Attack Predictions: initial implementation of HP probability graphs
This commit is contained in:
parent
55b90a128b
commit
32118d59c4
3 changed files with 243 additions and 6 deletions
|
@ -115,6 +115,47 @@
|
|||
[/grid]
|
||||
#enddef
|
||||
|
||||
#define _GUI_HP_GRAPH _ID_PREFIX
|
||||
[drawing]
|
||||
id = {_ID_PREFIX} + "_hp_graph"
|
||||
definition = "default"
|
||||
|
||||
width = 300
|
||||
height = 200
|
||||
|
||||
[draw]
|
||||
|
||||
[rectangle]
|
||||
x = 0
|
||||
y = 0
|
||||
w = "(width)"
|
||||
h = "(height)"
|
||||
fill_color = "25, 25, 25, 255"
|
||||
border_thickness = 2
|
||||
border_color = "183, 193, 183, 255"
|
||||
[/rectangle]
|
||||
|
||||
[rectangle]
|
||||
x = "(hp_column_width)"
|
||||
y = 0
|
||||
w = 2
|
||||
h = "(height - 2)"
|
||||
fill_color = "183, 193, 183, 255"
|
||||
[/rectangle]
|
||||
|
||||
[rectangle]
|
||||
x = "(width - chance_column_width - 2)"
|
||||
y = 0
|
||||
w = 2
|
||||
h = "(height - 2)"
|
||||
fill_color = "183, 193, 183, 255"
|
||||
[/rectangle]
|
||||
|
||||
[/draw]
|
||||
|
||||
[/drawing]
|
||||
#enddef
|
||||
|
||||
[window]
|
||||
id = "attack_predictions"
|
||||
description = "Statistics dialog."
|
||||
|
@ -126,7 +167,7 @@
|
|||
vertical_placement = "center"
|
||||
horizontal_placement = "center"
|
||||
|
||||
maximum_height = 400
|
||||
#maximum_height = 400
|
||||
|
||||
[linked_group]
|
||||
id = "header"
|
||||
|
@ -311,6 +352,44 @@
|
|||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 1
|
||||
|
||||
[column]
|
||||
horizontal_grow = true
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = true
|
||||
vertical_grow = true
|
||||
|
||||
{_GUI_HP_GRAPH ("attacker")}
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = true
|
||||
vertical_grow = true
|
||||
|
||||
{_GUI_HP_GRAPH ("defender")}
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
|
@ -334,5 +413,6 @@
|
|||
|
||||
[/window]
|
||||
|
||||
#undef _GUI_HP_GRAPH
|
||||
#undef _GUI_DATA_PANEL
|
||||
#undef _GUI_SPACER_ROW
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
|
||||
#include "attack_prediction.hpp"
|
||||
#include "color.hpp"
|
||||
#include "config.hpp"
|
||||
#include "font/text_formatting.hpp"
|
||||
#include "formatter.hpp"
|
||||
#include "formula/variant.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
#include "gui/widgets/drawing.hpp"
|
||||
#include "gui/widgets/label.hpp"
|
||||
#include "gui/widgets/image.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "gettext.hpp"
|
||||
|
@ -40,6 +42,9 @@ namespace dialogs
|
|||
|
||||
REGISTER_DIALOG(attack_predictions)
|
||||
|
||||
const unsigned int attack_predictions::graph_width = 300;
|
||||
const unsigned int attack_predictions::graph_height = 200;
|
||||
|
||||
attack_predictions::attack_predictions(battle_context& bc, const unit& attacker, const unit& defender)
|
||||
: attacker_data_(attacker, bc.get_attacker_combatant(), bc.get_attacker_stats())
|
||||
, defender_data_(defender, bc.get_defender_combatant(), bc.get_defender_stats())
|
||||
|
@ -196,8 +201,148 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker
|
|||
const color_t ndc_color = game_config::red_to_green(attacker.combatant_.untouched * 10);
|
||||
|
||||
// Unscathed probability.
|
||||
set_label_helper("no_damage_chance", (formatter() << font::span_color(ndc_color) << get_probability_string(attacker.combatant_.untouched) << "</span>").str());
|
||||
set_label_helper("no_damage_chance",
|
||||
(formatter() << font::span_color(ndc_color) << get_probability_string(attacker.combatant_.untouched) << "</span>").str());
|
||||
|
||||
drawing& graph_widget = find_widget<drawing>(&window, widget_id_prefix + "hp_graph", false);
|
||||
|
||||
draw_hp_graph(graph_widget, attacker, defender);
|
||||
}
|
||||
|
||||
void attack_predictions::draw_hp_graph(drawing& hp_graph, const combatant_data& attacker, const combatant_data& defender)
|
||||
{
|
||||
// Font size. If you change this, you must update the separator space.
|
||||
const int fs = font::SIZE_SMALL;
|
||||
|
||||
// Space before HP separator.
|
||||
const int hp_sep = 24 + 6;
|
||||
|
||||
// Space after percentage separator.
|
||||
const int percent_sep = 43 + 6;
|
||||
|
||||
// Bar space between both separators.
|
||||
const int bar_space = graph_width - hp_sep - percent_sep - 4;
|
||||
|
||||
// Set some variables for the WML portion of the graph to use.
|
||||
canvas& hp_graph_canvas = hp_graph.get_drawing_canvas();
|
||||
|
||||
hp_graph_canvas.set_variable("hp_column_width", variant(hp_sep));
|
||||
hp_graph_canvas.set_variable("chance_column_width", variant(percent_sep));
|
||||
|
||||
config cfg, shape;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// Draw the rows (lower HP values are at the bottom).
|
||||
for(const auto& probability : get_hitpoint_probabilities(attacker.combatant_.hp_dist)) {
|
||||
|
||||
// Get the HP and probability.
|
||||
int hp; double prob;
|
||||
std::tie(hp, prob) = probability;
|
||||
|
||||
color_t row_color;
|
||||
|
||||
// Death line is red.
|
||||
if(hp == 0) {
|
||||
row_color = {229, 0, 0};
|
||||
}
|
||||
|
||||
// Below current hitpoints value is orange.
|
||||
else if(hp < static_cast<int>(attacker.stats_.hp)) {
|
||||
// Stone is grey.
|
||||
if(defender.stats_.petrifies) {
|
||||
row_color = {154, 154, 154};
|
||||
} else {
|
||||
row_color = {244, 201, 0};
|
||||
}
|
||||
}
|
||||
|
||||
// Current hitpoints value and above is green.
|
||||
else {
|
||||
row_color = {8, 202, 0};
|
||||
}
|
||||
|
||||
shape["text"] = hp;
|
||||
shape["x"] = 2;
|
||||
shape["y"] = 2 + (fs + 2) * i;
|
||||
shape["w"] = "(text_width)";
|
||||
shape["h"] = "(text_height)";
|
||||
shape["font_size"] = 12;
|
||||
shape["color"] = "255, 255, 255, 255";
|
||||
shape["text_alignment"] = "(text_alignment)";
|
||||
|
||||
cfg.add_child("text", shape);
|
||||
|
||||
shape.clear();
|
||||
shape["text"] = get_probability_string(prob);
|
||||
shape["x"] = graph_width - percent_sep + 2;
|
||||
shape["y"] = 2 + (fs + 2) * i;
|
||||
shape["w"] = "(text_width)";
|
||||
shape["h"] = "(text_height)";
|
||||
shape["font_size"] = 12;
|
||||
shape["color"] = "255, 255, 255, 255";
|
||||
shape["text_alignment"] = "(text_alignment)";
|
||||
|
||||
cfg.add_child("text", shape);
|
||||
|
||||
const int bar_len = std::max(static_cast<int>((prob * (bar_space - 4)) + 0.5), 2);
|
||||
|
||||
const SDL_Rect bar_rect_1 {
|
||||
hp_sep + 4,
|
||||
6 + (fs + 2) * i,
|
||||
bar_len,
|
||||
8
|
||||
};
|
||||
|
||||
shape.clear();
|
||||
shape["x"] = bar_rect_1.x;
|
||||
shape["y"] = bar_rect_1.y;
|
||||
shape["w"] = bar_rect_1.w;
|
||||
shape["h"] = bar_rect_1.h;
|
||||
shape["fill_color"] = row_color.to_rgba_string();
|
||||
|
||||
cfg.add_child("rectangle", shape);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
hp_graph.append_drawing_data(cfg);
|
||||
}
|
||||
|
||||
hp_probability_vector attack_predictions::get_hitpoint_probabilities(const std::vector<double>& hp_dist)
|
||||
{
|
||||
hp_probability_vector res;
|
||||
|
||||
// First, we sort the probabilities in ascending order.
|
||||
std::vector<std::pair<double, int>> prob_hp_vector;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < static_cast<int>(hp_dist.size()); i++) {
|
||||
double prob = hp_dist[i];
|
||||
|
||||
// We keep only values above 0.1%.
|
||||
if(prob > 0.001) {
|
||||
prob_hp_vector.push_back(std::pair<double, int>(prob, i));
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(prob_hp_vector.begin(), prob_hp_vector.end());
|
||||
|
||||
// We store a few of the highest probability hitpoint values.
|
||||
int nb_elem = std::min<int>(10, prob_hp_vector.size());
|
||||
//int nb_elem = prob_hp_vector.size();
|
||||
|
||||
for(i = prob_hp_vector.size() - nb_elem; i < static_cast<int>(prob_hp_vector.size()); i++) {
|
||||
|
||||
res.push_back(std::pair<int, double>
|
||||
(prob_hp_vector[i].second, prob_hp_vector[i].first));
|
||||
}
|
||||
|
||||
// Then, we sort the hitpoint values in ascending order.
|
||||
std::sort(res.begin(), res.end());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
} // namespace gui2
|
||||
|
|
|
@ -19,17 +19,22 @@
|
|||
#include "gui/dialogs/modal_dialog.hpp"
|
||||
#include "units/map.hpp"
|
||||
|
||||
class battle_context;
|
||||
class battle_context;
|
||||
class CVideo;
|
||||
|
||||
struct battle_context_unit_stats;
|
||||
class CVideo;
|
||||
struct map_location;
|
||||
struct combatant;
|
||||
struct map_location;
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
class drawing;
|
||||
|
||||
namespace dialogs
|
||||
{
|
||||
|
||||
using hp_probability_vector = std::vector<std::pair<int, double>>;
|
||||
|
||||
class attack_predictions : public modal_dialog
|
||||
{
|
||||
public:
|
||||
|
@ -62,6 +67,13 @@ private:
|
|||
|
||||
void set_data(window& window, const combatant_data& attacker, const combatant_data& defender);
|
||||
|
||||
hp_probability_vector get_hitpoint_probabilities(const std::vector<double>& hp_dist);
|
||||
|
||||
static const unsigned int graph_width;
|
||||
static const unsigned int graph_height;
|
||||
|
||||
void draw_hp_graph(drawing& hp_graph, const combatant_data& attacker, const combatant_data& defender);
|
||||
|
||||
combatant_data attacker_data_;
|
||||
combatant_data defender_data_;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue