The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
helper.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
3 by David White <dave@whitevine.net>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16/**
17 * @file
18 * Support functions for dealing with units.
19 */
20
21#include "actions/create.hpp"
23#include "resources.hpp"
24#include "units/unit.hpp"
25#include "units/helper.hpp"
26#include "units/types.hpp"
27#include "play_controller.hpp"
29#include "utils/general.hpp"
31
32namespace unit_helper {
33
35{
36 return u.advances_to().size() + u.get_modification_advances().size();
37}
38
40{
41 if(!u.valid()) {
42 return false;
43 }
44 return u->advances() && number_of_possible_advances(*u) > 0;
45}
46
47/**
48 * Maps resistance <= -60 (resistance value <= -60%) to intense red.
49 * Maps resistance >= 60 (resistance value >= 60%) to intense green.
50 * Intermediate values are affinely mapped to the red-to-green scale,
51 * with 0 (0%) being mapped to yellow.
52 * Compare attack_info_percent_color() in reports.cpp.
53 */
54std::string resistance_color(const int resistance)
55{
56 // Passing false to select the more saturated red-to-green scale.
57 return game_config::red_to_green(50.0 + resistance * 5.0 / 6.0, false).to_hex_string();
58}
59
60static std::string unit_level_tooltip(const int level, const std::vector<std::string> &adv_to_types, const std::vector<config> &adv_to_mods)
61{
62 std::ostringstream tooltip;
63 tooltip << _("Level: ") << markup::bold(level) << "\n";
64 const bool has_advancements = !adv_to_types.empty() || !adv_to_mods.empty();
65 if(has_advancements) {
66 tooltip << _("Advancements:") << "\n\t";
67 if(!adv_to_types.empty())
68 tooltip << markup::bold(utils::join(adv_to_types, "\n\t"));
69 if(!adv_to_mods.empty()) {
70 if(!adv_to_types.empty())
71 tooltip << "\n\t";
72 std::vector<std::string> descriptions;
73 for(const config& adv : adv_to_mods)
74 descriptions.push_back(adv["description"].str());
75 tooltip << markup::bold(utils::join(descriptions, "\n\t"));
76 }
77 } else {
78 tooltip << _("No advancement");
79 }
80 return tooltip.str();
81}
82
87
88std::string unit_level_tooltip(const unit_type &type)
89{
90 const auto mod_adv_iters = type.modification_advancements();
91 const std::vector<config> mod_advancements(mod_adv_iters.begin(), mod_adv_iters.end());
92
93 return unit_level_tooltip(type.level(), type.advances_to(), mod_advancements);
94}
95
96std::string maybe_inactive(const std::string& str, bool active)
97{
98 return (active ? str : markup::span_color(font::INACTIVE_COLOR, str));
99}
100
101std::string format_cost_string(int unit_recall_cost, bool active)
102{
103 std::stringstream str;
104 if (active) {
105 str << markup::img("themes/gold.png") << ' ' << unit_recall_cost;
106 } else {
107 str << markup::img("themes/gold.png~GS()") << ' '
108 << maybe_inactive(std::to_string(unit_recall_cost), false);
109 }
110 return str.str();
111}
112
113std::string format_cost_string(int unit_recall_cost, const int team_recall_cost)
114{
115 if(unit_recall_cost < 0) {
116 unit_recall_cost = team_recall_cost;
117 }
118
119 std::stringstream str;
120 str << markup::img("themes/gold.png") << ' ';
121
122 if(unit_recall_cost > team_recall_cost) {
123 str << markup::span_color(font::BAD_COLOR, unit_recall_cost);
124 } else if(unit_recall_cost < team_recall_cost) {
125 str << markup::span_color(font::GOOD_COLOR, unit_recall_cost);
126 } else {
127 // Default: show cost in white font color.
128 // Should handle the unit cost = team cost case.
129 str << unit_recall_cost;
130 }
131
132 return str.str();
133}
134
135std::string format_level_string(const int level, bool recallable)
136{
137 if(!recallable) {
138 // Same logic as when recallable, but always in inactive_color.
140 (level < 2 ? std::to_string(level) : markup::bold(level)));
141 } else if(level < 1) {
143 } else if(level == 1) {
144 return std::to_string(level);
145 } else if(level == 2) {
146 return markup::bold(level);
147 } else if(level == 3) {
148 return markup::span_color(color_t(0xe2, 0xb7, 0x76), markup::bold(level));
149 } else {
150 return markup::span_color(color_t(0xdd, 0x66, 0x00), markup::bold(level));
151 }
152}
153
154std::string format_movement_string(const int moves_left, const int moves_max, bool active)
155{
156 if (!active) {
157 return markup::span_color(font::GRAY_COLOR, moves_left, "/", moves_max);
158 } else if(moves_left == 0) {
159 return markup::span_color(font::BAD_COLOR, moves_left, "/", moves_max);
160 } else if(moves_left > moves_max) {
161 return markup::span_color(font::YELLOW_COLOR, moves_left, "/", moves_max);
162 } else {
163 return markup::span_color(font::GOOD_COLOR, moves_left, "/", moves_max);
164 }
165}
166
167int planned_gold_spent(int side_number)
168{
169 wb::future_map future; // FIXME: why not future_map_if_active?
171 return wb ? wb->get_spent_gold_for(side_number) : 0;
172}
173
174std::string check_recruit_purse(int unit_cost, int current_purse, int investments)
175{
176 if(unit_cost > (current_purse - investments)) {
177 return investments > 0
178 // TRANSLATORS: "plan" refers to Planning Mode
179 ? _("At this point in your plan, you will not have enough gold to recruit this unit.")
180 : _("You do not have enough gold to recruit this unit.");
181 }
182
183 return "";
184}
185
187 const std::string& type, int side_number, const map_location& target_hex)
188{
189 const unit_type* u_type = unit_types.find(type);
190 if(!u_type || utils::contains(actions::get_recruits(side_number, target_hex), type)) {
191 return "";
192 }
193
194 utils::string_map symbols{{ "unit_type", u_type->type_name() }};
195 return VGETTEXT("The $unit_type is not available to recruit.", symbols);
196}
197
198std::tuple<std::string, map_location, map_location> validate_recruit_target(
199 const std::string& type, int side_number, const map_location& target_hex)
200{
201 // start planned unit map scope if in planning mode
203
204 map_location recruit_to = target_hex;
205 map_location recruit_from; // Populated below
206
207 std::string msg = actions::find_recruit_location(side_number, recruit_to, recruit_from, type);
208 return std::tuple(msg, recruit_to, recruit_from);
209}
210
211} // unit_helper
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
std::shared_ptr< wb::manager > get_whiteboard() const
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition types.cpp:1253
A single unit type that the player may recruit.
Definition types.hpp:43
const t_string & type_name() const
The name of the unit in the current language setting.
Definition types.hpp:142
This class represents a single unit of a specific type.
Definition unit.hpp:39
Various functions related to the creation of units (recruits, recalls, and placed units).
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
static std::string _(const char *str)
Definition gettext.hpp:100
int level() const
The current level of this unit.
Definition unit.hpp:481
std::vector< config > get_modification_advances() const
Gets any non-typed advanced options set by modifications.
Definition unit.cpp:1893
const std::vector< std::string > advances_to_translated() const
Gets the names of the possible types this unit can advance to on level-up.
Definition unit.cpp:1293
const advances_to_t & advances_to() const
Gets the possible types this unit can advance to on level-up.
Definition unit.hpp:150
std::string tooltip
Shown when hovering over an entry in the filter's drop-down list.
Definition manager.cpp:203
std::string find_recruit_location(const int side, map_location &recruit_location, map_location &recruited_from, const std::string &unit_type)
Finds a location on which to place a unit.
Definition create.cpp:466
std::set< std::string > get_recruits(int side, const map_location &recruit_loc)
Gets the recruitable units from a side's leaders' personal recruit lists who can recruit on or from a...
Definition create.cpp:60
const color_t YELLOW_COLOR
const color_t GOOD_COLOR
const color_t BAD_COLOR
const color_t GRAY_COLOR
const color_t INACTIVE_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....
std::string img(const std::string &src, const std::string &align, bool floating)
Generates a Help markup tag corresponding to an image.
Definition markup.cpp:37
std::string bold(Args &&... data)
Applies bold Pango markup to the input.
Definition markup.hpp:161
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition markup.hpp:110
play_controller * controller
Definition resources.cpp:21
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:60
bool will_certainly_advance(const unit_map::iterator &u)
Encapsulates the logic for deciding whether an iterator u points to a unit that can advance.
Definition helper.cpp:39
std::string resistance_color(const int resistance)
Maps resistance <= -60 (resistance value <= -60%) to intense red.
Definition helper.cpp:54
std::string format_level_string(const int level, bool recallable)
Definition helper.cpp:135
std::string check_recruit_list(const std::string &type, int side_number, const map_location &target_hex)
Definition helper.cpp:186
std::string format_movement_string(const int moves_left, const int moves_max, bool active)
Definition helper.cpp:154
std::string check_recruit_purse(int unit_cost, int current_purse, int investments)
Definition helper.cpp:174
int planned_gold_spent(int side_number)
Definition helper.cpp:167
std::string maybe_inactive(const std::string &str, bool active)
Definition helper.cpp:96
int number_of_possible_advances(const unit &u)
Determines the total number of available advancements (of any kind) for a given unit.
Definition helper.cpp:34
std::string format_cost_string(int unit_recall_cost, bool active)
Definition helper.cpp:101
std::tuple< std::string, map_location, map_location > validate_recruit_target(const std::string &type, int side_number, const map_location &target_hex)
Verifies that target_hex is a valid recruit location for the given side.
Definition helper.cpp:198
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition general.hpp:88
std::string join(const Range &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::map< std::string, t_string > string_map
Definition display.hpp:45
int moves_left
Definition pathfind.cpp:156
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
std::string to_hex_string() const
Returns the stored color in rrggbb hex format.
Definition color.cpp:88
Encapsulates the map of the game.
Definition location.hpp:46
bool valid() const
Definition map.hpp:273
ONLY IF whiteboard is currently active, applies the planned unit map for the duration of the struct's...
Definition manager.hpp:274
Applies the planned unit map for the duration of the struct's life.
Definition manager.hpp:253
unit_type_data unit_types
Definition types.cpp:1499