The Battle for Wesnoth  1.19.25+dev
abilities.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2025
3  by Dominic Bolin <dominic.bolin@exong.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 "units/ptr.hpp"
20 #include "units/race.hpp" // for unit_race::GENDER
21 
22 
23 #include <vector>
24 class config;
25 
26 namespace wfl {
27  class map_formula_callable;
28 }
29 
31 
32 
33 using ability_vector = std::vector<ability_ptr>;
34 
36 {
37 public:
38 
39  enum class active_on_t { offense, defense, both };
40  enum class apply_to_t { self, opponent, attacker, defender, both };
42 
43  enum class affects_t { SELF = 1, OTHER = 2, EITHER = 3 };
44 
45  unit_ability_t(std::string tag, config cfg, bool inside_attack);
46 
47  static ability_ptr create(std::string tag, config cfg, bool inside_attack) {
48  return std::make_shared<unit_ability_t>(tag, cfg, inside_attack);
49  }
50 
51  static void do_compat_fixes(config& cfg, const std::string& tag, bool inside_attack);
52 
53  const std::string& tag() const { return tag_; };
54  const std::string& id() const { return id_; };
55  bool in_specials_tag() const { return in_specials_tag_; };
56  const config& cfg() const { return cfg_; };
57 
58  active_on_t active_on() const { return active_on_; };
59  apply_to_t apply_to() const { return apply_to_; };
60  double priority() const { return priority_; };
61 
64 
65  //has no effect in [specials]
67  //has no effect in [specials]
68  bool affects_self() const { return affects_self_; }
69  //has no effect in [specials]
70  bool affects_enemies() const { return affects_enemies_; }
71 
72  struct tooltip_info
73  {
76  // a unique id used for help topics, generated from name and id.
77  // doesn't include the "ability_" prefix. Derived from cfg["unique_id"].
78  std::string help_topic_id;
79  };
80 
81  //Generates a unique id to be used to identify the help page for this ability.
82  static std::string get_help_topic_id(const config& cfg);
83  std::string get_help_topic_id() const;
84 
85 
86  std::string get_name(bool is_inactive = false, unit_race::GENDER = unit_race::MALE) const;
87  std::string get_description(bool is_inactive = false, unit_race::GENDER = unit_race::MALE) const;
88 
89  //checks whether the ability is active according to the active_on= attribute.
90  bool active_on_matches(bool student_is_attacker) const;
91 
92 
93  //checks whether the ability matches the filter specified in a [filter_special] or [filter_ability]
94  bool matches_filter(const config& filter) const;
95  void write(config& abilities_cfg);
96 
97 
98  static void parse_vector(const config& abilities_cfg, ability_vector& res, bool inside_attack);
99  static config vector_to_cfg(const ability_vector& abilities);
100  static ability_vector cfg_to_vector(const config& abilities_cfg, bool inside_attack);
101 
102 
103  static ability_vector filter_tag(const ability_vector& vec, const std::string& tag);
104  static ability_vector clone(const ability_vector& vec);
105 
106  /**
107  * Substitute gettext variables in name and description of abilities and specials
108  * @param str The string in which the substitution is to be done
109  *
110  * @return The string `str` with all gettext variables substitutes with corresponding special properties
111  */
112  std::string substitute_variables(const std::string& str) const;
113 
114 
115 
117  {
118  public:
122  recursion_guard() = delete;
124 
125  /**
126  * Returns true if a level of recursion was available at the time when guard_against_recursion()
127  * created this object.
128  */
129  operator bool() const;
131  };
132 
133  /**
134  * Tests which might otherwise cause infinite recursion should call this, check that the
135  * returned object evaluates to true, and then keep the object returned as long as the
136  * recursion might occur, similar to a reentrant mutex that's limited to a small number of
137  * reentrances.
138  *
139  * This only expects to be called in a single thread
140  */
142 // recursion_guard guard_against_recursion(const attack_type& a) const;
143 
144 private:
145  std::string tag_;
146  std::string id_;
147  // abilities/specials inside [specials] tag follow a differnt syntax than in [abilities] tags, in paricular [filter_self] inside [specials] is equivalent to [filter_student] in abilities.
154  double priority_;
158 
159  mutable bool currently_checked_;
160 };
161 
162 
163 /** Data typedef for active_ability_list. */
165 {
169  , p_ability_(p_ability)
170  {
171  }
172 
173  /**
174  * Used by the formula in the ability.
175  * The REAL location of the student (not the 'we are assuming the student is at this position' location)
176  * once active_ability_list can contain abilities from different 'students', as it contains abilities from
177  * a unit aswell from its opponents (abilities with apply_to= opponent)
178  */
180  /**
181  * The location of the teacher, that is the unit who owns the ability tags
182  * (different from student because of [affect_adjacent])
183  */
185 
186  const config& ability_cfg() const { return p_ability_->cfg(); }
187  const unit_ability_t& ability() const { return *p_ability_; }
188 private:
189  /** The contents of the ability tag, never nullptr. */
191 };
192 
194 {
195 public:
197 
198  // Implemented in unit_abilities.cpp
199  std::pair<int, map_location> highest(const std::string& key, int def = 0) const
200  {
201  return get_extremum(key, def, std::less<int>());
202  }
203  std::pair<int, map_location> lowest(const std::string& key, int def = 0) const
204  {
205  return get_extremum(key, def, std::greater<int>());
206  }
207 
208  template<typename TComp>
209  std::pair<int, map_location> get_extremum(const std::string& key, int def, const TComp& comp) const;
210 
211  // The following make this class usable with standard library algorithms and such
213  typedef std::vector<active_ability>::const_iterator const_iterator;
214 
215  iterator begin() { return cfgs_.begin(); }
216  const_iterator begin() const { return cfgs_.begin(); }
217  iterator end() { return cfgs_.end(); }
218  const_iterator end() const { return cfgs_.end(); }
219 
220  // Vector access
221  bool empty() const { return cfgs_.empty(); }
222  active_ability& front() { return cfgs_.front(); }
223  const active_ability& front() const { return cfgs_.front(); }
224  active_ability& back() { return cfgs_.back(); }
225  const active_ability& back() const { return cfgs_.back(); }
226  std::size_t size() { return cfgs_.size(); }
227 
228  iterator erase(const iterator& erase_it) { return cfgs_.erase(erase_it); }
229  iterator erase(const iterator& first, const iterator& last) { return cfgs_.erase(first, last); }
230 
231  template<typename... T>
232  void emplace_back(T&&... args) { cfgs_.emplace_back(args...); }
233 
234  const map_location& loc() const { return loc_; }
235 
236  /** Appends the abilities from @a other to @a this, ignores other.loc() */
237  void append(const active_ability_list& other)
238  {
239  std::copy(other.begin(), other.end(), std::back_inserter(cfgs_));
240  }
241 
242  /**
243  * Appends any abilities from @a other for which the given condition returns true to @a this, ignores other.loc().
244  *
245  * @param other where to copy the elements from
246  * @param predicate a single-argument function that takes a reference to an element and returns a bool
247  */
248  template<typename Predicate>
249  void append_if(const active_ability_list& other, const Predicate& predicate)
250  {
251  std::copy_if(other.begin(), other.end(), std::back_inserter(cfgs_), predicate);
252  }
253 
254 private:
255  // Data
256  std::vector<active_ability> cfgs_;
258 };
259 
261 
262 public:
267  };
268 
271 
274 
276  {
277  return specials_context_t{
278  {
279  std::move(attacking ? self : other),
280  } , {
281  std::move(attacking ? other : self),
282  }
283  };
284  }
285 
286  void set_for_listing(bool for_listing)
287  {
288  is_for_listing = for_listing;
289  }
290 
292  const specials_combatant& self;
294  };
295 
297  {
298  return &self_att == attacker.at.get() ? self_and_other_ref{ attacker, defender } : self_and_other_ref{ defender, attacker };
299  }
300  self_and_other_ref self_and_other(const unit& self_un) const
301  {
302  return &self_un == attacker.un.get() ? self_and_other_ref{ attacker, defender } : self_and_other_ref{ defender, attacker };
303  }
304 
305  const specials_combatant& other(const specials_combatant& self) const
306  {
307  return &self == &attacker ? defender : attacker;
308  }
309 
313 
314  active_ability_list get_active_specials(const attack_type& at, const std::string& tag) const;
315 
316  active_ability_list get_abilities_weapons(const std::string& tag, const unit& un) const;
317 
318  bool has_active_special(const attack_type& at, const std::string& tag) const;
319  bool has_active_special_id(const attack_type& at, const std::string& id) const;
321 
322  static bool has_active_ability_id(const unit& un, map_location loc, const std::string& id);
323  static bool has_active_ability_matching_filter(const unit& un, map_location loc, const config& filter);
324 
325  bool is_special_active(const specials_combatant& wep, const unit_ability_t& ab, unit_ability_t::affects_t whom) const;
326 
327  void add_formula_context(wfl::map_formula_callable& callable) const;
328 
329  std::vector<unit_ability_t::tooltip_info> special_tooltips(const attack_type& at, boost::dynamic_bitset<>& active_list) const;
330  std::vector<unit_ability_t::tooltip_info> abilities_special_tooltips(const attack_type& at, boost::dynamic_bitset<>& active_list) const;
331 
332  std::string describe_weapon_specials(const attack_type& at) const;
333  std::string describe_weapon_specials_value(const attack_type& at, const std::set<std::string>& checking_tags) const;
334 
336 
337 };
338 
339 namespace unit_abilities
340 {
341 bool filter_base_matches(const config& cfg, int def);
342 
344 
346 
348 {
349  void set(value_modifier t, int val, const config& abil,const map_location &l);
351  int value{0};
352  const config* ability{nullptr};
354 };
355 
356 class effect
357 {
358  public:
359  effect(active_ability_list list, int def, const specials_context_t* ctx = nullptr, EFFECTS wham = EFFECT_DEFAULT);
360  // Provide read-only access to the effect list:
361  typedef std::vector<individual_effect>::const_iterator iterator;
362  typedef std::vector<individual_effect>::const_iterator const_iterator;
363 
365  { return composite_value_; }
367  { return composite_double_value_; }
369  { return effect_list_.begin(); }
371  { return effect_list_.end(); }
372  private:
373  /** Part of the constructor, calculates for a group of abilities with equal priority. */
374  void effect_impl(const active_ability_list& list, int def, const specials_context_t* ctx, EFFECTS wham);
375  std::vector<individual_effect> effect_list_;
378 };
379 
380 
381 }
std::vector< ability_ptr > ability_vector
Definition: abilities.hpp:33
map_location loc
Definition: move.cpp:172
double t
Definition: astarsearch.cpp:63
std::vector< active_ability >::iterator iterator
Definition: abilities.hpp:212
void append_if(const active_ability_list &other, const Predicate &predicate)
Appends any abilities from other for which the given condition returns true to this,...
Definition: abilities.hpp:249
active_ability & front()
Definition: abilities.hpp:222
iterator erase(const iterator &first, const iterator &last)
Definition: abilities.hpp:229
std::vector< active_ability >::const_iterator const_iterator
Definition: abilities.hpp:213
std::pair< int, map_location > highest(const std::string &key, int def=0) const
Definition: abilities.hpp:199
std::vector< active_ability > cfgs_
Definition: abilities.hpp:256
iterator erase(const iterator &erase_it)
Definition: abilities.hpp:228
const map_location & loc() const
Definition: abilities.hpp:234
const_iterator begin() const
Definition: abilities.hpp:216
std::pair< int, map_location > get_extremum(const std::string &key, int def, const TComp &comp) const
Definition: abilities.cpp:970
void emplace_back(T &&... args)
Definition: abilities.hpp:232
active_ability & back()
Definition: abilities.hpp:224
const active_ability & front() const
Definition: abilities.hpp:223
active_ability_list(const map_location &loc=map_location())
Definition: abilities.hpp:196
map_location loc_
Definition: abilities.hpp:257
void append(const active_ability_list &other)
Appends the abilities from other to this, ignores other.loc()
Definition: abilities.hpp:237
const_iterator end() const
Definition: abilities.hpp:218
std::pair< int, map_location > lowest(const std::string &key, int def=0) const
Definition: abilities.hpp:203
bool empty() const
Definition: abilities.hpp:221
const active_ability & back() const
Definition: abilities.hpp:225
std::size_t size()
Definition: abilities.hpp:226
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:157
self_and_other_ref self_and_other(const attack_type &self_att) const
Definition: abilities.hpp:296
bool has_active_special(const attack_type &at, const std::string &tag) const
Returns whether or not *this has a special ability with a tag or id equal to special.
Definition: abilities.cpp:1530
void set_for_listing(bool for_listing)
Definition: abilities.hpp:286
active_ability_list get_abilities_weapons(const std::string &tag, const unit &un) const
Definition: abilities.cpp:1616
bool is_special_active(const specials_combatant &wep, const unit_ability_t &ab, unit_ability_t::affects_t whom) const
Returns whether or not the given special is active for the specified unit, based on the current conte...
Definition: abilities.cpp:1911
specials_combatant defender
Definition: abilities.hpp:311
std::vector< unit_ability_t::tooltip_info > special_tooltips(const attack_type &at, boost::dynamic_bitset<> &active_list) const
Returns a vector of names and descriptions for the specials of *this.
Definition: abilities.cpp:1316
static bool has_active_ability_matching_filter(const unit &un, map_location loc, const config &filter)
Definition: abilities.cpp:1862
std::string describe_weapon_specials_value(const attack_type &at, const std::set< std::string > &checking_tags) const
Definition: abilities.cpp:1115
specials_combatant attacker
Definition: abilities.hpp:310
const specials_combatant & other(const specials_combatant &self) const
Definition: abilities.hpp:305
std::string describe_weapon_specials(const attack_type &at) const
Returns a comma-separated string of active names for the specials of *this.
Definition: abilities.cpp:1071
void add_formula_context(wfl::map_formula_callable &callable) const
Definition: abilities.cpp:894
bool has_active_special_id(const attack_type &at, const std::string &id) const
Definition: abilities.cpp:1541
specials_context_t(specials_context_t &&)=delete
std::vector< unit_ability_t::tooltip_info > abilities_special_tooltips(const attack_type &at, boost::dynamic_bitset<> &active_list) const
Definition: abilities.cpp:1389
self_and_other_ref self_and_other(const unit &self_un) const
Definition: abilities.hpp:300
bool has_active_special_matching_filter(const attack_type &at, const config &filter) const
Definition: abilities.cpp:1846
static specials_context_t make(specials_combatant &&self, specials_combatant &&other, bool attacking)
Definition: abilities.hpp:275
active_ability_list get_active_specials(const attack_type &at, const std::string &tag) const
Definition: abilities.cpp:1592
static bool has_active_ability_id(const unit &un, map_location loc, const std::string &id)
Definition: abilities.cpp:1873
specials_context_t(const specials_context_t &)=delete
active_ability_list get_active_combat_teachers(const attack_type &at) const
Definition: abilities.cpp:1559
int get_composite_value() const
Definition: abilities.hpp:364
std::vector< individual_effect > effect_list_
Definition: abilities.hpp:375
const_iterator end() const
Definition: abilities.hpp:370
double get_composite_double_value() const
Definition: abilities.hpp:366
effect(active_ability_list list, int def, const specials_context_t *ctx=nullptr, EFFECTS wham=EFFECT_DEFAULT)
Definition: abilities.cpp:2104
std::vector< individual_effect >::const_iterator const_iterator
Definition: abilities.hpp:362
std::vector< individual_effect >::const_iterator iterator
Definition: abilities.hpp:361
void effect_impl(const active_ability_list &list, int def, const specials_context_t *ctx, EFFECTS wham)
Part of the constructor, calculates for a group of abilities with equal priority.
Definition: abilities.cpp:2128
const_iterator begin() const
Definition: abilities.hpp:368
const unit_ability_t * parent
Definition: abilities.hpp:130
recursion_guard(recursion_guard &&)=delete
recursion_guard(const recursion_guard &)=delete
std::string substitute_variables(const std::string &str) const
Substitute gettext variables in name and description of abilities and specials.
Definition: abilities.cpp:315
const std::string & tag() const
Definition: abilities.hpp:53
double suppress_special_priority_
Definition: abilities.hpp:155
bool in_specials_tag_
Definition: abilities.hpp:148
double suppress_special_priority() const
Definition: abilities.hpp:62
apply_to_t apply_to() const
Definition: abilities.hpp:59
static config vector_to_cfg(const ability_vector &abilities)
Definition: abilities.cpp:300
static void do_compat_fixes(config &cfg, const std::string &tag, bool inside_attack)
Definition: abilities.cpp:185
const config & cfg() const
Definition: abilities.hpp:56
static void parse_vector(const config &abilities_cfg, ability_vector &res, bool inside_attack)
Definition: abilities.cpp:266
bool affects_enemies() const
Definition: abilities.hpp:70
std::string get_description(bool is_inactive=false, unit_race::GENDER=unit_race::MALE) const
Definition: abilities.cpp:379
std::string id_
Definition: abilities.hpp:146
bool matches_filter(const config &filter) const
Definition: abilities.cpp:1841
active_on_t active_on() const
Definition: abilities.hpp:58
bool in_specials_tag() const
Definition: abilities.hpp:55
active_on_t active_on_
Definition: abilities.hpp:149
static ability_vector filter_tag(const ability_vector &vec, const std::string &tag)
Definition: abilities.cpp:280
double priority_
Definition: abilities.hpp:154
double priority() const
Definition: abilities.hpp:60
const std::string & id() const
Definition: abilities.hpp:54
unit_ability_t(std::string tag, config cfg, bool inside_attack)
Definition: abilities.cpp:124
double suppress_ability_priority() const
Definition: abilities.hpp:63
static ability_ptr create(std::string tag, config cfg, bool inside_attack)
Definition: abilities.hpp:47
bool currently_checked_
Definition: abilities.hpp:159
affects_allies_t affects_allies_
Definition: abilities.hpp:151
std::string tag_
Definition: abilities.hpp:145
static ability_vector clone(const ability_vector &vec)
Definition: abilities.cpp:291
std::string get_name(bool is_inactive=false, unit_race::GENDER=unit_race::MALE) const
Definition: abilities.cpp:372
std::string get_help_topic_id() const
Definition: abilities.cpp:260
recursion_guard guard_against_recursion(const unit &u) const
Tests which might otherwise cause infinite recursion should call this, check that the returned object...
Definition: abilities.cpp:421
void write(config &abilities_cfg)
Definition: abilities.cpp:310
double suppress_ability_priority_
Definition: abilities.hpp:156
static ability_vector cfg_to_vector(const config &abilities_cfg, bool inside_attack)
Definition: abilities.cpp:273
affects_allies_t affects_allies() const
Definition: abilities.hpp:66
apply_to_t apply_to_
Definition: abilities.hpp:150
bool affects_enemies_
Definition: abilities.hpp:153
bool active_on_matches(bool student_is_attacker) const
Definition: abilities.cpp:386
bool affects_self() const
Definition: abilities.hpp:68
@ MALE
Definition: race.hpp:28
This class represents a single unit of a specific type.
Definition: unit.hpp:39
const config * cfg
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
Definition: markup.hpp:45
static std::string at(const std::string &file, int line)
bool filter_base_matches(const config &cfg, int def)
Definition: abilities.cpp:2069
@ EFFECT_WITHOUT_CLAMP_MIN_MAX
Definition: abilities.hpp:345
constexpr auto filter
Definition: ranges.hpp:42
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
Definition: callable.hpp:26
std::shared_ptr< const unit_ability_t > const_ability_ptr
Definition: ptr.hpp:39
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
std::shared_ptr< unit_ability_t > ability_ptr
Definition: ptr.hpp:38
Data typedef for active_ability_list.
Definition: abilities.hpp:165
active_ability(const ability_ptr &p_ability, map_location student_loc, map_location teacher_loc)
Definition: abilities.hpp:166
const config & ability_cfg() const
Definition: abilities.hpp:186
map_location teacher_loc
The location of the teacher, that is the unit who owns the ability tags (different from student becau...
Definition: abilities.hpp:184
const unit_ability_t & ability() const
Definition: abilities.hpp:187
const_ability_ptr p_ability_
The contents of the ability tag, never nullptr.
Definition: abilities.hpp:190
map_location student_loc
Used by the formula in the ability.
Definition: abilities.hpp:179
Encapsulates the map of the game.
Definition: location.hpp:46
static const map_location & null_location()
Definition: location.hpp:103
const specials_combatant & other
Definition: abilities.hpp:293
void set(value_modifier t, int val, const config &abil, const map_location &l)
Definition: abilities.cpp:2061