The Battle for Wesnoth  1.19.18+dev
attack_type.hpp
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 #pragma once
17 
18 #include "map/location.hpp"
19 #include "tstring.hpp"
20 #include "config.hpp"
21 #include <string>
22 #include <vector>
23 
24 #include <boost/iterator/indirect_iterator.hpp>
25 #include <boost/dynamic_bitset_fwd.hpp>
26 
27 #include "units/abilities.hpp"
28 #include "units/ptr.hpp" // for attack_ptr
30 
32 class unit_type;
33 
34 namespace wfl {
35  class map_formula_callable;
36 }
37 
38 //the 'attack type' is the type of attack, how many times it strikes,
39 //and how much damage it does.
40 class attack_type : public std::enable_shared_from_this<attack_type>
41 {
42 public:
43 
44  explicit attack_type(const config& cfg);
45  const t_string& name() const { return description_; }
46  const std::string& id() const { return id_; }
47  const std::string& type() const { return type_; }
48  const std::string& icon() const { return icon_; }
49  const std::string& range() const { return range_; }
50  int min_range() const { return min_range_; }
51  int max_range() const { return max_range_; }
52  std::string accuracy_parry_description() const;
53  std::string accuracy_parry_tooltip() const;
54  int accuracy() const { return accuracy_; }
55  int parry() const { return parry_; }
56  int damage() const { return damage_; }
57  int num_attacks() const { return num_attacks_; }
58  double attack_weight() const { return attack_weight_; }
59  double defense_weight() const { return defense_weight_; }
60  const ability_vector& specials() const { return specials_; }
61 
62  config specials_cfg() const {
64  }
65 
66  ability_vector specials(const std::string& tag) const {
68  }
69 
70  void set_name(const t_string& value) { description_ = value; set_changed(true); }
71  void set_id(const std::string& value) { id_ = value; set_changed(true); }
72  void set_type(const std::string& value) { type_ = value; set_changed(true); }
73  void set_icon(const std::string& value) { icon_ = value; set_changed(true); }
74  void set_range(const std::string& value) { range_ = value; set_changed(true); }
75  void set_min_range(int value) { min_range_ = value; set_changed(true); }
76  void set_max_range(int value) { max_range_ = value; set_changed(true); }
77  void set_attack_alignment(const std::string& value) { alignment_ = unit_alignments::get_enum(value); set_changed(true); }
78  void set_accuracy(int value) { accuracy_ = value; set_changed(true); }
79  void set_parry(int value) { parry_ = value; set_changed(true); }
80  void set_damage(int value) { damage_ = value; set_changed(true); }
81  void set_num_attacks(int value) { num_attacks_ = value; set_changed(true); }
82  void set_attack_weight(double value) { attack_weight_ = value; set_changed(true); }
83  void set_defense_weight(double value) { defense_weight_ = value; set_changed(true); }
84  void set_specials_cfg(const config& value) {
86  }
87 
88 
89  // In unit_abilities.cpp:
90 
91 
92  active_ability_list get_specials(const std::string& special) const;
93 
94  std::vector<unit_ability_t::tooltip_info> special_tooltips(boost::dynamic_bitset<>* active_list = nullptr) const;
95  // This returns a list describing all active abilities in the current context, that have the name_affected= set,
96  // in particular it also returns attack-unrelatedabilities if they have name_affected set.
97  std::vector<unit_ability_t::tooltip_info> abilities_special_tooltips(boost::dynamic_bitset<>* active_list) const;
98 
99  std::string describe_weapon_specials() const;
100  std::string describe_weapon_specials_value(const std::set<std::string>& checking_tags) const;
101 
102  /** Returns alignment specified by alignment_ variable.
103  */
104  utils::optional<unit_alignments::type> alignment() const { return alignment_; }
105  /** Returns alignment specified by alignment() for filtering when exist.
106  */
107  std::string alignment_str() const { return alignment_ ? unit_alignments::get_string(*alignment_) : ""; }
108 
109  /** Calculates the number of attacks this weapon has, considering specials. */
110  void modified_attacks(unsigned & min_attacks,
111  unsigned & max_attacks) const;
112 
113  /** @return A type()/replacement_type and a list of alternative_types that should be displayed in the selected unit's report. */
114  std::pair<std::string, std::set<std::string>> damage_types() const;
115  /** @return The type of attack used and the resistance value that does the most damage. */
116  std::pair<std::string, int> effective_damage_type() const;
117 
118  /** Returns the damage per attack of this weapon, considering specials. */
119  double modified_damage() const;
120  /** Return the defense value, considering specials.
121  * @param cth The chance_to_hit value modified or not by function.
122  */
123  int modified_chance_to_hit(int cth) const;
124 
125  /** Return the special weapon value, considering specials.
126  * @param abil_list The list of special checked.
127  * @param base_value The value modified or not by function.
128  */
129  int composite_value(const active_ability_list& abil_list, int base_value) const;
130  /** Returns list for weapon like abilities for each ability type. */
131  active_ability_list get_weapon_ability(const std::string& ability) const;
132  /**
133  * @param special the tag name to check for
134  * @return list which contains get_weapon_ability and get_specials list for each ability type, with overwritten items removed
135  */
136  active_ability_list get_specials_and_abilities(const std::string& special) const;
137  /** used for abilities used like weapon and true specials
138  * @return True if the ability @a special is active.
139  * @param special The special being checked.
140  */
141  bool has_special_or_ability(const std::string& special) const;
142  /**
143  * @param special id to check.
144  */
145  bool has_active_special_or_ability_id(const std::string& special) const;
146  /** check if special matche
147  * @return True if special matche with filter(if 'active' filter is true, check if special active).
148  * @param filter contain attributes to check(special_id, special_type etc...).
149  */
150  bool has_filter_special_or_ability(const config& filter) const;
151  /**
152  * Returns true if this is a dummy attack_type, for example the placeholder that the unit_attack dialog
153  * uses when a defender has no weapon for a given range.
154  */
155  bool attack_empty() const {return (id().empty() && name().empty() && type().empty() && range().empty());}
156  /** remove special if matche condition
157  * @param filter if special check with filter, it will be removed.
158  */
160  /** check if special matche
161  * @return True if special matche with filter(if 'active' filter is true, check if special active).
162  * @param filter if special check with filter, return true.
163  */
165 
166  // In unit_types.cpp:
167 
168  bool matches_filter(const config& filter, const std::string& check_if_recursion = "") const;
169 
170  /** Applies effect modifications described by @a cfg. */
171  void apply_effect(const config& cfg);
172 
173  /**
174  * Generates a description of the effect specified by @a cfg, if applicable.
175  * This covers a subset of the effects which can be applied via @ref apply_effect.
176  */
177  static std::string describe_effect(const config& cfg);
178 
179  int movement_used() const { return movement_used_; }
180  void set_movement_used(int value) { movement_used_ = value; }
181  int attacks_used() const { return attacks_used_; }
182  void set_attacks_used(int value) { attacks_used_ = value; }
183 
184  void write(config& cfg) const;
185  inline config to_config() const { config c; write(c); return c; }
186 
188 
189  // In unit_abilities.cpp:
190 
191  // Configured as a bit field, in case that is useful.
193  /**
194  * Select best damage type based on frequency count for replacement_type.
195  *
196  * @param damage_type_list list of [damage_type] to check.
197  */
198  std::string select_replacement_type(const active_ability_list& damage_type_list) const;
199  /**
200  * Select best damage type based on highest damage for alternative_type.
201  *
202  * @param damage_type_list list of [damage_type] to check.
203  * @param resistance_list list of "resistance" abilities to check for each type of damage checked.
204  */
205  std::pair<std::string, int> select_alternative_type(const active_ability_list& damage_type_list, const active_ability_list& resistance_list) const;
206  /**
207  * Filter a list of abilities or weapon specials, removing any entries that don't own
208  * the overwrite_specials attributes.
209  *
210  * @param overwriters list that may have overwrite_specials attributes.
211  */
213  /**
214  * Check whether @a cfg would be overwritten by any element of @a overwriters.
215  *
216  * @return True if element checked is overwritable.
217  * @param overwriters list used for check if element is overwritable.
218  * @param ab the ability/special checked
219  */
220  bool overwrite_special_checking(active_ability_list& overwriters, const unit_ability_t& ab) const;
221 
222  bool special_active(const unit_ability_t& ab, AFFECTS whom) const;
223 
224  bool special_tooltip_active(const unit_ability_t& ab) const;
225 /** weapon_specials_impl_self and weapon_specials_impl_adj : check if special name can be added.
226  * @param[in,out] temp_string the string modified and returned
227  * @param[in] self the unit checked.
228  * @param[in] self_attack the attack used by unit checked in this function.
229  * @param[in] other_attack the attack used by opponent to unit checked.
230  * @param[in] self_loc location of the unit checked.
231  * @param[in] whom determine if unit affected or not by special ability.
232  * @param[in,out] checking_name the reference for checking if a name is already added
233  * @param[in] checking_tags the reference for checking if special ability type can be used
234  */
235  static void weapon_specials_impl_self(
236  std::string& temp_string,
237  const unit_const_ptr& self,
238  const const_attack_ptr& self_attack,
239  const const_attack_ptr& other_attack,
240  const map_location& self_loc,
241  AFFECTS whom,
242  std::set<std::string>& checking_name,
243  const std::set<std::string>& checking_tags={}
244  );
245 
246  static void weapon_specials_impl_adj(
247  std::string& temp_string,
248  const unit_const_ptr& self,
249  const const_attack_ptr& self_attack,
250  const const_attack_ptr& other_attack,
251  const map_location& self_loc,
252  AFFECTS whom,
253  std::set<std::string>& checking_name,
254  const std::set<std::string>& checking_tags={},
255  const std::string& affect_adjacents=""
256  );
257 
258 
259  static bool special_active_impl(
260  const const_attack_ptr& self_attack,
261  const const_attack_ptr& other_attack,
262  const unit_ability_t& special,
263  AFFECTS whom
264  );
265 
266 
267  // make more functions proivate after refactoring finished.
268 private:
269 
270  // Used via specials_context() to control which specials are
271  // considered active.
272  friend class specials_context_t;
276  mutable bool is_attacker_;
278  mutable bool is_for_listing_ = false;
279 public:
281  std::shared_ptr<const attack_type> parent;
282  friend class attack_type;
283  /** Initialize weapon specials context for listing */
284  explicit specials_context_t(const attack_type& weapon, bool attacking);
285  /** Initialize weapon specials context for a single unit */
286  specials_context_t(const attack_type& weapon, const_attack_ptr other_weapon,
287  unit_const_ptr self, unit_const_ptr other,
288  const map_location& self_loc, const map_location& other_loc,
289  bool attacking);
290  /** Initialize weapon specials context for a pair of units */
291  specials_context_t(const attack_type& weapon, unit_const_ptr self, const map_location& loc, bool attacking);
293  bool was_moved = false;
294  public:
295  // Destructor at least needs to be public for all this to work.
298  };
299  // Set up a specials context.
300  // Usage: auto ctx = weapon.specials_context(...);
302  const map_location& unit_loc, const map_location& other_loc,
303  bool attacking, const_attack_ptr other_attack) const {
304  return specials_context_t(*this, other_attack, self, other, unit_loc, other_loc, attacking);
305  }
306  specials_context_t specials_context(unit_const_ptr self, const map_location& loc, bool attacking = true) const {
307  return specials_context_t(*this, self, loc, attacking);
308  }
309  specials_context_t specials_context_for_listing(bool attacking = true) const {
310  return specials_context_t(*this, attacking);
311  }
312  void set_changed(bool value)
313  {
314  changed_ = value;
315  }
316  bool get_changed() const
317  {
318  return changed_;
319  }
320 private:
321 
323  std::string id_;
324  std::string type_;
325  std::string icon_;
326  std::string range_;
328  utils::optional<unit_alignments::type> alignment_;
329  int damage_;
333 
337  int parry_;
339  bool changed_;
340 };
341 
342 using attack_list = std::vector<attack_ptr>;
343 using attack_itors = boost::iterator_range<boost::indirect_iterator<attack_list::iterator>>;
344 using const_attack_itors = boost::iterator_range<boost::indirect_iterator<attack_list::const_iterator>>;
345 
347  return boost::make_iterator_range(boost::make_indirect_iterator(atks.begin()), boost::make_indirect_iterator(atks.end()));
348 }
349 
351  return boost::make_iterator_range(boost::make_indirect_iterator(atks.begin()), boost::make_indirect_iterator(atks.end()));
352 }
std::vector< ability_ptr > ability_vector
Definition: abilities.hpp:29
map_location loc
Definition: move.cpp:172
boost::iterator_range< boost::indirect_iterator< attack_list::iterator > > attack_itors
std::vector< attack_ptr > attack_list
boost::iterator_range< boost::indirect_iterator< attack_list::const_iterator > > const_attack_itors
attack_itors make_attack_itors(attack_list &atks)
specials_context_t(const specials_context_t &)=delete
specials_context_t(const attack_type &weapon, bool attacking)
Initialize weapon specials context for listing.
Definition: abilities.cpp:1287
std::shared_ptr< const attack_type > parent
std::string alignment_str() const
Returns alignment specified by alignment() for filtering when exist.
void set_min_range(int value)
Definition: attack_type.hpp:75
map_location other_loc_
active_ability_list overwrite_special_overwriter(active_ability_list overwriters) const
Filter a list of abilities or weapon specials, removing any entries that don't own the overwrite_spec...
Definition: abilities.cpp:1497
double defense_weight() const
Definition: attack_type.hpp:59
void set_num_attacks(int value)
Definition: attack_type.hpp:81
specials_context_t specials_context(unit_const_ptr self, const map_location &loc, bool attacking=true) const
int min_range() const
Definition: attack_type.hpp:50
bool has_active_special_or_ability_id(const std::string &special) const
Definition: abilities.cpp:1638
static void weapon_specials_impl_adj(std::string &temp_string, const unit_const_ptr &self, const const_attack_ptr &self_attack, const const_attack_ptr &other_attack, const map_location &self_loc, AFFECTS whom, std::set< std::string > &checking_name, const std::set< std::string > &checking_tags={}, const std::string &affect_adjacents="")
Definition: abilities.cpp:1210
double attack_weight() const
Definition: attack_type.hpp:58
const_attack_ptr other_attack_
void add_formula_context(wfl::map_formula_callable &) const
Definition: abilities.cpp:833
const std::string & range() const
Definition: attack_type.hpp:49
void set_attacks_used(int value)
map_location self_loc_
int movement_used() const
active_ability_list get_weapon_ability(const std::string &ability) const
Returns list for weapon like abilities for each ability type.
Definition: abilities.cpp:1455
specials_context_t specials_context_for_listing(bool attacking=true) const
bool has_special_or_ability_with_filter(const config &filter) const
check if special matche
Definition: abilities.cpp:1866
void set_accuracy(int value)
Definition: attack_type.hpp:78
bool get_changed() const
const std::string & type() const
Definition: attack_type.hpp:47
void set_movement_used(int value)
std::pair< std::string, int > select_alternative_type(const active_ability_list &damage_type_list, const active_ability_list &resistance_list) const
Select best damage type based on highest damage for alternative_type.
bool has_special_or_ability(const std::string &special) const
used for abilities used like weapon and true specials
Definition: abilities.cpp:1614
int parry() const
Definition: attack_type.hpp:55
std::string accuracy_parry_tooltip() const
std::string accuracy_parry_description() const
Definition: attack_type.cpp:93
double modified_damage() const
Returns the damage per attack of this weapon, considering specials.
std::string describe_weapon_specials() const
Returns a comma-separated string of active names for the specials of *this.
Definition: abilities.cpp:1102
void apply_effect(const config &cfg)
Applies effect modifications described by cfg.
bool matches_filter(const config &filter, const std::string &check_if_recursion="") const
Returns whether or not *this matches the given filter.
void set_specials_cfg(const config &value)
Definition: attack_type.hpp:84
std::string select_replacement_type(const active_ability_list &damage_type_list) const
Select best damage type based on frequency count for replacement_type.
config specials_cfg() const
Definition: attack_type.hpp:62
unit_const_ptr self_
friend class specials_context_t
void set_defense_weight(double value)
Definition: attack_type.hpp:83
ability_vector specials(const std::string &tag) const
Definition: attack_type.hpp:66
int num_attacks() const
Definition: attack_type.hpp:57
void set_changed(bool value)
active_ability_list get_specials_and_abilities(const std::string &special) const
Definition: abilities.cpp:1474
std::pair< std::string, std::set< std::string > > damage_types() const
Return a type()/replacement_type and a list of alternative_types that should be displayed in the sele...
std::string type_
std::string icon_
void set_parry(int value)
Definition: attack_type.hpp:79
std::vector< unit_ability_t::tooltip_info > special_tooltips(boost::dynamic_bitset<> *active_list=nullptr) const
Returns a vector of names and descriptions for the specials of *this.
Definition: abilities.cpp:1012
void set_attack_weight(double value)
Definition: attack_type.hpp:82
void set_damage(int value)
Definition: attack_type.hpp:80
ability_vector specials_
utils::optional< unit_alignments::type > alignment() const
Returns alignment specified by alignment_ variable.
const t_string & name() const
Definition: attack_type.hpp:45
std::string describe_weapon_specials_value(const std::set< std::string > &checking_tags) const
Definition: abilities.cpp:1148
int attacks_used() const
unit_ability_t::affects_t AFFECTS
const std::string & id() const
Definition: attack_type.hpp:46
void set_icon(const std::string &value)
Definition: attack_type.hpp:73
std::vector< unit_ability_t::tooltip_info > abilities_special_tooltips(boost::dynamic_bitset<> *active_list) const
Definition: abilities.cpp:1044
bool has_filter_special_or_ability(const config &filter) const
check if special matche
static void weapon_specials_impl_self(std::string &temp_string, const unit_const_ptr &self, const const_attack_ptr &self_attack, const const_attack_ptr &other_attack, const map_location &self_loc, AFFECTS whom, std::set< std::string > &checking_name, const std::set< std::string > &checking_tags={})
weapon_specials_impl_self and weapon_specials_impl_adj : check if special name can be added.
Definition: abilities.cpp:1188
int modified_chance_to_hit(int cth) const
Return the defense value, considering specials.
bool special_active(const unit_ability_t &ab, AFFECTS whom) const
Definition: abilities.cpp:1894
bool attack_empty() const
Returns true if this is a dummy attack_type, for example the placeholder that the unit_attack dialog ...
double defense_weight_
std::string id_
double attack_weight_
bool special_tooltip_active(const unit_ability_t &ab) const
Returns whether or not the given special is active for the specified unit disregarding other units,...
Definition: abilities.cpp:2042
config to_config() const
void modified_attacks(unsigned &min_attacks, unsigned &max_attacks) const
Calculates the number of attacks this weapon has, considering specials.
std::string range_
void set_id(const std::string &value)
Definition: attack_type.hpp:71
void remove_special_by_filter(const config &filter)
remove special if matche condition
active_ability_list get_specials(const std::string &special) const
Returns the currently active specials as an ability list, given the current context (see set_specials...
Definition: abilities.cpp:979
specials_context_t specials_context(unit_const_ptr self, unit_const_ptr other, const map_location &unit_loc, const map_location &other_loc, bool attacking, const_attack_ptr other_attack) const
void set_max_range(int value)
Definition: attack_type.hpp:76
utils::optional< unit_alignments::type > alignment_
attack_type(const config &cfg)
Definition: attack_type.cpp:55
void set_type(const std::string &value)
Definition: attack_type.hpp:72
void write(config &cfg) const
bool overwrite_special_checking(active_ability_list &overwriters, const unit_ability_t &ab) const
Check whether cfg would be overwritten by any element of overwriters.
Definition: abilities.cpp:1533
int accuracy() const
Definition: attack_type.hpp:54
unit_const_ptr other_
int max_range() const
Definition: attack_type.hpp:51
void set_range(const std::string &value)
Definition: attack_type.hpp:74
int composite_value(const active_ability_list &abil_list, int base_value) const
Return the special weapon value, considering specials.
static std::string describe_effect(const config &cfg)
Generates a description of the effect specified by cfg, if applicable.
const std::string & icon() const
Definition: attack_type.hpp:48
int damage() const
Definition: attack_type.hpp:56
const ability_vector & specials() const
Definition: attack_type.hpp:60
void set_attack_alignment(const std::string &value)
Definition: attack_type.hpp:77
t_string description_
static bool special_active_impl(const const_attack_ptr &self_attack, const const_attack_ptr &other_attack, const unit_ability_t &special, AFFECTS whom)
Returns whether or not the given special is active for the specified unit, based on the current conte...
Definition: abilities.cpp:1930
void set_name(const t_string &value)
Definition: attack_type.hpp:70
bool is_for_listing_
std::pair< std::string, int > effective_damage_type() const
The type of attack used and the resistance value that does the most damage.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:157
static config vector_to_cfg(const ability_vector &abilities)
Definition: abilities.cpp:277
static ability_vector filter_tag(const ability_vector &vec, const std::string &tag)
Definition: abilities.cpp:257
static ability_vector cfg_to_vector(const config &abilities_cfg, bool inside_attack)
Definition: abilities.cpp:250
A single unit type that the player may recruit.
Definition: types.hpp:43
Definitions for the interface to Wesnoth Markup Language (WML).
const config * cfg
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
Definition: markup.hpp:45
constexpr auto filter
Definition: ranges.hpp:38
Definition: callable.hpp:26
std::shared_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:27
std::shared_ptr< const attack_type > const_attack_ptr
Definition: ptr.hpp:34
Encapsulates the map of the game.
Definition: location.hpp:46
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
Definition: enum_base.hpp:46
static constexpr utils::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
Definition: enum_base.hpp:57
mock_char c