attack_prediction_display.cpp

Go to the documentation of this file.
00001 /* $Id: attack_prediction_display.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2006 - 2012 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
00004    wesnoth playturn Copyright (C) 2003 by David White <dave@whitevine.net>
00005    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY.
00013 
00014    See the COPYING file for more details.
00015 */
00016 
00017 #include "attack_prediction_display.hpp"
00018 
00019 #include "attack_prediction.hpp"
00020 #include "gettext.hpp"
00021 #include "game_display.hpp"
00022 #include "language.hpp"
00023 #include "marked-up_text.hpp"
00024 #include "resources.hpp"
00025 #include "unit_abilities.hpp"
00026 
00027 // Conversion routine for both unscathed and damage change percentage.
00028 static void format_prob(char str_buf[10], double prob)
00029 {
00030 
00031     if(prob > 0.9995) {
00032         snprintf(str_buf, 10, "100 %%");
00033     } else if(prob >= 0.1) {
00034         snprintf(str_buf, 10, "%4.1f %%", 100.0 * prob);
00035     } else {
00036         snprintf(str_buf, 10, " %3.1f %%", 100.0 * prob);
00037     }
00038 
00039     str_buf[9] = '\0';  //prevents _snprintf error
00040 }
00041 
00042 
00043 const int battle_prediction_pane::inter_line_gap_ = 3;
00044 const int battle_prediction_pane::inter_column_gap_ = 30;
00045 const int battle_prediction_pane::inter_units_gap_ = 30;
00046 const int battle_prediction_pane::max_hp_distrib_rows_ = 10;
00047 
00048 battle_prediction_pane::battle_prediction_pane(const battle_context &bc,
00049         const map_location &attacker_loc, const map_location &defender_loc) :
00050     gui::preview_pane(resources::screen->video()),
00051     bc_(bc),
00052     attacker_loc_(attacker_loc),
00053     defender_loc_(defender_loc),
00054     attacker_(*resources::units->find(attacker_loc)),
00055     defender_(*resources::units->find(defender_loc)),
00056     attacker_label_(),
00057     defender_label_(),
00058     attacker_label_width_(0),
00059     defender_label_width_(0),
00060     attacker_left_strings_(),
00061     attacker_right_strings_(),
00062     defender_left_strings_(),
00063     defender_right_strings_(),
00064     attacker_strings_width_(0),
00065     attacker_left_strings_width_(0),
00066     attacker_right_strings_width_(0),
00067     defender_strings_width_(0),
00068     defender_left_strings_width_(0),
00069     defender_right_strings_width_(0),
00070     units_strings_height_(0),
00071     hp_distrib_string_(),
00072     attacker_hp_distrib_(),
00073     defender_hp_distrib_(),
00074     hp_distrib_string_width_(0),
00075     attacker_hp_distrib_width_(0),
00076     defender_hp_distrib_width_(0),
00077     attacker_hp_distrib_height_(0),
00078     defender_hp_distrib_height_(0),
00079     hp_distribs_height_(0),
00080     attacker_width_(0),
00081     defender_width_(0),
00082     units_width_(0),
00083     dialog_width_(0),
00084     dialog_height_(0)
00085 {
00086     // Predict the battle outcome.
00087     combatant attacker_combatant(bc.get_attacker_stats());
00088     combatant defender_combatant(bc.get_defender_stats());
00089     attacker_combatant.fight(defender_combatant);
00090 
00091     const battle_context_unit_stats& attacker_stats = bc.get_attacker_stats();
00092     const battle_context_unit_stats& defender_stats = bc.get_defender_stats();
00093 
00094     // Create the hitpoints distribution graphics.
00095     std::vector<std::pair<int, double> > hp_prob_vector;
00096     get_hp_prob_vector(attacker_combatant.hp_dist, hp_prob_vector);
00097     get_hp_distrib_surface(hp_prob_vector, attacker_stats, defender_stats, attacker_hp_distrib_,
00098                            attacker_hp_distrib_width_, attacker_hp_distrib_height_);
00099     get_hp_prob_vector(defender_combatant.hp_dist, hp_prob_vector);
00100     get_hp_distrib_surface(hp_prob_vector, defender_stats, attacker_stats, defender_hp_distrib_,
00101                        defender_hp_distrib_width_, defender_hp_distrib_height_);
00102     hp_distribs_height_ = std::max<int>(attacker_hp_distrib_height_, defender_hp_distrib_height_);
00103 
00104     // Build the strings and compute the layout.
00105     attacker_label_ = _("Attacker");
00106     defender_label_ = _("Defender");
00107     attacker_label_width_ = font::line_width(attacker_label_, font::SIZE_PLUS, TTF_STYLE_BOLD);
00108     defender_label_width_ = font::line_width(defender_label_, font::SIZE_PLUS, TTF_STYLE_BOLD);
00109 
00110     // Get the units strings.
00111     get_unit_strings(attacker_stats, attacker_, attacker_loc_, static_cast<float>(attacker_combatant.untouched),
00112                      defender_, defender_loc_, defender_stats.weapon,
00113                      attacker_left_strings_, attacker_right_strings_,
00114                      attacker_left_strings_width_, attacker_right_strings_width_, attacker_strings_width_);
00115 
00116     get_unit_strings(defender_stats, defender_, defender_loc_, static_cast<float>(defender_combatant.untouched),
00117                      attacker_, attacker_loc_, attacker_stats.weapon,
00118                      defender_left_strings_, defender_right_strings_,
00119                      defender_left_strings_width_, defender_right_strings_width_, defender_strings_width_);
00120 
00121     units_strings_height_ = std::max<int>(attacker_left_strings_.size(), defender_left_strings_.size())
00122                             * (font::SIZE_NORMAL + inter_line_gap_) + 14;
00123 
00124     hp_distrib_string_ = _("Expected Battle Result (HP)");
00125     hp_distrib_string_width_ = font::line_width(hp_distrib_string_, font::SIZE_SMALL);
00126 
00127     attacker_width_ = std::max<int>(attacker_label_width_, attacker_strings_width_);
00128     attacker_width_ = std::max<int>(attacker_width_, hp_distrib_string_width_);
00129     attacker_width_ = std::max<int>(attacker_width_, attacker_hp_distrib_width_);
00130     defender_width_ = std::max<int>(defender_label_width_, defender_strings_width_);
00131     defender_width_ = std::max<int>(defender_width_, hp_distrib_string_width_);
00132     defender_width_ = std::max<int>(defender_width_, defender_hp_distrib_width_);
00133     units_width_ = std::max<int>(attacker_width_, defender_width_);
00134 
00135     dialog_width_ = 2 * units_width_ + inter_units_gap_;
00136     dialog_height_ = 15 + 24 + units_strings_height_ + 14 + 19 + hp_distribs_height_ + 18;
00137 
00138     // Set the dialog size.
00139     set_measurements(dialog_width_, dialog_height_);
00140 }
00141 
00142 void battle_prediction_pane::get_unit_strings(const battle_context_unit_stats& stats,
00143                                           const unit& u, const map_location& u_loc, float u_unscathed,
00144                                           const unit& opp, const map_location& opp_loc, const attack_type *opp_weapon,
00145                                               std::vector<std::string>& left_strings, std::vector<std::string>& right_strings,
00146                                           int& left_strings_width, int& right_strings_width, int& strings_width)
00147 {
00148     std::stringstream str;
00149     char str_buf[10];
00150 
00151     // With a weapon.
00152     if(stats.weapon != NULL) {
00153 
00154         // Set specials context (for safety, it should not have changed normally).
00155         const attack_type *weapon = stats.weapon;
00156         weapon->set_specials_context(u_loc, opp_loc, *resources::units, stats.is_attacker, opp_weapon);
00157 
00158         // Get damage modifiers.
00159         unit_ability_list dmg_specials = weapon->get_specials("damage");
00160         unit_abilities::effect dmg_effect(dmg_specials, weapon->damage(), stats.backstab_pos);
00161 
00162         // Get the SET damage modifier, if any.
00163         const unit_abilities::individual_effect *set_dmg_effect = NULL;
00164         unit_abilities::effect_list::const_iterator i;
00165         for(i = dmg_effect.begin(); i != dmg_effect.end(); ++i) {
00166             if(i->type == unit_abilities::SET) {
00167                 set_dmg_effect = &*i;
00168                 break;
00169             }
00170         }
00171 
00172         // Either user the SET modifier or the base weapon damage.
00173         if(set_dmg_effect == NULL) {
00174             left_strings.push_back(weapon->name());
00175             str.str("");
00176             str << weapon->damage();
00177             right_strings.push_back(str.str());
00178         } else {
00179             assert(set_dmg_effect->ability);
00180 
00181             left_strings.push_back((*set_dmg_effect->ability)["name"]);
00182             str.str("");
00183             str << set_dmg_effect->value;
00184             right_strings.push_back(str.str());
00185         }
00186 
00187         // Process the ADD damage modifiers.
00188         for(i = dmg_effect.begin(); i != dmg_effect.end(); ++i) {
00189             if(i->type == unit_abilities::ADD) {
00190                 left_strings.push_back((*i->ability)["name"]);
00191                 str.str("");
00192                 if(i->value >= 0) str << "+" << i->value;
00193                 else str << i->value;
00194                 right_strings.push_back(str.str());
00195             }
00196         }
00197 
00198         // Process the MUL damage modifiers.
00199         for(i = dmg_effect.begin(); i != dmg_effect.end(); ++i) {
00200             if(i->type == unit_abilities::MUL) {
00201                 left_strings.push_back((*i->ability)["name"]);
00202                 str.str("");
00203                 str << "* " << (i->value / 100);
00204                 if(i->value % 100) {
00205                     str << "." << ((i->value % 100) / 10);
00206                     if(i->value % 10) str << (i->value % 10);
00207                 }
00208                 right_strings.push_back(str.str());
00209             }
00210         }
00211 
00212         // Time of day modifier.
00213         int tod_modifier = combat_modifier(u_loc, u.alignment(), u.is_fearless());
00214         if(tod_modifier != 0) {
00215             left_strings.push_back(_("Time of day"));
00216             str.str("");
00217             str << utils::signed_percent(tod_modifier);
00218             right_strings.push_back(str.str());
00219         }
00220 
00221         // Leadership bonus.
00222         int leadership_bonus = 0;
00223         under_leadership(*resources::units, u_loc, &leadership_bonus);
00224         if(leadership_bonus != 0) {
00225             left_strings.push_back(_("Leadership"));
00226             str.str("");
00227             str << utils::signed_percent(leadership_bonus);
00228             right_strings.push_back(str.str());
00229         }
00230 
00231 
00232         // Resistance modifier.
00233         int resistance_modifier = opp.damage_from(*weapon, !stats.is_attacker, opp_loc);
00234         if(resistance_modifier != 100) {
00235             str.str("");
00236             if(stats.is_attacker) str << _("Defender");
00237             else str << _("Attacker");
00238             if(resistance_modifier < 100) str << _(" resistance vs ");
00239             else str << _(" vulnerability vs ");
00240             str << string_table["type_" + weapon->type()];
00241             left_strings.push_back(str.str());
00242             str.str("");
00243             str << "* " << (resistance_modifier / 100) << "." << ((resistance_modifier % 100) / 10);
00244             right_strings.push_back(str.str());
00245         }
00246 
00247         // Slowed penalty.
00248         if(stats.is_slowed) {
00249             left_strings.push_back(_("Slowed"));
00250             right_strings.push_back("/ 2");
00251         }
00252 
00253         // Total damage.
00254         left_strings.push_back(_("Total damage"));
00255         str.str("");
00256         str << stats.damage << utils::unicode_en_dash << stats.num_blows << " (" << stats.chance_to_hit << "%)";
00257         right_strings.push_back(str.str());
00258 
00259     // Without a weapon.
00260     } else {
00261         left_strings.push_back(_("No usable weapon"));
00262         right_strings.push_back("");
00263     }
00264 
00265     // Unscathed probability.
00266     left_strings.push_back(_("Chance of being unscathed"));
00267     format_prob(str_buf, u_unscathed);
00268     right_strings.push_back(str_buf);
00269 
00270 #if 0 // might not be en English!
00271     // Fix capitalization of left strings.
00272     for(int i = 0; i < (int) left_strings.size(); i++)
00273         if(left_strings[i].size() > 0) left_strings[i][0] = toupper(left_strings[i][0]);
00274 #endif
00275 
00276     // Compute the width of the strings.
00277     left_strings_width = get_strings_max_length(left_strings);
00278     right_strings_width = get_strings_max_length(right_strings);
00279     strings_width = left_strings_width + inter_column_gap_ + right_strings_width;
00280 }
00281 
00282 int battle_prediction_pane::get_strings_max_length(const std::vector<std::string>& strings)
00283 {
00284     int max_len = 0;
00285 
00286     for(int i = 0; i < static_cast<int>(strings.size()); i++)
00287         max_len = std::max<int>(font::line_width(strings[i], font::SIZE_NORMAL), max_len);
00288 
00289     return max_len;
00290 }
00291 
00292 void battle_prediction_pane::get_hp_prob_vector(const std::vector<double>& hp_dist,
00293                                                 std::vector<std::pair<int, double> >& hp_prob_vector)
00294 {
00295     hp_prob_vector.clear();
00296 
00297     // First, we sort the probabilities in ascending order.
00298     std::vector<std::pair<double, int> > prob_hp_vector;
00299     int i;
00300 
00301     for(i = 0; i < static_cast<int>(hp_dist.size()); i++) {
00302         double prob = hp_dist[i];
00303 
00304         // We keep only values above 0.1%.
00305         if(prob > 0.001)
00306             prob_hp_vector.push_back(std::pair<double, int>(prob, i));
00307     }
00308 
00309     std::sort(prob_hp_vector.begin(), prob_hp_vector.end());
00310 
00311     // We store a few of the highest probability hitpoint values.
00312     int nb_elem = std::min<int>(max_hp_distrib_rows_, prob_hp_vector.size());
00313 
00314     for(i = prob_hp_vector.size() - nb_elem;
00315             i < static_cast<int>(prob_hp_vector.size()); i++) {
00316 
00317         hp_prob_vector.push_back(std::pair<int, double>
00318             (prob_hp_vector[i].second, prob_hp_vector[i].first));
00319         }
00320 
00321     // Then, we sort the hitpoint values in ascending order.
00322     std::sort(hp_prob_vector.begin(), hp_prob_vector.end());
00323 }
00324 
00325 void battle_prediction_pane::draw_contents()
00326 {
00327     // We must align both damage lines.
00328     int damage_line_skip = std::max<int>(attacker_left_strings_.size(), defender_left_strings_.size()) - 2;
00329 
00330     draw_unit(0, damage_line_skip,
00331               attacker_left_strings_width_, attacker_left_strings_, attacker_right_strings_,
00332               attacker_label_, attacker_label_width_, attacker_hp_distrib_, attacker_hp_distrib_width_);
00333 
00334     draw_unit(units_width_ + inter_units_gap_, damage_line_skip,
00335               defender_left_strings_width_, defender_left_strings_, defender_right_strings_,
00336               defender_label_, defender_label_width_, defender_hp_distrib_, defender_hp_distrib_width_);
00337 }
00338 
00339 void battle_prediction_pane::draw_unit(int x_off, int damage_line_skip, int left_strings_width,
00340                                        const std::vector<std::string>& left_strings,
00341                                        const std::vector<std::string>& right_strings,
00342                                        const std::string& label, int label_width,
00343                                        surface& hp_distrib, int hp_distrib_width)
00344 {
00345     surface screen = resources::screen->get_screen_surface();
00346     int i;
00347 
00348     // NOTE. A preview pane is not made to be used alone and it is not
00349     // centered in the middle of the dialog. We "fix" this problem by moving
00350     // the clip rectangle 10 pixels to the right. This is a kludge and it
00351     // should be removed by 1) writing a custom dialog handler, or
00352     // 2) modify preview_pane so that it accepts {left, middle, right} as
00353     // layout possibilities.
00354 
00355     // Get clip rectangle and center it
00356     SDL_Rect clip_rect = location();
00357     clip_rect.x += 10;
00358 
00359     // Current vertical offset. We draw the dialog line-by-line, starting at the top.
00360     int y_off = 15;
00361 
00362     // Draw unit label.
00363     font::draw_text_line(screen, clip_rect, font::SIZE_15, font::NORMAL_COLOR, label,
00364                          clip_rect.x + x_off + (units_width_ - label_width) / 2, clip_rect.y + y_off, 0, TTF_STYLE_BOLD);
00365 
00366     y_off += 24;
00367 
00368     // Draw unit left and right strings except the last two (total damage and unscathed probability).
00369     for(i = 0; i < static_cast<int>(left_strings.size()) - 2; i++) {
00370         font::draw_text_line(screen, clip_rect, font::SIZE_NORMAL, font::NORMAL_COLOR, left_strings[i],
00371                              clip_rect.x + x_off, clip_rect.y + y_off + (font::SIZE_NORMAL + inter_line_gap_) * i,
00372                              0, TTF_STYLE_NORMAL);
00373 
00374         font::draw_text_line(screen, clip_rect, font::SIZE_NORMAL, font::NORMAL_COLOR, right_strings[i],
00375                              clip_rect.x + x_off + left_strings_width + inter_column_gap_,
00376                              clip_rect.y + y_off + (font::SIZE_NORMAL + inter_line_gap_) * i, 0, TTF_STYLE_NORMAL);
00377     }
00378 
00379     // Ensure both damage lines are aligned.
00380     y_off += damage_line_skip * (font::SIZE_NORMAL + inter_line_gap_) + 14;
00381 
00382     // Draw total damage and unscathed probability.
00383     for(i = 0; i < 2; i++) {
00384         const std::string& left_string = left_strings[left_strings.size() - 2 + i];
00385         const std::string& right_string = right_strings[right_strings.size() - 2 + i];
00386 
00387         font::draw_text_line(screen, clip_rect, font::SIZE_NORMAL, font::NORMAL_COLOR, left_string,
00388                              clip_rect.x + x_off, clip_rect.y + y_off + (font::SIZE_NORMAL + inter_line_gap_) * i,
00389                              0, TTF_STYLE_NORMAL);
00390 
00391         font::draw_text_line(screen, clip_rect, font::SIZE_NORMAL, font::NORMAL_COLOR, right_string,
00392                              clip_rect.x + x_off + left_strings_width + inter_column_gap_,
00393                              clip_rect.y + y_off + (font::SIZE_NORMAL + inter_line_gap_) * i, 0, TTF_STYLE_NORMAL);
00394     }
00395 
00396     y_off += 2 * (font::SIZE_NORMAL + inter_line_gap_) + 14;
00397 
00398     // Draw hitpoints distribution string.
00399     font::draw_text(screen, clip_rect, font::SIZE_SMALL, font::NORMAL_COLOR, hp_distrib_string_,
00400                     clip_rect.x + x_off + (units_width_ - hp_distrib_string_width_) / 2, clip_rect.y + y_off);
00401 
00402     y_off += 19;
00403 
00404     // Draw hitpoints distributions.
00405     video().blit_surface(clip_rect.x + x_off + (units_width_ - hp_distrib_width) / 2, clip_rect.y + y_off, hp_distrib);
00406 }
00407 
00408 void battle_prediction_pane::get_hp_distrib_surface(const std::vector<std::pair<int, double> >& hp_prob_vector,
00409                                                     const battle_context_unit_stats& stats,
00410                                                     const battle_context_unit_stats& opp_stats,
00411                                                     surface& surf, int& width, int& height)
00412 {
00413     // Font size. If you change this, you must update the separator space.
00414     int fs = font::SIZE_SMALL;
00415 
00416     // Space before HP separator.
00417     int hp_sep = 24 + 6;
00418 
00419     // Bar space between both separators.
00420     int bar_space = 150;
00421 
00422     // Space after percentage separator.
00423     int percent_sep = 43 + 6;
00424 
00425     // Surface width and height.
00426     width = 30 + 2 + bar_space + 2 + percent_sep;
00427     height = 5 + (fs + 2) * hp_prob_vector.size();
00428 
00429     // Create the surface.
00430     surf = create_neutral_surface(width, height);
00431 
00432     // Dsiable alpha channel to avoid problem with sdl_blit
00433     SDL_SetAlpha(surf, 0, SDL_ALPHA_OPAQUE);
00434 
00435     SDL_Rect clip_rect = create_rect(0, 0, width, height);
00436     Uint32 grey_color = SDL_MapRGBA(surf->format, 0xb7, 0xc1, 0xc1, 255);
00437 
00438     Uint32 background_color = SDL_MapRGBA(surf->format, 25, 25, 25, 255);
00439     sdl_fill_rect(surf, &clip_rect, background_color);
00440 
00441     // Draw the surrounding borders and separators.
00442     SDL_Rect top_border_rect = create_rect(0, 0, width, 2);
00443     sdl_fill_rect(surf, &top_border_rect, grey_color);
00444 
00445     SDL_Rect bottom_border_rect = create_rect(0, height - 2, width, 2);
00446     sdl_fill_rect(surf, &bottom_border_rect, grey_color);
00447 
00448     SDL_Rect left_border_rect = create_rect(0, 0, 2, height);
00449     sdl_fill_rect(surf, &left_border_rect, grey_color);
00450 
00451     SDL_Rect right_border_rect = create_rect(width - 2, 0, 2, height);
00452     sdl_fill_rect(surf, &right_border_rect, grey_color);
00453 
00454     SDL_Rect hp_sep_rect = create_rect(hp_sep, 0, 2, height);
00455     sdl_fill_rect(surf, &hp_sep_rect, grey_color);
00456 
00457     SDL_Rect percent_sep_rect = create_rect(width - percent_sep - 2, 0, 2, height);
00458     sdl_fill_rect(surf, &percent_sep_rect, grey_color);
00459 
00460     // Draw the rows (lower HP values are at the bottom).
00461     for(int i = 0; i < static_cast<int>(hp_prob_vector.size()); i++) {
00462         char str_buf[10];
00463 
00464         // Get the HP and probability.
00465         int hp = hp_prob_vector[hp_prob_vector.size() - i - 1].first;
00466         double prob = hp_prob_vector[hp_prob_vector.size() - i - 1].second;
00467 
00468         SDL_Color row_color;
00469 
00470         // Death line is red.
00471         if(hp == 0) {
00472             SDL_Color color = {0xe5, 0, 0, 0};
00473             row_color = color;
00474         }
00475 
00476         // Below current hitpoints value is orange.
00477         else if(hp < static_cast<int>(stats.hp)) {
00478             // Stone is grey.
00479             if(opp_stats.petrifies) {
00480                 SDL_Color color = {0x9a, 0x9a, 0x9a, 0};
00481                 row_color = color;
00482             } else {
00483                 SDL_Color color = {0xf4, 0xc9, 0, 0};
00484                 row_color = color;
00485             }
00486         }
00487 
00488         // Current hitpoints value and above is green.
00489         else {
00490             SDL_Color color = {0x08, 0xca, 0, 0};
00491             row_color = color;
00492         }
00493 
00494         // Print HP, aligned right.
00495         snprintf(str_buf, 10, "%d", hp);
00496         str_buf[9] = '\0';  //prevents _snprintf error
00497         int hp_width = font::line_width(str_buf, fs);
00498 
00499         // Draw bars.
00500         font::draw_text_line(surf, clip_rect, fs, font::NORMAL_COLOR, str_buf,
00501                              hp_sep - hp_width - 2, 2 + (fs + 2) * i, 0, TTF_STYLE_NORMAL);
00502 
00503         int bar_len = std::max<int>(static_cast<int>((prob * (bar_space - 4)) + 0.5), 2);
00504 
00505         SDL_Rect bar_rect_1 = create_rect(hp_sep + 4, 6 + (fs + 2) * i, bar_len, 8);
00506         sdl_fill_rect(surf, &bar_rect_1, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 100));
00507 
00508         SDL_Rect bar_rect_2 = create_rect(hp_sep + 4, 7 + (fs + 2) * i, bar_len, 6);
00509         sdl_fill_rect(surf, &bar_rect_2, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 66));
00510 
00511         SDL_Rect bar_rect_3 = create_rect(hp_sep + 4, 8 + (fs + 2) * i, bar_len, 4);
00512         sdl_fill_rect(surf, &bar_rect_3, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 33));
00513 
00514         SDL_Rect bar_rect_4 = create_rect(hp_sep + 4, 9 + (fs + 2) * i, bar_len, 2);
00515         sdl_fill_rect(surf, &bar_rect_4, blend_rgb(surf, row_color.r, row_color.g, row_color.b, 0));
00516 
00517         // Draw probability percentage, aligned right.
00518         format_prob(str_buf, prob);
00519         int prob_width = font::line_width(str_buf, fs);
00520         font::draw_text_line(surf, clip_rect, fs, font::NORMAL_COLOR, str_buf,
00521                          width - prob_width - 4, 2 + (fs + 2) * i, 0, TTF_STYLE_NORMAL);
00522     }
00523 }
00524 
00525 Uint32 battle_prediction_pane::blend_rgb(const surface& surf, unsigned char r, unsigned char g, unsigned char b, unsigned char drop)
00526 {
00527     // We simply decrement each component.
00528     if(r < drop) r = 0; else r -= drop;
00529     if(g < drop) g = 0; else g -= drop;
00530     if(b < drop) b = 0; else b -= drop;
00531 
00532     return SDL_MapRGB(surf->format, r, g, b);
00533 }
00534 
00535 attack_prediction_displayer::RESULT attack_prediction_displayer::button_pressed(int selection)
00536 {
00537     // Get the selected weapon, if any.
00538     const size_t index = size_t(selection);
00539 
00540     if(index < bc_vector_.size()) {
00541         battle_prediction_pane battle_pane(bc_vector_[index], attacker_loc_, defender_loc_);
00542         std::vector<gui::preview_pane*> preview_panes;
00543         preview_panes.push_back(&battle_pane);
00544 
00545         gui::show_dialog(*resources::screen, NULL, _("Damage Calculations"), "", gui::OK_ONLY, NULL, &preview_panes);
00546     }
00547 
00548     return gui::CONTINUE_DIALOG;
00549 }
00550 
00551 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Wed May 23 2012 01:02:34 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs