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