16 #define GETTEXT_DOMAIN "wesnoth-lib"
51 , attacker_data_(attacker, bc.get_attacker_combatant(), bc.get_attacker_stats())
52 , defender_data_(defender, bc.get_defender_combatant(), bc.get_defender_stats())
64 std::ostringstream ss;
69 ss << std::fixed << std::setprecision(1) << 100.0 * prob <<
'%';
78 const std::string widget_id_prefix = attacker.
stats_.
is_attacker ?
"attacker" :
"defender";
80 const auto get_prefixed_widget_id = [&widget_id_prefix](
const std::string&
id) {
81 return (
formatter() << widget_id_prefix <<
"_" <<
id).str();
85 const auto set_label_helper = [&](
const std::string&
id,
const std::string& value) {
86 find_widget<label>(&
window, get_prefixed_widget_id(
id),
false).set_label(value);
89 const auto hide_label_helper = [&](
const std::string&
id) {
104 set_label_helper(
"chance_unscathed", ss.str());
107 drawing& graph_widget = find_widget<drawing>(&
window, get_prefixed_widget_id(
"hp_graph"),
false);
115 set_label_helper(
"base_damage",
_(
"No usable weapon"));
118 hide_label_helper(
"tod_modifier");
119 hide_label_helper(
"leadership_modifier");
120 hide_label_helper(
"slowed_modifier");
130 utils::optional<decltype(ctx)> opp_ctx;
141 auto set_dmg_effect = std::find_if(dmg_effect.
begin(), dmg_effect.
end(),
146 if(set_dmg_effect == dmg_effect.
end()) {
147 ss << weapon->damage() <<
" (<i>" << weapon->name() <<
"</i>)";
149 assert(set_dmg_effect->ability);
150 ss << set_dmg_effect->value <<
" (<i>" << (*set_dmg_effect->ability)[
"name"] <<
"</i>)";
154 for(
const auto&
e : dmg_effect) {
163 ss <<
" (<i>" << (*
e.ability)[
"name"] <<
"</i>)";
168 for(
const auto&
e : dmg_effect) {
174 ss <<
"." << ((
e.value % 100) / 10);
176 ss << (
e.value % 10);
180 ss <<
" (<i>" << (*
e.ability)[
"name"] <<
"</i>)";
184 set_label_helper(
"base_damage", ss.str());
189 const int resistance_modifier = defender.
unit_->damage_from(*weapon, !attacker.
stats_.
is_attacker, defender.
unit_->get_location(), opp_weapon);
190 if(resistance_modifier != 100) {
192 if(resistance_modifier < 100) {
193 ss <<
_(
"Defender resistance vs") <<
" ";
195 ss <<
_(
"Defender vulnerability vs") <<
" ";
198 if(resistance_modifier < 100) {
199 ss <<
_(
"Attacker resistance vs") <<
" ";
201 ss <<
_(
"Attacker vulnerability vs") <<
" ";
205 std::pair<std::string, std::string> types = weapon->damage_type();
206 std::string type_bis = types.second;
207 if (!type_bis.empty()) {
212 set_label_helper(
"resis_label", ss.str());
217 set_label_helper(
"resis", ss.str());
230 if(tod_modifier != 0) {
233 hide_label_helper(
"tod_modifier");
239 if(leadership_bonus != 0) {
242 hide_label_helper(
"leadership_modifier");
247 set_label_helper(
"slowed_modifier",
"/ 2");
249 hide_label_helper(
"slowed_modifier");
253 const int base_damage = weapon->damage();
265 set_label_helper(
"total_damage", ss.str());
273 set_label_helper(
"chance_to_hit", ss.str());
283 const int hp_sep = 30;
286 const int percent_sep = 50;
289 const int bar_space =
graph_width - hp_sep - percent_sep - 4;
305 auto [hp, prob] = probability;
311 row_color = {229, 0, 0};
315 else if(hp <
static_cast<int>(attacker.
stats_.
hp)) {
318 row_color = {154, 154, 154};
320 row_color = {244, 201, 0};
326 row_color = {8, 202, 0};
331 shape[
"y"] = 2 + (
fs + 2) *
i;
332 shape[
"w"] =
"(text_width)";
333 shape[
"h"] =
"(text_height)";
334 shape[
"font_size"] = 12;
335 shape[
"color"] =
"255, 255, 255, 255";
336 shape[
"text_alignment"] =
"(text_alignment)";
343 shape[
"y"] = 2 + (
fs + 2) *
i;
344 shape[
"w"] =
"(text_width)";
345 shape[
"h"] =
"(text_height)";
346 shape[
"font_size"] = 12;
347 shape[
"color"] =
"255, 255, 255, 255";
348 shape[
"text_alignment"] =
"(text_alignment)";
352 const int bar_len = std::max(
static_cast<int>((prob * (bar_space - 4)) + 0.5), 2);
354 const SDL_Rect bar_rect_1 {
362 shape[
"x"] = bar_rect_1.x;
363 shape[
"y"] = bar_rect_1.y;
364 shape[
"w"] = bar_rect_1.w;
365 shape[
"h"] = bar_rect_1.h;
381 for(
int i = 0; i < static_cast<int>(hp_dist.size()); ++
i) {
382 const double prob = hp_dist[
i];
386 temp_vec.emplace_back(
i, prob);
391 std::sort(temp_vec.begin(), temp_vec.end(), [](
const auto& pair1,
const auto& pair2) {
392 return pair1.second > pair2.second;
396 std::copy_n(temp_vec.begin(), std::min<int>(
graph_max_rows, temp_vec.size()), std::back_inserter(res));
399 std::sort(res.begin(), res.end(), [](
const auto& pair1,
const auto& pair2) {
400 return pair1.first > pair2.first;
int under_leadership(const unit &u, const map_location &loc, const_attack_ptr weapon, const_attack_ptr opp_weapon)
Tests if the unit at loc is currently affected by leadership.
int combat_modifier(const unit_map &units, const gamemap &map, const map_location &loc, unit_alignments::type alignment, bool is_fearless)
Returns the amount that a unit's damage should be multiplied by due to the current time of day.
Computes the statistics of a battle between an attacker and a defender unit.
A config object defines a single node in a WML file, with access to child nodes.
config & add_child(config_key_type key)
A simple canvas which can be drawn upon.
void set_variable(const std::string &key, wfl::variant &&value)
void draw_hp_graph(drawing &hp_graph, const combatant_data &attacker, const combatant_data &defender) const
static const unsigned int graph_width
attack_predictions(battle_context &bc, unit_const_ptr attacker, unit_const_ptr defender)
void set_data(window &window, const combatant_data &attacker, const combatant_data &defender) const
static const unsigned int graph_height
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
static const unsigned int graph_max_rows
combatant_data attacker_data_
hp_probability_vector get_hitpoint_probabilities(const std::vector< double > &hp_dist) const
combatant_data defender_data_
Abstract base class for all modal dialogs.
void append_drawing_data(const ::config &cfg)
canvas & get_drawing_canvas()
base class of top level items, the only item which needs to store the final canvases to draw on.
const_iterator end() const
const_iterator begin() const
This class represents a single unit of a specific type.
Definitions for the interface to Wesnoth Markup Language (WML).
static std::string _(const char *str)
unit_alignments::type alignment() const
The alignment of this unit.
const map_location & get_location() const
The current map location this unit is at.
bool is_fearless() const
Gets whether this unit is fearless - ie, unaffected by time of day.
symbol_table string_table
const std::string unicode_multiplication_sign
const color_t good_dmg_color
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
const color_t weapon_color
const std::string weapon_numbers_sep
const color_t bad_dmg_color
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....
REGISTER_DIALOG(editor_edit_unit)
static std::string get_probability_string(const double prob)
std::vector< std::pair< int, double > > hp_probability_vector
std::string signed_percent(int val)
Convert into a percentage (using the Unicode "−" and +0% convention.
std::shared_ptr< const unit > unit_const_ptr
std::shared_ptr< const attack_type > const_attack_ptr
unsigned int num_blows
Effective number of blows, takes swarm into account.
bool petrifies
Attack petrifies opponent when it hits.
unsigned int hp
Hitpoints of the unit at the beginning of the battle.
bool is_attacker
True if the unit is the attacker.
const_attack_ptr weapon
The weapon used by the unit to attack the opponent, or nullptr if there is none.
bool is_slowed
True if the unit is slowed at the beginning of the battle.
int damage
Effective damage of the weapon (all factors accounted for).
unsigned int chance_to_hit
Effective chance to hit as a percentage (all factors accounted for).
The basic class for representing 8-bit RGB or RGBA colour values.
std::string to_rgba_string() const
Returns the stored color as an "R,G,B,A" string.
std::vector< double > hp_dist
Resulting probability distribution (might be not as large as max_hp)
double untouched
Resulting chance we were not hit by this opponent (important if it poisons)
const battle_context_unit_stats & stats_
unit_const_ptr unit_
never null
const combatant & combatant_