The Battle for Wesnoth  1.19.19+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 
62  //has no effect in [specials]
64  //has no effect in [specials]
65  bool affects_self() const { return affects_self_; }
66  //has no effect in [specials]
67  bool affects_enemies() const { return affects_enemies_; }
68 
69  struct tooltip_info
70  {
73  // a unique id used for help topics, generated from name and id.
74  // doesn't include the "ability_" prefix.
75  // TODO: maybe use cfg["unique_id"] at some point?
76  std::string help_topic_id;
77  };
78 
79  //Generates a unique id to be used to identify the help page for this ability.
80  static std::string get_help_topic_id(const config& cfg);
81  std::string get_help_topic_id() const;
82 
83 
84  std::string get_name(bool is_inactive = false, unit_race::GENDER = unit_race::MALE) const;
85  std::string get_description(bool is_inactive = false, unit_race::GENDER = unit_race::MALE) const;
86 
87  //checks whether the ability is active according to the active_on= attribute.
88  bool active_on_matches(bool student_is_attacker) const;
89 
90 
91  //checks whether the ability matches the filter specified in a [filter_special] or [filter_ability]
92  bool matches_filter(const config& filter) const;
93  void write(config& abilities_cfg);
94 
95 
96  static void parse_vector(const config& abilities_cfg, ability_vector& res, bool inside_attack);
97  static config vector_to_cfg(const ability_vector& abilities);
98  static ability_vector cfg_to_vector(const config& abilities_cfg, bool inside_attack);
99 
100 
101  static ability_vector filter_tag(const ability_vector& vec, const std::string& tag);
102  static ability_vector clone(const ability_vector& vec);
103 
104  /**
105  * Substitute gettext variables in name and description of abilities and specials
106  * @param str The string in which the substitution is to be done
107  *
108  * @return The string `str` with all gettext variables substitutes with corresponding special properties
109  */
110  std::string substitute_variables(const std::string& str) const;
111 
112 
113 
115  {
116  public:
120  recursion_guard() = delete;
122 
123  /**
124  * Returns true if a level of recursion was available at the time when guard_against_recursion()
125  * created this object.
126  */
127  operator bool() const;
129  };
130 
131  /**
132  * Tests which might otherwise cause infinite recursion should call this, check that the
133  * returned object evaluates to true, and then keep the object returned as long as the
134  * recursion might occur, similar to a reentrant mutex that's limited to a small number of
135  * reentrances.
136  *
137  * This only expects to be called in a single thread
138  */
140 // recursion_guard guard_against_recursion(const attack_type& a) const;
141 
142 private:
143  std::string tag_;
144  std::string id_;
145  // 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.
152  double priority_;
154 
155  mutable bool currently_checked_;
156 };
157 
158 
159 /** Data typedef for active_ability_list. */
161 {
165  , p_ability_(p_ability)
166  {
167  }
168 
169  /**
170  * Used by the formula in the ability.
171  * The REAL location of the student (not the 'we are assuming the student is at this position' location)
172  * once active_ability_list can contain abilities from different 'students', as it contains abilities from
173  * a unit aswell from its opponents (abilities with apply_to= opponent)
174  */
176  /**
177  * The location of the teacher, that is the unit who owns the ability tags
178  * (different from student because of [affect_adjacent])
179  */
181 
182  const config& ability_cfg() const { return p_ability_->cfg(); }
183  const unit_ability_t& ability() const { return *p_ability_; }
184 private:
185  /** The contents of the ability tag, never nullptr. */
187 };
188 
190 {
191 public:
193 
194  // Implemented in unit_abilities.cpp
195  std::pair<int, map_location> highest(const std::string& key, int def = 0) const
196  {
197  return get_extremum(key, def, std::less<int>());
198  }
199  std::pair<int, map_location> lowest(const std::string& key, int def = 0) const
200  {
201  return get_extremum(key, def, std::greater<int>());
202  }
203 
204  template<typename TComp>
205  std::pair<int, map_location> get_extremum(const std::string& key, int def, const TComp& comp) const;
206 
207  // The following make this class usable with standard library algorithms and such
209  typedef std::vector<active_ability>::const_iterator const_iterator;
210 
211  iterator begin() { return cfgs_.begin(); }
212  const_iterator begin() const { return cfgs_.begin(); }
213  iterator end() { return cfgs_.end(); }
214  const_iterator end() const { return cfgs_.end(); }
215 
216  // Vector access
217  bool empty() const { return cfgs_.empty(); }
218  active_ability& front() { return cfgs_.front(); }
219  const active_ability& front() const { return cfgs_.front(); }
220  active_ability& back() { return cfgs_.back(); }
221  const active_ability& back() const { return cfgs_.back(); }
222  std::size_t size() { return cfgs_.size(); }
223 
224  iterator erase(const iterator& erase_it) { return cfgs_.erase(erase_it); }
225  iterator erase(const iterator& first, const iterator& last) { return cfgs_.erase(first, last); }
226 
227  template<typename... T>
228  void emplace_back(T&&... args) { cfgs_.emplace_back(args...); }
229 
230  const map_location& loc() const { return loc_; }
231 
232  /** Appends the abilities from @a other to @a this, ignores other.loc() */
233  void append(const active_ability_list& other)
234  {
235  std::copy(other.begin(), other.end(), std::back_inserter(cfgs_));
236  }
237 
238  /**
239  * Appends any abilities from @a other for which the given condition returns true to @a this, ignores other.loc().
240  *
241  * @param other where to copy the elements from
242  * @param predicate a single-argument function that takes a reference to an element and returns a bool
243  */
244  template<typename Predicate>
245  void append_if(const active_ability_list& other, const Predicate& predicate)
246  {
247  std::copy_if(other.begin(), other.end(), std::back_inserter(cfgs_), predicate);
248  }
249 
250 private:
251  // Data
252  std::vector<active_ability> cfgs_;
254 };
255 
257 
258 public:
263  };
264 
267 
270 
272  {
273  return specials_context_t{
274  {
275  std::move(attacking ? self : other),
276  } , {
277  std::move(attacking ? other : self),
278  }
279  };
280  }
281 
282  void set_for_listing(bool for_listing)
283  {
284  is_for_listing = for_listing;
285  }
286 
288  const specials_combatant& self;
290  };
291 
293  {
294  return &self_att == attacker.at.get() ? self_and_other_ref{ attacker, defender } : self_and_other_ref{ defender, attacker };
295  }
296  self_and_other_ref self_and_other(const unit& self_un) const
297  {
298  return &self_un == attacker.un.get() ? self_and_other_ref{ attacker, defender } : self_and_other_ref{ defender, attacker };
299  }
300 
301  const specials_combatant& other(const specials_combatant& self) const
302  {
303  return &self == &attacker ? defender : attacker;
304  }
305 
309 
310  active_ability_list get_active_specials(const attack_type& at, const std::string& tag) const;
311 
312  active_ability_list get_abilities_weapons(const std::string& tag, const unit& un) const;
313 
314  bool has_active_special(const attack_type& at, const std::string& tag) const;
315  bool has_active_special_id(const attack_type& at, const std::string& id) const;
317 
318  bool is_special_active(const specials_combatant& wep, const unit_ability_t& ab, unit_ability_t::affects_t whom) const;
319 
320  void add_formula_context(wfl::map_formula_callable& callable) const;
321 
322  std::vector<unit_ability_t::tooltip_info> special_tooltips(const attack_type& at, boost::dynamic_bitset<>& active_list) const;
323  std::vector<unit_ability_t::tooltip_info> abilities_special_tooltips(const attack_type& at, boost::dynamic_bitset<>& active_list) const;
324 
325  std::string describe_weapon_specials(const attack_type& at) const;
326  std::string describe_weapon_specials_value(const attack_type& at, const std::set<std::string>& checking_tags) const;
327 
329 
330 };
331 
332 namespace unit_abilities
333 {
334 bool filter_base_matches(const config& cfg, int def);
335 
337 
339 
341 {
342  void set(value_modifier t, int val, const config& abil,const map_location &l);
344  int value{0};
345  const config* ability{nullptr};
347 };
348 
349 class effect
350 {
351  public:
352  effect(const active_ability_list& list, int def, const const_attack_ptr& attacker = const_attack_ptr(), EFFECTS wham = EFFECT_DEFAULT);
353  // Provide read-only access to the effect list:
354  typedef std::vector<individual_effect>::const_iterator iterator;
355  typedef std::vector<individual_effect>::const_iterator const_iterator;
356 
358  { return composite_value_; }
360  { return composite_double_value_; }
362  { return effect_list_.begin(); }
364  { return effect_list_.end(); }
365  private:
366  /** Part of the constructor, calculates for a group of abilities with equal priority. */
367  void effect_impl(const active_ability_list& list, int def, const const_attack_ptr& att, EFFECTS wham);
368  std::vector<individual_effect> effect_list_;
371 };
372 
373 
374 }
std::vector< ability_ptr > ability_vector
Definition: abilities.hpp:33
double t
Definition: astarsearch.cpp:63
std::vector< active_ability >::iterator iterator
Definition: abilities.hpp:208
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:245
active_ability & front()
Definition: abilities.hpp:218
iterator erase(const iterator &first, const iterator &last)
Definition: abilities.hpp:225
std::vector< active_ability >::const_iterator const_iterator
Definition: abilities.hpp:209
std::pair< int, map_location > highest(const std::string &key, int def=0) const
Definition: abilities.hpp:195
std::vector< active_ability > cfgs_
Definition: abilities.hpp:252
iterator erase(const iterator &erase_it)
Definition: abilities.hpp:224
const map_location & loc() const
Definition: abilities.hpp:230
const_iterator begin() const
Definition: abilities.hpp:212
std::pair< int, map_location > get_extremum(const std::string &key, int def, const TComp &comp) const
Definition: abilities.cpp:940
void emplace_back(T &&... args)
Definition: abilities.hpp:228
active_ability & back()
Definition: abilities.hpp:220
const active_ability & front() const
Definition: abilities.hpp:219
active_ability_list(const map_location &loc=map_location())
Definition: abilities.hpp:192
map_location loc_
Definition: abilities.hpp:253
void append(const active_ability_list &other)
Appends the abilities from other to this, ignores other.loc()
Definition: abilities.hpp:233
const_iterator end() const
Definition: abilities.hpp:214
std::pair< int, map_location > lowest(const std::string &key, int def=0) const
Definition: abilities.hpp:199
bool empty() const
Definition: abilities.hpp:217
const active_ability & back() const
Definition: abilities.hpp:221
std::size_t size()
Definition: abilities.hpp:222
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:292
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:1521
void set_for_listing(bool for_listing)
Definition: abilities.hpp:282
active_ability_list get_abilities_weapons(const std::string &tag, const unit &un) const
Definition: abilities.cpp:1607
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:1879
specials_combatant defender
Definition: abilities.hpp:307
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:1282
std::string describe_weapon_specials_value(const attack_type &at, const std::set< std::string > &checking_tags) const
Definition: abilities.cpp:1084
specials_combatant attacker
Definition: abilities.hpp:306
const specials_combatant & other(const specials_combatant &self) const
Definition: abilities.hpp:301
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:1041
void add_formula_context(wfl::map_formula_callable &callable) const
Definition: abilities.cpp:864
bool has_active_special_id(const attack_type &at, const std::string &id) const
Definition: abilities.cpp:1532
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:1355
self_and_other_ref self_and_other(const unit &self_un) const
Definition: abilities.hpp:296
bool has_active_special_matching_filter(const attack_type &at, const config &filter) const
Definition: abilities.cpp:1834
static specials_context_t make(specials_combatant &&self, specials_combatant &&other, bool attacking)
Definition: abilities.hpp:271
active_ability_list get_active_specials(const attack_type &at, const std::string &tag) const
Definition: abilities.cpp:1583
specials_context_t(const specials_context_t &)=delete
active_ability_list get_active_combat_teachers(const attack_type &at) const
Definition: abilities.cpp:1550
int get_composite_value() const
Definition: abilities.hpp:357
std::vector< individual_effect > effect_list_
Definition: abilities.hpp:368
effect(const active_ability_list &list, int def, const const_attack_ptr &attacker=const_attack_ptr(), EFFECTS wham=EFFECT_DEFAULT)
Definition: abilities.cpp:2024
const_iterator end() const
Definition: abilities.hpp:363
double get_composite_double_value() const
Definition: abilities.hpp:359
std::vector< individual_effect >::const_iterator const_iterator
Definition: abilities.hpp:355
std::vector< individual_effect >::const_iterator iterator
Definition: abilities.hpp:354
const_iterator begin() const
Definition: abilities.hpp:361
void effect_impl(const active_ability_list &list, int def, const const_attack_ptr &att, EFFECTS wham)
Part of the constructor, calculates for a group of abilities with equal priority.
Definition: abilities.cpp:2044
const unit_ability_t * parent
Definition: abilities.hpp:128
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:298
const std::string & tag() const
Definition: abilities.hpp:53
bool in_specials_tag_
Definition: abilities.hpp:146
apply_to_t apply_to() const
Definition: abilities.hpp:59
static config vector_to_cfg(const ability_vector &abilities)
Definition: abilities.cpp:283
static void do_compat_fixes(config &cfg, const std::string &tag, bool inside_attack)
Definition: abilities.cpp:168
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:249
bool affects_enemies() const
Definition: abilities.hpp:67
std::string get_description(bool is_inactive=false, unit_race::GENDER=unit_race::MALE) const
Definition: abilities.cpp:362
std::string id_
Definition: abilities.hpp:144
bool matches_filter(const config &filter) const
Definition: abilities.cpp:1829
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:147
static ability_vector filter_tag(const ability_vector &vec, const std::string &tag)
Definition: abilities.cpp:263
double priority_
Definition: abilities.hpp:152
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:123
static ability_ptr create(std::string tag, config cfg, bool inside_attack)
Definition: abilities.hpp:47
bool currently_checked_
Definition: abilities.hpp:155
affects_allies_t affects_allies_
Definition: abilities.hpp:149
std::string tag_
Definition: abilities.hpp:143
static ability_vector clone(const ability_vector &vec)
Definition: abilities.cpp:274
std::string get_name(bool is_inactive=false, unit_race::GENDER=unit_race::MALE) const
Definition: abilities.cpp:355
std::string get_help_topic_id() const
Definition: abilities.cpp:243
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:404
void write(config &abilities_cfg)
Definition: abilities.cpp:293
static ability_vector cfg_to_vector(const config &abilities_cfg, bool inside_attack)
Definition: abilities.cpp:256
affects_allies_t affects_allies() const
Definition: abilities.hpp:63
apply_to_t apply_to_
Definition: abilities.hpp:148
bool affects_enemies_
Definition: abilities.hpp:151
bool active_on_matches(bool student_is_attacker) const
Definition: abilities.cpp:369
bool affects_self() const
Definition: abilities.hpp:65
@ 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:1989
@ EFFECT_WITHOUT_CLAMP_MIN_MAX
Definition: abilities.hpp:338
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:161
active_ability(const ability_ptr &p_ability, map_location student_loc, map_location teacher_loc)
Definition: abilities.hpp:162
const config & ability_cfg() const
Definition: abilities.hpp:182
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:180
const unit_ability_t & ability() const
Definition: abilities.hpp:183
const_ability_ptr p_ability_
The contents of the ability tag, never nullptr.
Definition: abilities.hpp:186
map_location student_loc
Used by the formula in the ability.
Definition: abilities.hpp:175
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:289
void set(value_modifier t, int val, const config &abil, const map_location &l)
Definition: abilities.cpp:1981