The Battle for Wesnoth  1.17.21+dev
unit_preview_pane.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2023
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
20 
22 #include "gui/widgets/button.hpp"
23 #include "gui/widgets/drawing.hpp"
24 #include "gui/widgets/image.hpp"
25 #include "gui/widgets/label.hpp"
26 #include "gui/widgets/settings.hpp"
27 #include "gui/widgets/window.hpp"
30 
31 #include "font/text_formatting.hpp"
32 #include "formatter.hpp"
33 #include "formula/string_utils.hpp"
34 #include "language.hpp"
35 #include "preferences/game.hpp"
36 #include "gettext.hpp"
37 #include "help/help.hpp"
38 #include "help/help_impl.hpp"
39 #include "play_controller.hpp"
40 #include "resources.hpp"
41 #include "team.hpp"
42 #include "terrain/movement.hpp"
43 #include "terrain/type_data.hpp"
44 #include "units/attack_type.hpp"
45 #include "units/types.hpp"
46 #include "units/helper.hpp"
47 #include "units/unit.hpp"
48 
49 #include <functional>
50 
51 namespace gui2
52 {
53 
54 // ------------ WIDGET -----------{
55 
56 REGISTER_WIDGET(unit_preview_pane)
57 
58 unit_preview_pane::unit_preview_pane(const implementation::builder_unit_preview_pane& builder)
59  : container_base(builder, type())
60  , current_type_()
61  , icon_type_(nullptr)
62  , icon_race_(nullptr)
63  , icon_alignment_(nullptr)
64  , label_name_(nullptr)
65  , label_level_(nullptr)
66  , label_race_(nullptr)
67  , label_details_(nullptr)
68  , tree_details_(nullptr)
69  , button_profile_(nullptr)
70  , image_mods_()
71 {
72 }
73 
75 {
76  // Icons
77  icon_type_ = find_widget<drawing>(this, "type_image", false, false);
78  icon_race_ = find_widget<image>(this, "type_race", false, false);
79  icon_alignment_ = find_widget<image>(this, "type_alignment", false, false);
80 
81  // Labels
82  label_name_ = find_widget<label>(this, "type_name", false, false);
83  label_level_ = find_widget<label>(this, "type_level", false, false);
84  label_race_ = find_widget<label>(this, "type_race_label", false, false);
85  label_details_ = find_widget<styled_widget>(this, "type_details_minimal", false, false);
86 
87  tree_details_ = find_widget<tree_view>(this, "type_details", false, false);
88 
89  // Profile button
90  button_profile_ = find_widget<button>(this, "type_profile", false, false);
91 
92  if(button_profile_) {
95  }
96 }
97 
98 static inline tree_view_node& add_name_tree_node(tree_view_node& header_node, const std::string& type, const t_string& label, const t_string& tooltip = "")
99 {
100  /* Note: We have to pass data instead of just doing 'child_label.set_label(label)' below
101  * because the tree_view_node::add_child needs to have the correct size of the
102  * node child widgets for its internal size calculations.
103  * Same is true for 'use_markup'
104  */
105  auto& child_node = header_node.add_child(type, { { "name",{ { "label", label },{ "use_markup", "true" } } } });
106  auto& child_label = find_widget<styled_widget>(&child_node, "name", true);
107 
108  child_label.set_tooltip(tooltip);
109  return child_node;
110 }
111 
112 static inline std::string get_hp_tooltip(
113  const utils::string_map_res& res, const std::function<int(const std::string&, bool)>& get)
114 {
115  std::ostringstream tooltip;
116 
117  std::vector<std::string> resistances_table;
118 
119  bool att_def_diff = false;
120  for(const utils::string_map_res::value_type &resist : res) {
121  std::ostringstream line;
122  line << translation::dgettext("wesnoth", resist.first.c_str()) << ": ";
123 
124  // Some units have different resistances when attacking or defending.
125  const int res_att = 100 - get(resist.first, true);
126  const int res_def = 100 - get(resist.first, false);
127 
128  if(res_att == res_def) {
129  line << "<span color='" << unit_helper::resistance_color(res_def) << "'>\t" << utils::signed_percent(res_def) << "</span>";
130  } else {
131  line << "<span color='" << unit_helper::resistance_color(res_att) << "'>\t" << utils::signed_percent(res_att) << "</span>" << "/"
132  << "<span color='" << unit_helper::resistance_color(res_def) << "'>" << utils::signed_percent(res_def) << "</span>";
133  att_def_diff = true;
134  }
135 
136  resistances_table.push_back(line.str());
137  }
138 
139  tooltip << "<big>" << _("Resistances: ") << "</big>";
140  if(att_def_diff) {
141  tooltip << _("(Att / Def)");
142  }
143 
144  for(const std::string &line : resistances_table) {
145  tooltip << '\n' << font::unicode_bullet << " " << line;
146  }
147 
148  return tooltip.str();
149 }
150 
151 static inline std::string get_mp_tooltip(int total_movement, std::function<int (t_translation::terrain_code)> get)
152 {
153  std::set<terrain_movement> terrain_moves;
154  std::ostringstream tooltip;
155  tooltip << "<big>" << _("Movement Costs:") << "</big>";
156 
157  std::shared_ptr<terrain_type_data> tdata = help::load_terrain_types_data();
158 
159  if(!tdata) {
160  return "";
161  }
162 
165  continue;
166  }
167 
168  const terrain_type& info = tdata->get_terrain_info(terrain);
169  if(info.is_indivisible() && info.is_nonnull()) {
170  terrain_moves.emplace(info.name(), get(terrain));
171  }
172  }
173 
174  for(const terrain_movement& tm: terrain_moves)
175  {
176  tooltip << '\n' << font::unicode_bullet << " " << tm.name << ": ";
177 
178  // movement - range: 1 .. 5, movetype::UNREACHABLE=impassable
179  const bool cannot_move = tm.moves > total_movement; // cannot move in this terrain
180  double movement_red_to_green = 100.0 - 25.0 * tm.moves;
181 
182  // passing true to select the less saturated red-to-green scale
183  std::string color = game_config::red_to_green(movement_red_to_green, true).to_hex_string();
184 
185  tooltip << "<span color='" << color << "'>";
186 
187  // A 5 MP margin; if the movement costs go above the unit's max moves + 5, we replace it with dashes.
188  if(cannot_move && (tm.moves > total_movement + 5)) {
190  } else if (cannot_move) {
191  tooltip << "(" << tm.moves << ")";
192  } else {
193  tooltip << tm.moves;
194  }
195  if(tm.moves != 0) {
196  const int movement_hexes_per_turn = total_movement / tm.moves;
197  tooltip << " ";
198  for(int i = 0; i < movement_hexes_per_turn; ++i) {
199  // Unicode horizontal black hexagon and Unicode zero width space (to allow a line break)
200  tooltip << "\u2b23\u200b";
201  }
202  }
203 
204  tooltip << "</span>";
205  }
206 
207  return tooltip.str();
208 }
209 
210 /*
211  * Both unit and unit_type use the same format (vector of attack_types) for their
212  * attack data, meaning we can keep this as a helper function.
213  */
214 template<typename T>
216 {
217  if(attacks.empty()) {
218  return;
219  }
220 
221  auto& header_node = add_name_tree_node(
222  parent_node,
223  "header",
224  "<b>" + _("Attacks") + "</b>"
225  );
226 
227  for(const auto& a : attacks) {
228  const std::string range_png = std::string("icons/profiles/") + a.range() + "_attack.png~SCALE_INTO(16,16)";
229  const std::string type_png = std::string("icons/profiles/") + a.type() + ".png~SCALE_INTO(16,16)";
230  const bool range_png_exists = ::image::locator(range_png).file_exists();
231  const bool type_png_exists = ::image::locator(type_png).file_exists();
232 
233  const t_string& range = string_table["range_" + a.range()];
234  const t_string& type = string_table["type_" + a.type()];
235 
236  const std::string label = (formatter()
238  << a.damage() << font::weapon_numbers_sep << a.num_attacks()
239  << " " << a.name() << "</span>").str();
240 
241  auto& subsection = header_node.add_child(
242  "item_image",
243  {
244  { "image_range", { { "label", range_png } } },
245  { "image_type", { { "label", type_png } } },
246  { "name", { { "label", label }, { "use_markup", "true" } } },
247  }
248  );
249 
250  find_widget<styled_widget>(&subsection, "image_range", true).set_tooltip(range);
251  find_widget<styled_widget>(&subsection, "image_type", true).set_tooltip(type);
252 
253  if(!range_png_exists || !type_png_exists) {
255  subsection,
256  "item",
257  (formatter()
259  << range << font::weapon_details_sep
260  << type << "</span>"
261  ).str()
262  );
263  }
264 
265  for(const auto& pair : a.special_tooltips()) {
267  subsection,
268  "item",
269  (formatter() << font::span_color(font::weapon_details_color) << pair.first << "</span>").str(),
270  (formatter() << "<span size='x-large'>" << pair.first << "</span>" << "\n" << pair.second).str()
271  );
272  }
273  }
274 }
275 
277 {
278  // Sets the current type id for the profile button callback to use
280 
281  if(icon_type_) {
282  std::string mods;
283 
285  mods = "~RC(" + type.flag_rgb() + ">" +
287  + ")";
288  }
289 
290  mods += image_mods_;
291 
292  icon_type_->set_label((type.icon().empty() ? type.image() : type.icon()) + mods);
293  }
294 
295  if(label_name_) {
296  label_name_->set_label("<big>" + type.type_name() + "</big>");
298  }
299 
300  if(label_level_) {
301  std::string l_str = VGETTEXT("Lvl $lvl", {{"lvl", std::to_string(type.level())}});
302 
303  label_level_->set_label("<b>" + l_str + "</b>");
306  }
307 
308  if(label_race_) {
309  label_race_ ->set_label(type.race()->name(type.genders().front()));
310  }
311 
312  if(icon_race_) {
313  icon_race_->set_label(type.race()->get_icon_path_stem() + "_30.png");
314  }
315 
316  if(icon_alignment_) {
317  const std::string& alignment_name = unit_alignments::get_string(type.alignment());
318 
319  icon_alignment_->set_label("icons/alignments/alignment_" + alignment_name + "_30.png");
321  type.alignment(),
322  type.genders().front()));
323  }
324 
325  if(label_details_) {
326  std::stringstream str;
327 
328  str << "<span size='large'> </span>" << "\n";
329 
330  str << font::span_color(font::unit_type_color) << type.type_name() << "</span>" << "\n";
331 
332  std::string l_str = VGETTEXT("Lvl $lvl", {{"lvl", std::to_string(type.level())}});
333  str << l_str << "\n";
334 
335  str << unit_alignments::get_string(type.alignment()) << "\n";
336 
337  str << "\n"; // Leave a blank line where traits would be
338 
339  str << _("HP: ") << type.hitpoints() << "\n";
340 
341  str << _("XP: ") << type.experience_needed(true);
342 
343  label_details_->set_label(str.str());
345  }
346 
347  if(tree_details_) {
348 
349  tree_details_->clear();
350  tree_details_->add_node("hp_xp_mp", {
351  { "hp",{
352  { "label", (formatter() << "<small>" << font::span_color(unit::hp_color_max()) << "<b>" << _("HP: ") << "</b>" << type.hitpoints() << "</span>" << " | </small>").str() },
353  { "use_markup", "true" },
354  { "tooltip", get_hp_tooltip(type.movement_type().get_resistances().damage_table(), [&type](const std::string& dt, bool is_attacker) { return type.resistance_against(dt, is_attacker); }) }
355  } },
356  { "xp",{
357  { "label", (formatter() << "<small>" << font::span_color(unit::xp_color(100, type.can_advance(), true)) << "<b>" << _("XP: ") << "</b>" << type.experience_needed() << "</span>" << " | </small>").str() },
358  { "use_markup", "true" },
359  { "tooltip", (formatter() << _("Experience Modifier: ") << unit_experience_accelerator::get_acceleration() << '%').str() }
360  } },
361  { "mp",{
362  { "label", (formatter() << "<small>" << "<b>" << _("MP: ") << "</b>" << type.movement() << "</small>").str() },
363  { "use_markup", "true" },
364  { "tooltip", get_mp_tooltip(type.movement(), [&type](t_translation::terrain_code terrain) { return type.movement_type().movement_cost(terrain); }) }
365  } },
366  });
367 
368  // Print trait details
369  {
370  tree_view_node* header_node = nullptr;
371 
372  for(const auto& tr : type.possible_traits()) {
373  t_string name = tr[type.genders().front() == unit_race::FEMALE ? "female_name" : "male_name"];
374  if(tr["availability"] != "musthave" || name.empty()) {
375  continue;
376  }
377 
378  if(header_node == nullptr) {
379  header_node = &add_name_tree_node(
381  "header",
382  "<b>" + _("Traits") + "</b>"
383  );
384  }
385 
387  *header_node,
388  "item",
389  name
390  );
391  }
392  }
393 
394  // Print ability details
395  if(!type.abilities_metadata().empty()) {
396 
397  auto& header_node = add_name_tree_node(
399  "header",
400  "<b>" + _("Abilities") + "</b>"
401  );
402 
403  for(const auto& ab : type.abilities_metadata()) {
404  if(!ab.name.empty()) {
406  header_node,
407  "item",
408  ab.name,
409  (formatter() << "<span size='x-large'>" << ab.name << "</span>\n" << ab.description).str()
410  );
411  }
412  }
413  }
414 
416  }
417 }
418 
420 {
421  // Sets the current type id for the profile button callback to use
422  current_type_ = u.type();
423 
424  if(icon_type_) {
425  std::string mods = u.image_mods();
426 
427  if(u.can_recruit()) {
428  mods += "~BLIT(" + unit::leader_crown() + ")";
429  }
430 
431  for(const std::string& overlay : u.overlays()) {
432  mods += "~BLIT(" + overlay + ")";
433  }
434 
435  mods += image_mods_;
436 
437  icon_type_->set_label(u.absolute_image() + mods);
438  }
439 
440  if(label_name_) {
441  std::string name;
442  if(!u.name().empty()) {
443  name = "<span size='large'>" + u.name() + "</span>" + "\n" + "<small>" + font::span_color(font::unit_type_color) + u.type_name() + "</span></small>";
444  } else {
445  name = "<span size='large'>" + u.type_name() + "</span>\n";
446  }
447 
448  label_name_->set_label(name);
450  }
451 
452  if(label_level_) {
453  std::string l_str = VGETTEXT("Lvl $lvl", {{"lvl", std::to_string(u.level())}});
454 
455  label_level_->set_label("<b>" + l_str + "</b>");
458  }
459 
460  if(label_race_) {
461  label_race_->set_label(u.race()->name(u.gender()));
462  }
463 
464  if(icon_race_) {
465  icon_race_->set_label(u.race()->get_icon_path_stem() + "_30.png");
466  }
467 
468  if(icon_alignment_) {
469  const std::string& alignment_name = unit_alignments::get_string(u.alignment());
470 
471  icon_alignment_->set_label("icons/alignments/alignment_" + alignment_name + "_30.png");
473  u.alignment(),
474  u.gender()));
475  }
476 
477  if(label_details_) {
478  std::stringstream str;
479 
480  const std::string name = "<span size='large'>" + (!u.name().empty() ? u.name() : " ") + "</span>";
481  str << name << "\n";
482 
483  str << font::span_color(font::unit_type_color) << u.type_name() << "</span>" << "\n";
484 
485  std::string l_str = VGETTEXT("Lvl $lvl", {{"lvl", std::to_string(u.level())}});
486  str << l_str << "\n";
487 
488  str << unit_type::alignment_description(u.alignment(), u.gender()) << "\n";
489 
490  str << utils::join(u.trait_names(), ", ") << "\n";
491 
492  str << font::span_color(u.hp_color())
493  << _("HP: ") << u.hitpoints() << "/" << u.max_hitpoints() << "</span>" << "\n";
494 
495  str << font::span_color(u.xp_color()) << _("XP: ");
496  if(u.can_advance()) {
497  str << u.experience() << "/" << u.max_experience();
498  } else {
499  str << font::unicode_en_dash;
500  }
501  str << "</span>";
502 
503  label_details_->set_label(str.str());
505  }
506 
507  if(tree_details_) {
508  tree_details_->clear();
509  const std::string unit_xp = u.can_advance() ? (formatter() << u.experience() << "/" << u.max_experience()).str() : font::unicode_en_dash;
510  tree_details_->add_node("hp_xp_mp", {
511  { "hp",{
512  { "label", (formatter() << "<small>" << font::span_color(u.hp_color()) << "<b>" << _("HP: ") << "</b>" << u.hitpoints() << "/" << u.max_hitpoints() << "</span>" << " | </small>").str() },
513  { "use_markup", "true" },
514  { "tooltip", get_hp_tooltip(u.get_base_resistances(), [&u](const std::string& dt, bool is_attacker) { return u.resistance_against(dt, is_attacker, u.get_location()); }) }
515  } },
516  { "xp",{
517  { "label", (formatter() << "<small>" << font::span_color(u.xp_color()) << "<b>" << _("XP: ") << "</b>" << unit_xp << "</span>" << " | </small>").str() },
518  { "use_markup", "true" },
519  { "tooltip", (formatter() << _("Experience Modifier: ") << unit_experience_accelerator::get_acceleration() << '%').str() }
520  } },
521  { "mp",{
522  { "label", (formatter() << "<small>" << "<b>" << _("MP: ") << "</b>" << u.movement_left() << "/" << u.total_movement() << "</small>").str() },
523  { "use_markup", "true" },
524  { "tooltip", get_mp_tooltip(u.total_movement(), [&u](t_translation::terrain_code terrain) { return u.movement_cost(terrain); }) }
525  } },
526  });
527 
528  if(!u.trait_names().empty()) {
529  auto& header_node = add_name_tree_node(
531  "header",
532  "<b>" + _("Traits") + "</b>"
533  );
534 
535  assert(u.trait_names().size() == u.trait_descriptions().size());
536  for (std::size_t i = 0; i < u.trait_names().size(); ++i) {
538  header_node,
539  "item",
540  u.trait_names()[i],
541  u.trait_descriptions()[i]
542  );
543  }
544  }
545 
546  if(!u.get_ability_list().empty()) {
547  auto& header_node = add_name_tree_node(
549  "header",
550  "<b>" + _("Abilities") + "</b>"
551  );
552 
553  for(const auto& ab : u.ability_tooltips()) {
555  header_node,
556  "item",
557  std::get<2>(ab),
558  std::get<3>(ab)
559  );
560  }
561  }
563  }
564 }
565 
567 {
568  if(get_window() && current_type_) {
570  }
571 }
572 
573 void unit_preview_pane::set_image_mods(const std::string& mods)
574 {
575  image_mods_ = mods;
576 }
577 
578 void unit_preview_pane::set_active(const bool /*active*/)
579 {
580  /* DO NOTHING */
581 }
582 
584 {
585  return true;
586 }
587 
589 {
590  return ENABLED;
591 }
592 
593 void unit_preview_pane::set_self_active(const bool /*active*/)
594 {
595  /* DO NOTHING */
596 }
597 
598 // }---------- DEFINITION ---------{
599 
602 {
603  DBG_GUI_P << "Parsing unit preview pane " << id;
604 
605  load_resolutions<resolution>(cfg);
606 }
607 
609  : resolution_definition(cfg), grid()
610 {
611  state.emplace_back(VALIDATE_WML_CHILD(cfg, "background", _("Missing required background for unit preview pane")));
612  state.emplace_back(VALIDATE_WML_CHILD(cfg, "foreground", _("Missing required foreground for unit preview pane")));
613 
614  auto child = VALIDATE_WML_CHILD(cfg, "grid", _("Missing required grid for unit preview pane"));
615  grid = std::make_shared<builder_grid>(child);
616 }
617 
618 // }---------- BUILDER -----------{
619 
620 namespace implementation
621 {
622 
623 builder_unit_preview_pane::builder_unit_preview_pane(const config& cfg)
624  : builder_styled_widget(cfg)
625  , image_mods_(cfg["image_mods"])
626 {
627 }
628 
629 std::unique_ptr<widget> builder_unit_preview_pane::build() const
630 {
631  auto widget = std::make_unique<unit_preview_pane>(*this);
632 
633  DBG_GUI_G << "Window builder: placed unit preview pane '" << id
634  << "' with definition '" << definition << "'.";
635 
636  const auto conf = widget->cast_config_to<unit_preview_pane_definition>();
637  assert(conf);
638 
639  widget->init_grid(*conf->grid);
640  widget->finalize_setup();
641  widget->set_image_mods(image_mods_);
642 
643  return widget;
644 }
645 
646 } // namespace implementation
647 
648 // }------------ END --------------
649 
650 } // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:161
std::ostringstream wrapper.
Definition: formatter.hpp:40
A generic container base class.
Class to show the tips.
Definition: tooltip.cpp:58
Base container class.
Definition: grid.hpp:32
A label displays text that can be wrapped but no scrollbars are provided.
Definition: label.hpp:57
void set_tooltip(const t_string &tooltip)
virtual void set_label(const t_string &label)
virtual void set_use_markup(bool use_markup)
tree_view_node & add_child(const std::string &id, const widget_data &data, const int index=-1)
Constructs a new child node.
tree_view_node & get_root_node()
Definition: tree_view.hpp:75
tree_view_node & add_node(const std::string &id, const widget_data &data, const int index=-1)
Definition: tree_view.cpp:57
void profile_button_callback()
Callback for the profile button.
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
virtual void set_active(const bool active) override
See styled_widget::set_active.
styled_widget * label_details_
void set_displayed_unit(const unit &u)
Displays the stats of a specific unit.
virtual bool get_active() const override
See styled_widget::get_active.
void print_attack_details(T attacks, tree_view_node &parent_node)
void set_image_mods(const std::string &mods)
Sets the facing of the unit image.
virtual void set_self_active(const bool active) override
See container_base::set_self_active.
void set_displayed_type(const unit_type &type)
Displays the stats of a specified unit type.
virtual unsigned get_state() const override
See styled_widget::get_state.
utils::optional_reference< const unit_type > current_type_
void finalize_setup()
Initializes the internal sub-widget pointers.
Base class for all widgets.
Definition: widget.hpp:54
window * get_window()
Get the parent window.
Definition: widget.cpp:118
Generic locator abstracting the location of an image.
Definition: picture.hpp:64
bool file_exists() const
Tests whether the file the locator points at exists.
Definition: picture.cpp:577
bool empty() const
Definition: tstring.hpp:187
static std::string get_side_color_id(unsigned side)
Definition: team.cpp:972
std::string get_icon_path_stem() const
Gets this race's icon path without state/size suffix and extension.
Definition: race.cpp:168
const t_string & name(GENDER gender=MALE) const
Definition: race.hpp:37
@ FEMALE
Definition: race.hpp:27
A single unit type that the player may recruit.
Definition: types.hpp:46
static std::string alignment_description(unit_alignments::type align, unit_race::GENDER gender=unit_race::MALE)
Implementation detail of unit_type::alignment_description.
Definition: types.cpp:839
This class represents a single unit of a specific type.
Definition: unit.hpp:134
static const std::string & leader_crown()
The path to the leader crown overlay.
Definition: unit.cpp:1051
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
std::size_t i
Definition: function.cpp:968
static std::string _(const char *str)
Definition: gettext.hpp:93
std::vector< std::tuple< std::string, t_string, t_string, t_string > > ability_tooltips() const
Gets the names and descriptions of this unit's abilities.
Definition: abilities.cpp:326
std::vector< std::string > get_ability_list() const
Get a list of all abilities by ID.
Definition: abilities.cpp:269
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:506
unit_alignments::type alignment() const
The alignment of this unit.
Definition: unit.hpp:476
int level() const
The current level of this unit.
Definition: unit.hpp:560
const t_string & type_name() const
Gets the translatable name of this unit's type.
Definition: unit.hpp:370
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:500
const unit_race * race() const
Gets this unit's race.
Definition: unit.hpp:494
const unit_type & type() const
This unit's type, accounting for gender and variation.
Definition: unit.hpp:356
int experience() const
The current number of experience points this unit has.
Definition: unit.hpp:524
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
Definition: unit.hpp:613
int max_experience() const
The max number of experience points this unit can have.
Definition: unit.hpp:530
unit_race::GENDER gender() const
The gender of this unit.
Definition: unit.hpp:466
const t_string & name() const
Gets this unit's translatable display name.
Definition: unit.hpp:404
bool can_advance() const
Checks whether this unit has any options to advance to.
Definition: unit.hpp:273
attack_itors attacks()
Gets an iterator over this unit's attacks.
Definition: unit.hpp:928
utils::string_map_res get_base_resistances() const
Gets resistances without any abilities applied.
Definition: unit.hpp:1050
color_t xp_color() const
Color for this unit's XP.
Definition: unit.cpp:1153
color_t hp_color() const
Color for this unit's current hitpoints.
Definition: unit.cpp:1099
static color_t hp_color_max()
Definition: unit.cpp:1109
std::string image_mods() const
Gets an IPF string containing all IPF image mods.
Definition: unit.cpp:2754
const std::vector< std::string > & overlays() const
Get the unit's overlay images.
Definition: unit.hpp:1600
std::string absolute_image() const
The name of the file to game_display (used in menus).
Definition: unit.cpp:2573
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition: unit.hpp:1283
int total_movement() const
The maximum moves this unit has.
Definition: unit.hpp:1267
const std::vector< t_string > & trait_descriptions() const
Gets the descriptions of the currently registered traits.
Definition: unit.hpp:1094
const std::vector< t_string > & trait_names() const
Gets the names of the currently registered traits.
Definition: unit.hpp:1084
#define DBG_GUI_G
Definition: log.hpp:41
#define DBG_GUI_P
Definition: log.hpp:66
std::string tooltip
Shown when hovering over an entry in the filter's drop-down list.
Definition: manager.cpp:219
This file contains the window object, this object is a top level container which has the event manage...
symbol_table string_table
Definition: language.cpp:65
CURSOR_TYPE get()
Definition: cursor.cpp:216
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:171
const std::string weapon_details_sep
Definition: constants.cpp:50
const color_t unit_type_color
const std::string unicode_bullet
Definition: constants.cpp:47
const color_t weapon_details_color
const std::string unicode_en_dash
Definition: constants.cpp:43
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
const std::string unicode_figure_dash
Definition: constants.cpp:45
const std::string weapon_numbers_sep
Definition: constants.cpp:49
color_t red_to_green(double val, bool for_text)
Return a color corresponding to the value val red for val=0.0 to green for val=100....
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:179
Generic file dialog.
static tree_view_node & add_name_tree_node(tree_view_node &header_node, const std::string &type, const t_string &label, const t_string &tooltip="")
static std::string get_mp_tooltip(int total_movement, std::function< int(t_translation::terrain_code)> get)
static std::string get_hp_tooltip(const utils::string_map_res &res, const std::function< int(const std::string &, bool)> &get)
std::shared_ptr< terrain_type_data > load_terrain_types_data()
Load the appropriate terrain types data to use.
Definition: help_impl.cpp:1696
void show_unit_description(const unit &u)
Definition: help.cpp:75
Contains the implementation details for lexical_cast and shouldn't be used directly.
logger & info()
Definition: log.cpp:238
std::set< t_translation::terrain_code > & encountered_terrains()
Definition: game.cpp:921
play_controller * controller
Definition: resources.cpp:22
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
bool terrain_matches(const terrain_code &src, const terrain_code &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
const ter_match ALL_OFF_MAP
const terrain_code FOGGED
std::string dgettext(const char *domain, const char *msgid)
Definition: gettext.cpp:427
static std::string unit_level_tooltip(const int level, const std::vector< std::string > &adv_to_types, const std::vector< config > &adv_to_mods)
Definition: helper.cpp:56
std::string resistance_color(const int resistance)
Maps resistance <= -60 (resistance value <= -60%) to intense red.
Definition: helper.cpp:50
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
std::map< std::string, t_string, res_compare > string_map_res
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::string signed_percent(int val)
Convert into a percentage (using the Unicode "−" and +0% convention.
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
static config unit_xp(const unit *u)
Definition: reports.cpp:530
This file contains the settings handling of the widget library.
std::string to_hex_string() const
Returns the stored color in rrggbb hex format.
Definition: color.cpp:78
std::string definition
Parameters for the styled_widget.
virtual std::unique_ptr< widget > build() const override
Base class of a resolution, contains the common keys for a resolution.
std::vector< state_definition > state
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
Definition: enum_base.hpp:46
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
static int get_acceleration()
Definition: types.cpp:572
#define VALIDATE_WML_CHILD(cfg, key, message)
#define a