The Battle for Wesnoth  1.17.23+dev
attack_type.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2023
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 #include <cassert>
24 
25 #include <boost/iterator/indirect_iterator.hpp>
26 #include <boost/range/iterator_range.hpp>
27 #include <boost/dynamic_bitset_fwd.hpp>
28 
29 #include "units/ptr.hpp" // for attack_ptr
30 
31 class unit_ability_list;
32 class unit_type;
33 namespace wfl {
34  class map_formula_callable;
35 }
36 //the 'attack type' is the type of attack, how many times it strikes,
37 //and how much damage it does.
38 class attack_type : public std::enable_shared_from_this<attack_type>
39 {
40 public:
41 
42  explicit attack_type(const config& cfg);
43  const t_string& name() const { return description_; }
44  const std::string& id() const { return id_; }
45  const std::string& type() const { return type_; }
46  const std::string& icon() const { return icon_; }
47  const std::string& range() const { return range_; }
48  int min_range() const { return min_range_; }
49  int max_range() const { return max_range_; }
50  std::string accuracy_parry_description() const;
51  int accuracy() const { return accuracy_; }
52  int parry() const { return parry_; }
53  int damage() const { return damage_; }
54  int num_attacks() const { return num_attacks_; }
55  double attack_weight() const { return attack_weight_; }
56  double defense_weight() const { return defense_weight_; }
57  const config &specials() const { return specials_; }
58 
59  void set_name(const t_string& value) { description_ = value; set_changed(true); }
60  void set_id(const std::string& value) { id_ = value; set_changed(true); }
61  void set_type(const std::string& value) { type_ = value; set_changed(true); }
62  void set_icon(const std::string& value) { icon_ = value; set_changed(true); }
63  void set_range(const std::string& value) { range_ = value; set_changed(true); }
64  void set_accuracy(int value) { accuracy_ = value; set_changed(true); }
65  void set_parry(int value) { parry_ = value; set_changed(true); }
66  void set_damage(int value) { damage_ = value; set_changed(true); }
67  void set_num_attacks(int value) { num_attacks_ = value; set_changed(true); }
68  void set_attack_weight(double value) { attack_weight_ = value; set_changed(true); }
69  void set_defense_weight(double value) { defense_weight_ = value; set_changed(true); }
70  void set_specials(config value) { specials_ = value; set_changed(true); }
71 
72 
73  // In unit_abilities.cpp:
74 
75  /**
76  * @return True iff the special @a special is active.
77  * @param special The special being checked.
78  * @param simple_check If true, check whether the unit has the special. Else, check whether the special is currently active.
79  * @param special_id If true, match @a special against the @c id of special tags.
80  * @param special_tags If true, match @a special against the tag name of special tags.
81  */
82  bool has_special(const std::string& special, bool simple_check=false, bool special_id=true, bool special_tags=true) const;
83  unit_ability_list get_specials(const std::string& special) const;
84  std::vector<std::pair<t_string, t_string>> special_tooltips(boost::dynamic_bitset<>* active_list = nullptr) const;
85  std::string weapon_specials() const;
86  std::string weapon_specials_value(const std::set<std::string> checking_tags) const;
87 
88  /** Calculates the number of attacks this weapon has, considering specials. */
89  void modified_attacks(unsigned & min_attacks,
90  unsigned & max_attacks) const;
91 
92  /** return a modified damage type and/or add a secondary_type for hybrid use if special is active. */
93  std::pair<std::string, std::string> damage_type() const;
94 
95  /** Returns the damage per attack of this weapon, considering specials. */
96  int modified_damage() const;
97 
98  /** Return the special weapon value, considering specials.
99  * @param abil_list The list of special checked.
100  * @param base_value The value modified or not by function.
101  */
102  int composite_value(const unit_ability_list& abil_list, int base_value) const;
103  /** Returns list for weapon like abilities for each ability type. */
104  unit_ability_list get_weapon_ability(const std::string& ability) const;
105  /**
106  * @param special the tag name to check for
107  * @return list which contains get_weapon_ability and get_specials list for each ability type, with overwritten items removed
108  */
109  unit_ability_list get_specials_and_abilities(const std::string& special) const;
110  /** used for abilities used like weapon
111  * @return True if the ability @a special is active.
112  * @param special The special being checked.
113  * @param special_id If true, match @a special against the @c id of special tags.
114  * @param special_tags If true, match @a special against the tag name of special tags.
115  */
116  bool has_weapon_ability(const std::string& special, bool special_id=true, bool special_tags=true) const;
117  /** used for abilities used like weapon and true specials
118  * @return True if the ability @a special is active.
119  * @param special The special being checked.
120  * @param special_id If true, match @a special against the @c id of special tags.
121  * @param special_tags If true, match @a special against the tag name of special tags.
122  */
123  bool has_special_or_ability(const std::string& special, bool special_id=true, bool special_tags=true) const;
124 
125  // In unit_types.cpp:
126 
127  bool matches_filter(const config& filter, const std::string& tag_name = "") const;
128  bool apply_modification(const config& cfg);
129  bool describe_modification(const config& cfg,std::string* description);
130 
131  int movement_used() const { return movement_used_; }
132  void set_movement_used(int value) { movement_used_ = value; }
133  int attacks_used() const { return attacks_used_; }
134  void set_attacks_used(int value) { attacks_used_ = value; }
135 
136  void write(config& cfg) const;
137  inline config to_config() const { config c; write(c); return c; }
138 
140 private:
141  // In unit_abilities.cpp:
142 
143  // Configured as a bit field, in case that is useful.
145  /**
146  * Filter a list of abilities or weapon specials, removing any entries that don't own
147  * the overwrite_specials attributes.
148  *
149  * @param overwriters list that may have overwrite_specials attributes.
150  * @param tag_name type of abilitie/special checked.
151  */
152  unit_ability_list overwrite_special_overwriter(unit_ability_list overwriters, const std::string& tag_name) const;
153  /**
154  * Check whether @a cfg would be overwritten by any element of @a overwriters.
155  *
156  * @return True if element checked is overwritable.
157  * @param overwriters list used for check if element is overwritable.
158  * @param cfg element checked.
159  * @param tag_name type of abilitie/special checked.
160  */
161  bool overwrite_special_checking(unit_ability_list& overwriters, const config& cfg, const std::string& tag_name) const;
162  /** check_self_abilities : return an boolean value for checking of activities of abilities used like weapon
163  * @return True if the special @a special is active.
164  * @param cfg the config to one special ability checked.
165  * @param special The special ability type who is being checked.
166  */
167  bool check_self_abilities(const config& cfg, const std::string& special) const;
168  /** check_adj_abilities : return an boolean value for checking of activities of abilities used like weapon
169  * @return True if the special @a special is active.
170  * @param cfg the config to one special ability checked.
171  * @param special The special ability type who is being checked.
172  * @param dir direction to research a unit adjacent to self_.
173  * @param from unit adjacent to self_ is checked.
174  */
175  bool check_adj_abilities(const config& cfg, const std::string& special, int dir, const unit& from) const;
176  bool special_active(const config& special, AFFECTS whom, const std::string& tag_name,
177  const std::string& filter_self ="filter_self") const;
178 
179 /** weapon_specials_impl_self and weapon_specials_impl_adj : check if special name can be added.
180  * @param[in,out] temp_string the string modified and returned
181  * @param[in] self the unit checked.
182  * @param[in] self_attack the attack used by unit checked in this function.
183  * @param[in] other_attack the attack used by opponent to unit checked.
184  * @param[in] self_loc location of the unit checked.
185  * @param[in] whom determine if unit affected or not by special ability.
186  * @param[in,out] checking_name the reference for checking if a name is already added
187  * @param[in] checking_tags the reference for checking if special ability type can be used
188  * @param[in] leader_bool If true, [leadership] abilities are checked.
189  */
190  static void weapon_specials_impl_self(
191  std::string& temp_string,
192  unit_const_ptr self,
193  const_attack_ptr self_attack,
194  const_attack_ptr other_attack,
195  const map_location& self_loc,
196  AFFECTS whom,
197  std::set<std::string>& checking_name,
198  const std::set<std::string>& checking_tags={},
199  bool leader_bool=false
200  );
201 
202  static void weapon_specials_impl_adj(
203  std::string& temp_string,
204  unit_const_ptr self,
205  const_attack_ptr self_attack,
206  const_attack_ptr other_attack,
207  const map_location& self_loc,
208  AFFECTS whom,
209  std::set<std::string>& checking_name,
210  const std::set<std::string>& checking_tags={},
211  const std::string& affect_adjacents="",
212  bool leader_bool=false
213  );
214  /** check_self_abilities_impl : return an boolean value for checking of activities of abilities used like weapon
215  * @return True if the special @a tag_name is active.
216  * @param self_attack the attack used by unit checked in this function.
217  * @param other_attack the attack used by opponent to unit checked.
218  * @param special the config to one special ability checked.
219  * @param u the unit checked.
220  * @param loc location of the unit checked.
221  * @param whom determine if unit affected or not by special ability.
222  * @param tag_name The special ability type who is being checked.
223  * @param leader_bool If true, [leadership] abilities are checked.
224  */
225  static bool check_self_abilities_impl(
226  const_attack_ptr self_attack,
227  const_attack_ptr other_attack,
228  const config& special,
229  unit_const_ptr u,
230  const map_location& loc,
231  AFFECTS whom,
232  const std::string& tag_name,
233  bool leader_bool=false
234  );
235 
236 
237  /** check_adj_abilities_impl : return an boolean value for checking of activities of abilities used like weapon in unit adjacent to fighter
238  * @return True if the special @a tag_name is active.
239  * @param self_attack the attack used by unit who fight.
240  * @param other_attack the attack used by opponent.
241  * @param special the config to one special ability checked.
242  * @param u the unit who is or not affected by an abilities owned by @a from.
243  * @param from unit adjacent to @a u is checked.
244  * @param dir direction to research a unit adjacent to @a u.
245  * @param loc location of the unit checked.
246  * @param whom determine if unit affected or not by special ability.
247  * @param tag_name The special ability type who is being checked.
248  * @param leader_bool If true, [leadership] abilities are checked.
249  */
250  static bool check_adj_abilities_impl(
251  const_attack_ptr self_attack,
252  const_attack_ptr other_attack,
253  const config& special,
254  unit_const_ptr u,
255  const unit& from,
256  int dir,
257  const map_location& loc,
258  AFFECTS whom,
259  const std::string& tag_name,
260  bool leader_bool=false
261  );
262 
263  static bool special_active_impl(
264  const_attack_ptr self_attack,
265  const_attack_ptr other_attack,
266  const config& special,
267  AFFECTS whom,
268  const std::string& tag_name,
269  const std::string& filter_self ="filter_self"
270  );
271 
272  // Used via specials_context() to control which specials are
273  // considered active.
274  friend class specials_context_t;
278  mutable bool is_attacker_;
280  mutable bool is_for_listing_ = false;
281 public:
283  std::shared_ptr<const attack_type> parent;
284  friend class attack_type;
285  /** Initialize weapon specials context for listing */
286  explicit specials_context_t(const attack_type& weapon, bool attacking);
287  /** Initialize weapon specials context for a unit type */
288  specials_context_t(const attack_type& weapon, const unit_type& self_type, const map_location& loc, bool attacking = true);
289  /** Initialize weapon specials context for a single unit */
290  specials_context_t(const attack_type& weapon, const_attack_ptr other_weapon,
291  unit_const_ptr self, unit_const_ptr other,
292  const map_location& self_loc, const map_location& other_loc,
293  bool attacking);
294  /** Initialize weapon specials context for a pair of units */
295  specials_context_t(const attack_type& weapon, unit_const_ptr self, const map_location& loc, bool attacking);
297  bool was_moved = false;
298  public:
299  // Destructor at least needs to be public for all this to work.
302  };
303  // Set up a specials context.
304  // Usage: auto ctx = weapon.specials_context(...);
306  const map_location& unit_loc, const map_location& other_loc,
307  bool attacking, const_attack_ptr other_attack) const {
308  return specials_context_t(*this, other_attack, self, other, unit_loc, other_loc, attacking);
309  }
310  specials_context_t specials_context(unit_const_ptr self, const map_location& loc, bool attacking = true) const {
311  return specials_context_t(*this, self, loc, attacking);
312  }
313  specials_context_t specials_context(const unit_type& self_type, const map_location& loc, bool attacking = true) const {
314  return specials_context_t(*this, self_type, loc, attacking);
315  }
316  specials_context_t specials_context_for_listing(bool attacking = true) const {
317  return specials_context_t(*this, attacking);
318  }
319  void set_changed(bool value)
320  {
321  changed_ = value;
322  }
323  bool get_changed() const
324  {
325  return changed_;
326  }
327 private:
328 
330  std::string id_;
331  std::string type_;
332  std::string icon_;
333  std::string range_;
335  int damage_;
339 
343  int parry_;
345  bool changed_;
346 };
347 
348 using attack_list = std::vector<attack_ptr>;
349 using attack_itors = boost::iterator_range<boost::indirect_iterator<attack_list::iterator>>;
350 using const_attack_itors = boost::iterator_range<boost::indirect_iterator<attack_list::const_iterator>>;
351 
353  return boost::make_iterator_range(boost::make_indirect_iterator(atks.begin()), boost::make_indirect_iterator(atks.end()));
354 }
355 
357  return boost::make_iterator_range(boost::make_indirect_iterator(atks.begin()), boost::make_indirect_iterator(atks.end()));
358 }
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:1118
std::shared_ptr< const attack_type > parent
const config & specials() const
Definition: attack_type.hpp:57
map_location other_loc_
std::string weapon_specials() const
Returns a comma-separated string of active names for the specials of *this.
Definition: abilities.cpp:913
double defense_weight() const
Definition: attack_type.hpp:56
void set_num_attacks(int value)
Definition: attack_type.hpp:67
specials_context_t specials_context(unit_const_ptr self, const map_location &loc, bool attacking=true) const
bool check_self_abilities(const config &cfg, const std::string &special) const
check_self_abilities : return an boolean value for checking of activities of abilities used like weap...
Definition: abilities.cpp:1522
bool has_special(const std::string &special, bool simple_check=false, bool special_id=true, bool special_tags=true) const
Returns whether or not *this has a special with a tag or id equal to special.
Definition: abilities.cpp:754
static bool special_active_impl(const_attack_ptr self_attack, const_attack_ptr other_attack, const config &special, AFFECTS whom, const std::string &tag_name, const std::string &filter_self="filter_self")
Returns whether or not the given special is active for the specified unit, based on the current conte...
Definition: abilities.cpp:1696
int min_range() const
Definition: attack_type.hpp:48
int composite_value(const unit_ability_list &abil_list, int base_value) const
Return the special weapon value, considering specials.
Definition: abilities.cpp:1376
double attack_weight() const
Definition: attack_type.hpp:55
const_attack_ptr other_attack_
void add_formula_context(wfl::map_formula_callable &) const
Definition: abilities.cpp:529
const std::string & range() const
Definition: attack_type.hpp:47
void set_attacks_used(int value)
map_location self_loc_
int movement_used() const
specials_context_t specials_context_for_listing(bool attacking=true) const
void set_accuracy(int value)
Definition: attack_type.hpp:64
bool get_changed() const
const std::string & type() const
Definition: attack_type.hpp:45
void set_movement_used(int value)
unit_ability_list get_weapon_ability(const std::string &ability) const
Returns list for weapon like abilities for each ability type.
Definition: abilities.cpp:1340
int parry() const
Definition: attack_type.hpp:52
std::string weapon_specials_value(const std::set< std::string > checking_tags) const
Definition: abilities.cpp:956
std::string accuracy_parry_description() const
Definition: attack_type.cpp:84
unit_ability_list get_specials_and_abilities(const std::string &special) const
Definition: abilities.cpp:1359
bool apply_modification(const config &cfg)
Modifies *this using the specifications in cfg, but only if *this matches cfg viewed as a filter.
bool overwrite_special_checking(unit_ability_list &overwriters, const config &cfg, const std::string &tag_name) const
Check whether cfg would be overwritten by any element of overwriters.
Definition: abilities.cpp:1423
void set_specials(config value)
Definition: attack_type.hpp:70
unit_const_ptr self_
bool check_adj_abilities(const config &cfg, const std::string &special, int dir, const unit &from) const
check_adj_abilities : return an boolean value for checking of activities of abilities used like weapo...
Definition: abilities.cpp:1542
friend class specials_context_t
config specials_
void set_defense_weight(double value)
Definition: attack_type.hpp:69
int num_attacks() const
Definition: attack_type.hpp:54
void set_changed(bool value)
unit_ability_list overwrite_special_overwriter(unit_ability_list overwriters, const std::string &tag_name) const
Filter a list of abilities or weapon specials, removing any entries that don't own the overwrite_spec...
Definition: abilities.cpp:1387
static bool check_adj_abilities_impl(const_attack_ptr self_attack, const_attack_ptr other_attack, const config &special, unit_const_ptr u, const unit &from, int dir, const map_location &loc, AFFECTS whom, const std::string &tag_name, bool leader_bool=false)
check_adj_abilities_impl : return an boolean value for checking of activities of abilities used like ...
Definition: abilities.cpp:1547
static void weapon_specials_impl_adj(std::string &temp_string, unit_const_ptr self, const_attack_ptr self_attack, 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="", bool leader_bool=false)
Definition: abilities.cpp:1014
std::vector< std::pair< t_string, t_string > > special_tooltips(boost::dynamic_bitset<> *active_list=nullptr) const
Returns a vector of names and descriptions for the specials of *this.
Definition: abilities.cpp:859
std::string type_
std::string icon_
void set_parry(int value)
Definition: attack_type.hpp:65
void set_attack_weight(double value)
Definition: attack_type.hpp:68
void set_damage(int value)
Definition: attack_type.hpp:66
static void weapon_specials_impl_self(std::string &temp_string, unit_const_ptr self, const_attack_ptr self_attack, 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={}, bool leader_bool=false)
weapon_specials_impl_self and weapon_specials_impl_adj : check if special name can be added.
Definition: abilities.cpp:994
const t_string & name() const
Definition: attack_type.hpp:43
bool describe_modification(const config &cfg, std::string *description)
Trimmed down version of apply_modification(), with no modifications actually made.
int attacks_used() const
const std::string & id() const
Definition: attack_type.hpp:44
void set_icon(const std::string &value)
Definition: attack_type.hpp:62
static bool check_self_abilities_impl(const_attack_ptr self_attack, const_attack_ptr other_attack, const config &special, unit_const_ptr u, const map_location &loc, AFFECTS whom, const std::string &tag_name, bool leader_bool=false)
check_self_abilities_impl : return an boolean value for checking of activities of abilities used like...
Definition: abilities.cpp:1527
double defense_weight_
std::string id_
int modified_damage() const
Returns the damage per attack of this weapon, considering specials.
Definition: abilities.cpp:1220
double attack_weight_
config to_config() const
void modified_attacks(unsigned &min_attacks, unsigned &max_attacks) const
Calculates the number of attacks this weapon has, considering specials.
Definition: abilities.cpp:1150
std::string range_
void set_id(const std::string &value)
Definition: attack_type.hpp:60
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
attack_type(const config &cfg)
Definition: attack_type.cpp:50
void set_type(const std::string &value)
Definition: attack_type.hpp:61
void write(config &cfg) const
bool matches_filter(const config &filter, const std::string &tag_name="") const
Returns whether or not *this matches the given filter.
int accuracy() const
Definition: attack_type.hpp:51
unit_const_ptr other_
int max_range() const
Definition: attack_type.hpp:49
void set_range(const std::string &value)
Definition: attack_type.hpp:63
bool special_active(const config &special, AFFECTS whom, const std::string &tag_name, const std::string &filter_self="filter_self") const
Definition: abilities.cpp:1680
unit_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:826
const std::string & icon() const
Definition: attack_type.hpp:46
specials_context_t specials_context(const unit_type &self_type, const map_location &loc, bool attacking=true) const
int damage() const
Definition: attack_type.hpp:53
bool has_special_or_ability(const std::string &special, bool special_id=true, bool special_tags=true) const
used for abilities used like weapon and true specials
Definition: abilities.cpp:1668
t_string description_
bool has_weapon_ability(const std::string &special, bool special_id=true, bool special_tags=true) const
used for abilities used like weapon
Definition: abilities.cpp:1567
void set_name(const t_string &value)
Definition: attack_type.hpp:59
std::pair< std::string, std::string > damage_type() const
return a modified damage type and/or add a secondary_type for hybrid use if special is active.
Definition: abilities.cpp:1198
bool is_for_listing_
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:161
A single unit type that the player may recruit.
Definition: types.hpp:46
This class represents a single unit of a specific type.
Definition: unit.hpp:135
Definition: contexts.hpp:44
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:38
mock_char c