The Battle for Wesnoth  1.17.23+dev
unit.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 "movetype.hpp"
20 #include "units/id.hpp"
21 #include "units/ptr.hpp"
22 #include "units/attack_type.hpp"
23 #include "units/race.hpp"
24 #include "utils/variant.hpp"
25 
26 #include <boost/dynamic_bitset_fwd.hpp>
27 
28 #include <bitset>
29 #include <optional>
30 
31 class display;
32 class team;
35 class vconfig;
36 struct color_t;
37 
38 /** Data typedef for unit_ability_list. */
40 {
45  {
46  }
47 
48  /**
49  * Used by the formula in the ability.
50  * The REAL location of the student (not the 'we are assuming the student is at this position' location)
51  * once unit_ability_list can contain abilities from different 'students', as it contains abilities from
52  * a unit aswell from its opponents (abilities with apply_to= opponent)
53  */
55  /**
56  * The location of the teacher, that is the unit who owns the ability tags
57  * (different from student because of [affect_adjacent])
58  */
60  /** The contents of the ability tag, never nullptr. */
62 };
63 
65 {
66 public:
68 
69  // Implemented in unit_abilities.cpp
70  std::pair<int, map_location> highest(const std::string& key, int def=0) const
71  {
72  return get_extremum(key, def, std::less<int>());
73  }
74  std::pair<int, map_location> lowest(const std::string& key, int def=0) const
75  {
76  return get_extremum(key, def, std::greater<int>());
77  }
78 
79  template<typename TComp>
80  std::pair<int, map_location> get_extremum(const std::string& key, int def, const TComp& comp) const;
81 
82  // The following make this class usable with standard library algorithms and such
84  typedef std::vector<unit_ability>::const_iterator const_iterator;
85 
86  iterator begin() { return cfgs_.begin(); }
87  const_iterator begin() const { return cfgs_.begin(); }
88  iterator end() { return cfgs_.end(); }
89  const_iterator end() const { return cfgs_.end(); }
90 
91  // Vector access
92  bool empty() const { return cfgs_.empty(); }
93  unit_ability& front() { return cfgs_.front(); }
94  const unit_ability& front() const { return cfgs_.front(); }
95  unit_ability& back() { return cfgs_.back(); }
96  const unit_ability& back() const { return cfgs_.back(); }
97  std::size_t size() { return cfgs_.size(); }
98 
99  iterator erase(const iterator& erase_it) { return cfgs_.erase(erase_it); }
100  iterator erase(const iterator& first, const iterator& last) { return cfgs_.erase(first, last); }
101 
102  template<typename... T>
103  void emplace_back(T&&... args) { cfgs_.emplace_back(args...); }
104 
105  const map_location& loc() const { return loc_; }
106 
107  /** Appends the abilities from @a other to @a this, ignores other.loc() */
108  void append(const unit_ability_list& other)
109  {
110  std::copy(other.begin(), other.end(), std::back_inserter(cfgs_ ));
111  }
112 
113  /**
114  * Appends any abilities from @a other for which the given condition returns true to @a this, ignores other.loc().
115  *
116  * @param other where to copy the elements from
117  * @param predicate a single-argument function that takes a reference to an element and returns a bool
118  */
119  template<typename Predicate>
120  void append_if(const unit_ability_list& other, const Predicate& predicate)
121  {
122  std::copy_if(other.begin(), other.end(), std::back_inserter(cfgs_ ), predicate);
123  }
124 
125 private:
126  // Data
127  std::vector<unit_ability> cfgs_;
129 };
130 
131 /**
132  * This class represents a *single* unit of a specific type.
133  */
134 class unit : public std::enable_shared_from_this<unit>
135 {
136 public:
137  /**
138  * Clear this unit status cache for all units. Currently only the hidden
139  * status of units is cached this way.
140  */
141  static void clear_status_caches();
142 
143  /** The path to the leader crown overlay. */
144  static const std::string& leader_crown();
145 
146 private:
147  void init(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr);
148 
149  void init(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS, const std::string& variation = "");
150 
151  // Copy constructor
152  unit(const unit& u);
153 
154  struct unit_ctor_t {};
155 
156 public:
157  //private default ctor, butusing constructor to allow calling make_shared<unit> in create().
158  unit(unit_ctor_t);
159  unit() = delete;
160 
161 private:
163  {
177  //note that UA_ATTACKS only tracks added/deleted attacks, not modified attacks.
184  UA_COUNT
185  };
186 
188  {
189  changed_attributes_[int(attr)] = true;
190  }
191 
192  bool get_attacks_changed() const;
193 
195  {
196  return changed_attributes_[int(attr)];
197  }
198 
200 
201 public:
202  /** Initializes a unit from a config */
203  static unit_ptr create(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr)
204  {
205  unit_ptr res = std::make_shared<unit>(unit_ctor_t());
206  res->init(cfg, use_traits, vcfg);
207  return res;
208  }
209 
210  /**
211  * Initializes a unit from a unit type.
212  *
213  * Only real_unit-s should have random traits, name and gender (to prevent OOS caused by RNG calls)
214  */
215  static unit_ptr create(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS, const std::string& variation = "")
216  {
217  unit_ptr res = std::make_shared<unit>(unit_ctor_t());
218  res->init(t, side, real_unit, gender, variation);
219 
220  return res;
221  }
222 
223  unit_ptr clone() const
224  {
225  return std::shared_ptr<unit>(new unit(*this));
226  }
227 
228  virtual ~unit();
229 
230  unit& operator=(const unit&) = delete;
231 
232  /**
233  * @defgroup unit_advance Advancement functions
234  * @{
235  */
236 
237  /** Advances this unit to another type */
238  void advance_to(const unit_type& t, bool use_traits = false);
239 
240  using advances_to_t = std::vector<std::string>;
241  /**
242  * Gets the possible types this unit can advance to on level-up.
243  *
244  * @returns A list of type IDs this unit may advance to.
245  */
246  const advances_to_t& advances_to() const
247  {
248  return advances_to_;
249  }
250 
251  /**
252  * Gets the names of the possible types this unit can advance to on level-up.
253  *
254  * @returns A list of the names of the types this unit may advance to.
255  */
256  const std::vector<std::string> advances_to_translated() const;
257 
258  /**
259  * Sets this unit's advancement options.
260  *
261  * @param advances_to A list of new type IDs this unit may advance to.
262  */
263  void set_advances_to(const std::vector<std::string>& advances_to);
264 
265  /**
266  * Checks whether this unit has any options to advance to.
267  *
268  * This considers both whether it has types to advance to OR whether any modifications
269  * specify non-type advancement options.
270  *
271  * Note this does not consider unit experience at all, it only checks option availability.
272  * See @ref advances if an experience check is necessary.
273  */
274  bool can_advance() const
275  {
276  return !advances_to_.empty() || !get_modification_advances().empty();
277  }
278 
279  /**
280  * Checks whether this unit is eligible for level-up.
281  *
282  * @retval true This unit has sufficient experience to level up and has advancement
283  * options available.
284  */
285  bool advances() const
286  {
287  return experience_ >= max_experience() && can_advance();
288  }
289 
290  /**
291  * Gets and image path and and associated description for each advancement option.
292  *
293  * Covers both type and modification-based advancements.
294  *
295  * @returns A data map, in image/description format. If the option is a unit type,
296  * advancement, the key is the type's image and the value the type ID.
297  *
298  * If the option is a modification, the key and value are set from config data
299  * (see @ref get_modification_advances).
300  */
301  std::map<std::string, std::string> advancement_icons() const;
302 
303  /**
304  * Gets any non-typed advanced options set by modifications.
305  *
306  * These are usually used to give a unit special advancement options that don't invole transforming to a
307  * new type.
308  *
309  * Note this is not the raw option data. Parsing is performed to ensure each option appears only once.
310  * Use @ref modification_advancements is the raw data is needed.
311  *
312  * @returns A config list of options data. Each option is unique.
313  */
314  std::vector<config> get_modification_advances() const;
315 
316  /**
317  * Gets the image and description data for modification advancements.
318  *
319  * @returns A list of pairs of the image paths(first) and descriptions (second) for
320  * each advancement option.
321  */
322  std::vector<std::pair<std::string, std::string>> amla_icons() const;
323 
324  /** The raw, unparsed data for modification advancements. */
325  const std::vector<config>& modification_advancements() const
326  {
327  return advancements_;
328  }
329 
330  /** Sets the raw modification advancement option data */
331  void set_advancements(std::vector<config> advancements);
332 
333  /**
334  * @}
335  * @defgroup unit_access Basic data setters and getters
336  * @{
337  **/
338 
339 public:
340  /**
341  * The side this unit belongs to.
342  *
343  * Note that side numbers starts from 1, not 0, so be sure to subtract 1 if using as a container index.
344  */
345  int side() const
346  {
347  return side_;
348  }
349 
350  /** Sets the side this unit belongs to. */
351  void set_side(unsigned int new_side)
352  {
353  side_ = new_side;
354  }
355 
356  /** This unit's type, accounting for gender and variation. */
357  const unit_type& type() const
358  {
359  return *type_;
360  }
361 
362  /**
363  * The id of this unit's type.
364  *
365  * If you are dealing with creating units (e.g. recruitment), this is not what you want, as a
366  * variation can change this; use type().parent_id() instead.
367  */
368  const std::string& type_id() const;
369 
370  /** Gets the translatable name of this unit's type. */
371  const t_string& type_name() const
372  {
373  return type_name_;
374  }
375 
376  /**
377  * Gets this unit's id.
378  *
379  * This is a unique string usually set by WML. It should *not* be used for internal tracking in
380  * the unit_map. Use @ref underlying_id for that.
381  */
382  const std::string& id() const
383  {
384  return id_;
385  }
386 
387  /** Sets this unit's string ID. */
388  void set_id(const std::string& id)
389  {
390  id_ = id;
391  }
392 
393  /** This unit's unique internal ID. This should *not* be used for user-facing operations. */
394  std::size_t underlying_id() const
395  {
396  return underlying_id_.value;
397  }
398 
399 private:
400  /** Sets the internal ID. */
401  void set_underlying_id(n_unit::id_manager& id_manager);
402 
403 public:
404  /** Gets this unit's translatable display name. */
405  const t_string& name() const
406  {
407  return name_;
408  }
409 
410  /**
411  * Sets this unit's translatable display name.
412  *
413  * This should only be used internally since it ignores the 'unrenamable' flag.
414  */
415  void set_name(const t_string& name)
416  {
417  name_ = name;
418  }
419 
420  /**
421  * Attempts to rename this unit's translatable display name, taking the 'unrenamable' flag into account.
422  *
423  * If a direct rename is desired, use @ref set_name.
424  * @todo should this also take a t_string?
425  */
426  void rename(const std::string& name)
427  {
428  if(!unrenamable_) {
429  name_ = name;
430  }
431  }
432 
433  /**
434  * Whether this unit can be renamed.
435  *
436  * This flag is considered by @ref rename, but not @ref set_name.
437  */
438  bool unrenamable() const
439  {
440  return unrenamable_;
441  }
442 
443  /**
444  * Sets the 'unrenamable' flag. Usually used for scenario-specific units which should not be renamed.
445  */
447  {
449  }
450 
451  /** A detailed description of this unit. */
453  {
454  return description_;
455  }
456 
457  /** A detailed description of this unit. */
458  void set_unit_description(const t_string& new_desc)
459  {
460  description_ = new_desc;
461  }
462 
463  /** The unit's special notes. */
464  std::vector<t_string> unit_special_notes() const;
465 
466  /** The gender of this unit. */
468  {
469  return gender_;
470  }
471 
472  /**
473  * The alignment of this unit.
474  *
475  * This affects the time of day during which this unit's attacks do the most damage.
476  */
478  {
479  return alignment_;
480  }
481 
482  /** Sets the alignment of this unit. */
484  {
487  }
488 
489  /**
490  * Gets this unit's race.
491  *
492  * @returns A pointer to a unit_race object - never nullptr, but it may point
493  * to the null race.
494  */
495  const unit_race* race() const
496  {
497  return race_;
498  }
499 
500  /** The current number of hitpoints this unit has. */
501  int hitpoints() const
502  {
503  return hit_points_;
504  }
505 
506  /** The max number of hitpoints this unit can have. */
507  int max_hitpoints() const
508  {
509  return max_hit_points_;
510  }
511 
512  void set_max_hitpoints(int value)
513  {
515  max_hit_points_ = value;
516  }
517 
518  /** Sets the current hitpoint amount. */
519  void set_hitpoints(int hp)
520  {
521  hit_points_ = hp;
522  }
523 
524  /** The current number of experience points this unit has. */
525  int experience() const
526  {
527  return experience_;
528  }
529 
530  /** The max number of experience points this unit can have. */
531  int max_experience() const
532  {
533  return max_experience_;
534  }
535 
536  void set_max_experience(int value)
537  {
539  max_experience_ = value;
540  }
541 
542  /** The number of experience points this unit needs to level up, or 0 if current XP > max XP. */
543  unsigned int experience_to_advance() const
544  {
545  return std::max(0, max_experience_ - experience_);
546  }
547 
548  /** The number of experience points over max this unit has, or 0 if current XP < max XP. */
549  unsigned int experience_overflow() const
550  {
551  return std::max(0, experience_ - max_experience_);
552  }
553 
554  /** Sets the current experience point amount. */
555  void set_experience(int xp)
556  {
557  experience_ = xp;
558  }
559 
560  /** The current level of this unit. */
561  int level() const
562  {
563  return level_;
564  }
565 
566  /** Sets the current level of this unit. */
567  void set_level(int level)
568  {
570  level_ = level;
571  }
572 
573  /** The ID of the variation of this unit's type. */
574  const std::string& variation() const
575  {
576  return variation_;
577  }
578 
579  /** The ID of the undead variation (ie, dwarf, swimmer) of this unit. */
580  void set_undead_variation(const std::string& value)
581  {
583  undead_variation_ = value;
584  }
585  const std::string& undead_variation() const
586  {
587  return undead_variation_;
588  }
589 
590  /**
591  * An optional profile image to display in Help.
592  *
593  * @returns The specified image, this unit's type's sprite image if empty
594  * or 'unit_image' was set.
595  */
596  std::string small_profile() const;
597 
598  void set_small_profile(const std::string& value)
599  {
601  small_profile_ = value;
602  }
603  /**
604  * An optional profile image displays when this unit is 'speaking' via [message].
605  *
606  * @returns The specified image, this unit's type's sprite image if empty
607  * or 'unit_image' was set.
608  */
609  std::string big_profile() const;
610 
611  void set_big_profile(const std::string& value);
612 
613  /** Whether this unit can recruit other units - ie, are they a leader unit. */
614  bool can_recruit() const
615  {
616  return canrecruit_;
617  }
618 
619  /** Sets whether this unit can recruit other units. */
620  void set_can_recruit(bool canrecruit)
621  {
622  canrecruit_ = canrecruit;
623  }
624 
625  /** The type IDs of the other units this unit may recruit, if possible. */
626  const std::vector<std::string>& recruits() const
627  {
628  return recruit_list_;
629  }
630 
631  /** Sets the recruit list. */
632  void set_recruits(const std::vector<std::string>& recruits);
633 
634  /** How much gold is required to recruit this unit. */
635  int cost() const
636  {
637  return unit_value_;
638  }
639 
640  /** How much gold it costs to recall this unit, or -1 if the side's default
641  * recall cost is used. */
642  int recall_cost() const
643  {
644  return recall_cost_;
645  }
646 
647  /** Sets the cost of recalling this unit. */
649  {
651  }
652 
653  /** Gets the filter constraints upon which units this unit may recall, if able. */
654  const config& recall_filter() const
655  {
656  return filter_recall_;
657  }
658 
659  /** Sets the filter constraints upon which units this unit may recall, if able. */
660  void set_recall_filter(const config& filter)
661  {
662  filter_recall_ = filter;
663  }
664 
665  /**
666  * Gets this unit's role.
667  *
668  * A role is a special string flag usually used to represent a unit's purpose in a scenario.
669  * It can be filtered on.
670  */
671  const std::string& get_role() const
672  {
673  return role_;
674  }
675 
676  /** Sets a unit's role */
677  void set_role(const std::string& role)
678  {
679  role_ = role;
680  }
681 
682  /**
683  * Gets this unit's usage. This is relevant to the AI.
684  *
685  * Usage refers to how the AI may consider utilizing this unit in combat.
686  * @todo document further
687  */
688  std::string usage() const
689  {
690  return usage_.value_or("");
691  }
692 
693  /** Sets this unit's usage. */
694  void set_usage(const std::string& usage)
695  {
696  usage_ = usage;
697  }
698 
699  /**
700  * Gets any user-defined variables this unit 'owns'.
701  *
702  * These are accessible via WML if the unit's data is serialized to a variable. They're strictly
703  * user-facing; internal engine calculations shouldn't use this.
704  */
706  {
707  return variables_;
708  }
709 
710  /** Const overload of @ref variables. */
711  const config& variables() const
712  {
713  return variables_;
714  }
715 
716  /**
717  * Gets whether this unit is currently hidden on the map.
718  *
719  * Hidden units are not drawn on the main map or the minimap. They are
720  * an implementation detail. For the [hides] ability, see invisible().
721  */
722  bool get_hidden() const
723  {
724  return hidden_;
725  }
726 
727  /** Sets whether the unit is hidden on the map. */
728  void set_hidden(bool state) const;
729 
730  /**
731  * The factor by which the HP bar should be scaled.
732  * @todo: document further
733  */
734  double hp_bar_scaling() const
735  {
736  return hp_bar_scaling_;
737  }
738 
739  /**
740  * The factor by which the XP bar should be scaled.
741  * @todo: document further
742  */
743  double xp_bar_scaling() const
744  {
745  return xp_bar_scaling_;
746  }
747 
748  /**
749  * Whether the unit has been instructed to hold its position.
750  * This excludes it from the unit cycling function.
751  * @return true if it is holding position
752  */
753  bool hold_position() const
754  {
755  return hold_position_;
756  }
757 
758  /**
759  * Toggle the unit's hold position status.
760  */
762  {
764  if(hold_position_) {
765  end_turn_ = true;
766  }
767  }
768 
769  /**
770  * Set whether the user ended their turn
771  * @todo Verify meaning and explain better
772  */
773  void set_user_end_turn(bool value = true)
774  {
775  end_turn_ = value;
776  }
777 
778  /**
779  * Toggle whether the user ended their turn
780  * @todo Verify meaning and explain better
781  */
783  {
784  end_turn_ = !end_turn_;
785  if(!end_turn_) {
786  hold_position_ = false;
787  }
788  }
789 
790  /**
791  * Check whether the user ended their turn
792  * @todo Verify meaning and explain better
793  */
794  bool user_end_turn() const
795  {
796  return end_turn_;
797  }
798 
799  /**
800  * Refresh unit for the beginning of a turn
801  */
802  void new_turn();
803 
804  /**
805  * Refresh unit for the end of a turn
806  */
807  void end_turn();
808 
809  /**
810  * Refresh unit for the beginning of a new scenario
811  */
812  void new_scenario();
813 
814  /**
815  * Damage the unit.
816  * @returns true if the unit dies as a result
817  */
818  bool take_hit(int damage)
819  {
820  hit_points_ -= damage;
821  return hit_points_ <= 0;
822  }
823 
824  /**
825  * Heal the unit
826  * @param amount The number of hitpoints to gain
827  */
828  void heal(int amount);
829 
830  /**
831  * Fully heal the unit, restoring it to max hitpoints
832  */
833  void heal_fully()
834  {
836  }
837 
838  /**
839  * Get the status effects currently affecting the unit.
840  * @return A set of status keys
841  */
842  const std::set<std::string> get_states() const;
843 
844  /**
845  * Check if the unit is affected by a status effect
846  * @param state The status effect to check
847  * @returns true if the unit is affected by the status effect
848  */
849  bool get_state(const std::string& state) const;
850 
851  /**
852  * Set whether the unit is affected by a status effect
853  * @param state The status effect to change
854  * @param value Whether the unit should be affected by the status
855  */
856  void set_state(const std::string& state, bool value);
857 
858  /**
859  * Built-in status effects known to the engine
860  */
861  enum state_t {
862  STATE_SLOWED = 0, /** The unit is slowed - it moves slower and does less damage */
863  STATE_POISONED, /** The unit is poisoned - it loses health each turn */
864  STATE_PETRIFIED, /** The unit is petrified - it cannot move or be attacked */
865  STATE_UNCOVERED, /** The unit is uncovered - it was hiding but has been spotted */
866  STATE_NOT_MOVED, /** The unit has not moved @todo Explain better */
867  STATE_UNHEALABLE, /** The unit cannot be healed */
868  STATE_GUARDIAN, /** The unit is a guardian - it won't move unless a target is sighted */
869  STATE_INVULNERABLE, /** The unit is invulnerable - it cannot be hit by any attack */
870  NUMBER_OF_STATES, /** To set the size of known_boolean_states_ */
871  STATE_UNKNOWN = -1 /** A status effect not known to the engine */
872  };
873 
874  /**
875  * Set whether the unit is affected by a status effect
876  * @param state The status effect to change
877  * @param value Whether the unit should be affected by the status
878  */
879  void set_state(state_t state, bool value);
880 
881  /**
882  * Check if the unit is affected by a status effect
883  * @param state The status effect to check
884  * @returns true if the unit is affected by the status effect
885  */
886  bool get_state(state_t state) const;
887 
888  /**
889  * Convert a string status effect ID to a built-in status effect ID
890  * @returns the state_t representing the status, or STATE_UNKNOWN if it's not built-in
891  */
892  static state_t get_known_boolean_state_id(const std::string& state);
893 
894  /**
895  * Check if the unit has been poisoned
896  * @returns true if it's poisoned
897  */
898  bool poisoned() const
899  {
900  return get_state(STATE_POISONED);
901  }
902 
903  /**
904  * Check if the unit has been petrified
905  * @returns true if it's petrified
906  */
907  bool incapacitated() const
908  {
909  return get_state(STATE_PETRIFIED);
910  }
911 
912  /**
913  * Check if the unit has been slowed
914  * @returns true if it's slowed
915  */
916  bool slowed() const
917  {
918  return get_state(STATE_SLOWED);
919  }
920 
921  /**
922  * @}
923  * @defgroup unit_atk Attack and resistance functions
924  * @{
925  */
926 
927 public:
928  /** Gets an iterator over this unit's attacks. */
930  {
931  return make_attack_itors(attacks_);
932  }
933 
934  /** Const overload of @ref attacks. */
936  {
937  return make_attack_itors(attacks_);
938  }
939 
940  /**
941  * Adds a new attack to the unit.
942  * @param position An iterator pointing to the attack before which to insert the new one.
943  * @param args The arguments for constructing the attack
944  */
945  template<typename... Args>
946  attack_ptr add_attack(attack_itors::iterator position, Args&&... args)
947  {
949  return *attacks_.emplace(position.base(), new attack_type(std::forward<Args>(args)...));
950  }
951 
952  /**
953  * Remove an attack from the unit
954  * @param atk A pointer to the attack to remove
955  * @return true if the attack was removed, false if it didn't exist on the unit
956  */
957  bool remove_attack(attack_ptr atk);
958 
959  /**
960  * Set the unit to have no attacks left for this turn.
961  */
962  void remove_attacks_ai();
963 
964  /**
965  * Calculates the damage this unit would take from a certain attack.
966  *
967  * @param attack The attack to consider.
968  * @param attacker Whether this unit should be considered the attacker.
969  * @param loc The unit's location (to resolve [resistance] abilities)
970  * @param weapon The weapon to check for any abilities or weapon specials
971  *
972  * @returns The expected damage.
973  */
974  int damage_from(const attack_type& attack, bool attacker, const map_location& loc, const_attack_ptr weapon = nullptr) const
975  {
976  return resistance_against(attack, attacker, loc, weapon);
977  }
978 
979  /** The maximum number of attacks this unit may perform per turn, usually 1. */
980  int max_attacks() const
981  {
982  return max_attacks_;
983  }
984 
985  void set_max_attacks(int value)
986  {
988  max_attacks_ = value;
989  }
990 
991  /**
992  * Gets the remaining number of attacks this unit can perform this turn.
993  *
994  * If the 'incapacitated' status is set, this will always be 0.
995  */
996  int attacks_left() const
997  {
998  return (attacks_left_ == 0 || incapacitated()) ? 0 : attacks_left_;
999  }
1000 
1001  /**
1002  * Gets the remaining number of attacks this unit can perform this turn.
1003  *
1004  * @param base_value If false, consider the `incapacitated` flag.
1005  *
1006  * @returns If @a base_value is true, the raw value is returned.
1007  */
1008  int attacks_left(bool base_value) const
1009  {
1010  return base_value ? attacks_left_ : attacks_left();
1011  }
1012 
1013  /**
1014  * Sets the number of attacks this unit has left this turn.
1015  * @param left The number of attacks left
1016  */
1017  void set_attacks(int left)
1018  {
1019  attacks_left_ = std::max<int>(0, left);
1020  }
1021 
1022  /**
1023  * The unit's defense on a given terrain
1024  * @param terrain The terrain to check
1025  */
1026  int defense_modifier(const t_translation::terrain_code& terrain) const;
1027 
1028  /**
1029  * The unit's resistance against a given damage type
1030  * @param damage_name The damage type
1031  * @param attacker True if this unit is on the offensive (to resolve [resistance] abilities)
1032  * @param loc The unit's location (to resolve [resistance] abilities)
1033  * @param weapon The weapon to check for any abilities or weapon specials
1034  * @param opp_weapon The opponent's weapon to check for any abilities or weapon specials
1035  */
1036  int resistance_against(const std::string& damage_name, bool attacker, const map_location& loc, const_attack_ptr weapon = nullptr, const_attack_ptr opp_weapon = nullptr) const;
1037 
1038  /**
1039  * The unit's resistance against a given attack
1040  * @param atk The attack
1041  * @param attacker True if this unit is on the offensive (to resolve [resistance] abilities)
1042  * @param loc The unit's location (to resolve [resistance] abilities)
1043  * @param weapon The weapon to check for any abilities or weapon specials
1044  */
1045  int resistance_against(const attack_type& atk, bool attacker, const map_location& loc, const_attack_ptr weapon = nullptr) const
1046  {
1047  return resistance_against(atk.type(), attacker, loc , weapon, atk.shared_from_this());
1048  }
1049 
1050  /** Gets resistances without any abilities applied. */
1052  {
1053  return movement_type_.damage_table();
1054  }
1055 
1056 private:
1057  bool resistance_filter_matches(const config& cfg, bool attacker, const std::string& damage_name, int res) const;
1058 
1059  /**
1060  * @}
1061  * @defgroup unit_trait Trait and upkeep functions
1062  * @{
1063  */
1064 public:
1065  /**
1066  * Applies mandatory traits (e.g. undead, mechanical) to a unit and then fills in the remaining traits
1067  * traits until no more are available (leaders have a restricted set of available traits) or the unit has
1068  * its maximum number of traits.
1069  *
1070  * This routine does not apply the effects of added traits to a unit; that must be done by the caller.
1071  *
1072  * Note that random numbers used in config files don't work in multiplayer, so leaders should be barred
1073  * from all random traits until that is fixed. Later the restrictions will be based on play balance.
1074  *
1075  * @param must_have_only Whether random or optional traits should be included or not. If false only
1076  * mandatory traits will be used.
1077  */
1078  void generate_traits(bool must_have_only = false);
1079 
1080  /**
1081  * Gets the names of the currently registered traits.
1082  *
1083  * @returns A list of translatable trait names.
1084  */
1085  const std::vector<t_string>& trait_names() const
1086  {
1087  return trait_names_;
1088  }
1089 
1090  /**
1091  * Gets the descriptions of the currently registered traits.
1092  *
1093  * @returns A list of translatable trait descriptions.
1094  */
1095  const std::vector<t_string>& trait_descriptions() const
1096  {
1097  return trait_descriptions_;
1098  }
1099 
1100  /**
1101  * Gets a list of the traits this unit currently has.
1102  *
1103  * @returns A list of trait IDs.
1104  */
1105  std::vector<std::string> get_traits_list() const;
1106 
1107  /**
1108  * Register a trait's name and its description for the UI's use.
1109  *
1110  * The resulting data can be fetched with @ref trait_names and @ref trait_descriptions.
1111  *
1112  * @param trait A config containing the trait's attributes.
1113  * @param description The translatable description of the trait.
1114  */
1115  void add_trait_description(const config& trait, const t_string& description);
1116 
1117  /**
1118  * Gets the amount of gold this unit costs a side per turn.
1119  *
1120  * This fetches an actual numeric gold value:
1121  * - If can_recruit is true, no upkeep is paid (0 is returned).
1122  * - If a special upkeep flag is set, the associated gold amount is returned (see @ref upkeep_value_visitor).
1123  * - If a numeric value is already set, it is returned directly.
1124  *
1125  * @returns A gold value, evaluated based on the state of @ref upkeep_raw.
1126  */
1127  int upkeep() const;
1128 
1130  {
1131  static std::string type() { static std::string v = "full"; return v; }
1132  };
1133 
1135  {
1136  static std::string type() { static std::string v = "loyal"; return v; }
1137  };
1138 
1139  using upkeep_t = utils::variant<upkeep_full, upkeep_loyal, int>;
1140 
1141  /** Visitor helper class to fetch the appropriate upkeep value. */
1143 #ifdef USING_BOOST_VARIANT
1144  : public boost::static_visitor<int>
1145 #endif
1146  {
1147  public:
1148  explicit upkeep_value_visitor(const unit& unit) : u_(unit) {}
1149 
1150  /** Full upkeep equals the unit's level. */
1151  int operator()(const upkeep_full&) const
1152  {
1153  return u_.level();
1154  }
1155 
1156  /** Loyal units cost no upkeep. */
1157  int operator()(const upkeep_loyal&) const
1158  {
1159  return 0;
1160  }
1161 
1162  int operator()(int v) const
1163  {
1164  return v;
1165  }
1166 
1167  private:
1168  const unit& u_;
1169  };
1170 
1171  /** Visitor helper struct to fetch the upkeep type flag if applicable, or the the value otherwise. */
1173 #ifdef USING_BOOST_VARIANT
1174  : public boost::static_visitor<std::string>
1175 #endif
1176  {
1177  template<typename T>
1178  std::enable_if_t<!std::is_same_v<int, T>, std::string>
1179  operator()(T&) const
1180  {
1181  // Any special upkeep type should have an associated @ref type getter in its helper struct.
1182  return T::type();
1183  }
1184 
1185  std::string operator()(int v) const
1186  {
1187  return std::to_string(v);
1188  }
1189  };
1190 
1191  /** Visitor helper class to parse the upkeep value from a config. */
1193 #ifdef USING_BOOST_VARIANT
1194  : public boost::static_visitor<upkeep_t>
1195 #endif
1196  {
1197  public:
1198  template<typename N>
1199  std::enable_if_t<std::is_arithmetic_v<N>, upkeep_t>
1200  operator()(N n) const
1201  {
1202  if(n == 0) return upkeep_loyal();
1203  if(n < 0) throw std::invalid_argument(std::to_string(n));
1204  return static_cast<int>(n);
1205  }
1206 
1207  template<typename B>
1208  std::enable_if_t<std::is_convertible_v<B, bool> && !std::is_arithmetic_v<B>, upkeep_t>
1209  operator()(B b) const
1210  {
1211  throw std::invalid_argument(b.str());
1212  }
1213 
1214  upkeep_t operator()(utils::monostate) const
1215  {
1216  return upkeep_full();
1217  }
1218 
1219  upkeep_t operator()(const std::string& s) const
1220  {
1221  if(s == "loyal" || s == "free")
1222  return upkeep_loyal();
1223  if(s == "full")
1224  return upkeep_full();
1225  throw std::invalid_argument(s);
1226  }
1227  };
1228 
1229  /**
1230  * Gets the raw variant controlling the upkeep value.
1231  *
1232  * This should not usually be called directly. To get an actual numeric value of upkeep use @ref upkeep.
1233  */
1235  {
1236  return upkeep_;
1237  }
1238 
1239  /** Sets the upkeep value to a specific value value. Does not necessarily need to be numeric */
1241  {
1242  upkeep_ = v;
1243  }
1244 
1245  /** Gets whether this unit is loyal - ie, it costs no upkeep. */
1246  bool loyal() const;
1247 
1248  /** Gets whether this unit is fearless - ie, unaffected by time of day. */
1249  bool is_fearless() const
1250  {
1251  return is_fearless_;
1252  }
1253 
1254  /** Gets whether this unit is healthy - ie, always rest heals. */
1255  bool is_healthy() const
1256  {
1257  return is_healthy_;
1258  }
1259 
1260  /**
1261  * @}
1262  * @defgroup unit_mvmt Movement and location functions
1263  * @{
1264  */
1265 
1266 public:
1267  /** The maximum moves this unit has. */
1268  int total_movement() const
1269  {
1270  return max_movement_;
1271  }
1272 
1273  void set_total_movement(int value)
1274  {
1276  max_movement_ = value;
1277  }
1278 
1279  /**
1280  * Gets how far a unit can move, considering the `incapacitated` flag.
1281  *
1282  * @returns The remaining movement, or zero if incapacitated.
1283  */
1284  int movement_left() const
1285  {
1286  return (movement_ == 0 || incapacitated()) ? 0 : movement_;
1287  }
1288 
1289  /**
1290  * Gets how far a unit can move.
1291  *
1292  * @param base_value If false, consider the `incapacitated` flag.
1293  *
1294  * @returns If @a base_value is true, the raw value is returned.
1295  */
1296  int movement_left(bool base_value) const
1297  {
1298  return base_value ? movement_ : movement_left();
1299  }
1300 
1301  /**
1302  * Set this unit's remaining movement to @a moves.
1303  *
1304  * This does not affect maximum movement.
1305  *
1306  * @param moves The new number of moves
1307  * @param unit_action If to true, the "end turn" and "hold position" flags will be cleared
1308  * (as they should be if a unit acts, as opposed to the movement being set
1309  * by the engine for other reasons).
1310  */
1311  void set_movement(int moves, bool unit_action = false);
1312 
1313  /** Checks if this unit has moved. */
1314  bool has_moved() const
1315  {
1316  return movement_left() != total_movement();
1317  }
1318 
1319  /** Sets the unit to have no moves left for this turn. */
1320  void remove_movement_ai();
1321 
1322  /**
1323  * Checks whether this unit is 'resting'.
1324  *
1325  * Resting refers to whether this unit has not moved yet this turn. Note that this can be true even
1326  * if @ref movement_left is not equal to @ref total_movement.
1327  */
1328  bool resting() const
1329  {
1330  return resting_;
1331  }
1332 
1333  /** Sets this unit's resting status. */
1334  void set_resting(bool rest)
1335  {
1336  resting_ = rest;
1337  }
1338 
1339  /** Tests whether the unit has a zone-of-control, considering @ref incapacitated. */
1340  bool emits_zoc() const
1341  {
1342  return emit_zoc_ && !incapacitated();
1343  }
1344 
1345  /** Gets the raw zone-of-control flag, disregarding @ref incapacitated. */
1346  bool get_emit_zoc() const
1347  {
1348  return emit_zoc_;
1349  }
1350 
1351  /** Sets the raw zone-of-control flag. */
1352  void set_emit_zoc(bool val)
1353  {
1355  emit_zoc_ = val;
1356  }
1357 
1358  /** The current map location this unit is at. */
1360  {
1361  return loc_;
1362  }
1363 
1364  /**
1365  * Sets this unit's map location.
1366  *
1367  * Note this should only be called by unit_map or for temporary units.
1368  */
1369  void set_location(const map_location& loc)
1370  {
1371  loc_ = loc;
1372  }
1373 
1374  /** The current direction this unit is facing within its hex. */
1376  {
1377  return facing_;
1378  }
1379 
1380  /** The this unit's facing. */
1381  void set_facing(map_location::DIRECTION dir) const;
1382 
1383  /** Gets whether this unit has a multi-turn destination set. */
1384  bool has_goto() const
1385  {
1386  return get_goto().valid();
1387  }
1388 
1389  /** The map location to which this unit is moving over multiple turns, if any. */
1390  const map_location& get_goto() const
1391  {
1392  return goto_;
1393  }
1394 
1395  /** Sets this unit's long term destination. */
1396  void set_goto(const map_location& new_goto)
1397  {
1398  goto_ = new_goto;
1399  }
1400 
1401  /** Gets the unit's vision points. */
1402  int vision() const
1403  {
1404  return vision_ < 0 ? max_movement_ : vision_;
1405  }
1406 
1407  /** Gets the unit's jamming points. */
1408  int jamming() const
1409  {
1410  return jamming_;
1411  }
1412 
1413  /** Check whether the unit's move has been interrupted. */
1414  bool move_interrupted() const
1415  {
1416  return movement_left() > 0 && interrupted_move_.x >= 0 && interrupted_move_.y >= 0;
1417  }
1418 
1419  /** Get the target location of the unit's interrupted move. */
1421  {
1422  return interrupted_move_;
1423  }
1424 
1425  /** Set the target location of the unit's interrupted move. */
1426  void set_interrupted_move(const map_location& interrupted_move)
1427  {
1428  interrupted_move_ = interrupted_move;
1429  }
1430 
1431  /** Get the unit's movement type. */
1432  const movetype& movement_type() const
1433  {
1434  return movement_type_;
1435  }
1436 
1437  /**
1438  * Get the unit's movement cost on a particular terrain
1439  * @param terrain The terrain to check
1440  * @returns the number of movement points to enter that terrain
1441  */
1442  int movement_cost(const t_translation::terrain_code& terrain) const
1443  {
1445  }
1446 
1447  /**
1448  * Get the unit's vision cost on a particular terrain
1449  * @param terrain The terrain to check
1450  * @returns the number of vision points to see into that terrain
1451  */
1452  int vision_cost(const t_translation::terrain_code& terrain) const
1453  {
1455  }
1456 
1457  /**
1458  * Get the unit's jamming cost on a particular terrain
1459  * @param terrain The terrain to check
1460  * @returns the number of jamming points to jam that terrain
1461  */
1462  int jamming_cost(const t_translation::terrain_code& terrain) const
1463  {
1465  }
1466 
1467  /** Check if the unit is a flying unit. */
1468  bool is_flying() const
1469  {
1470  return movement_type_.is_flying();
1471  }
1472 
1473  /**
1474  * @}
1475  * @defgroup unit_mod Modification functions
1476  * @{
1477  */
1478 
1479 public:
1480  /** Get the raw modifications. */
1482  {
1483  return modifications_;
1484  }
1485 
1486  /** Set the raw modifications. */
1487  const config& get_modifications() const
1488  {
1489  return modifications_;
1490  }
1491 
1492  /**
1493  * Count modifications of a particular type.
1494  * @param type The type of modification to count.
1495  * Valid values are "advancement", "trait", "object"
1496  * @param id The ID of the modification to count
1497  * @return The total number of modifications of that type and ID.
1498  */
1499  std::size_t modification_count(const std::string& type, const std::string& id) const;
1500 
1501  /**
1502  * Add a new modification to the unit.
1503  * @param type The type of modification to add.
1504  * Valid values are "advancement", "trait", "object"
1505  * @param modification The details of the modification
1506  * @param no_add If true, apply the modification but don't save it for unit rebuild time.
1507  * Defaults to false.
1508  */
1509  void add_modification(const std::string& type, const config& modification, bool no_add = false);
1510 
1511  /**
1512  * Clears those modifications whose duration has expired.
1513  *
1514  * @param duration If empty, all temporary modifications (those not lasting forever) expire.
1515  * Otherwise, modifications whose duration equals @a duration expire.
1516  */
1517  void expire_modifications(const std::string& duration);
1518 
1519  static const std::set<std::string> builtin_effects;
1520 
1521  /**
1522  * Apply a builtin effect to the unit.
1523  * @param type The effect to apply. Must be one of the effects in @ref builtin_effects.
1524  * @param effect The details of the effect
1525  */
1526  void apply_builtin_effect(std::string type, const config& effect);
1527 
1528  /**
1529  * Construct a string describing a built-in effect.
1530  * @param type The effect to describe. Must be one of the effects in @ref builtin_effects.
1531  * @param effect The details of the effect
1532  */
1533  std::string describe_builtin_effect(std::string type, const config& effect);
1534 
1535  /** Re-apply all saved modifications. */
1536  void apply_modifications();
1537 
1538  /**
1539  * @}
1540  * @defgroup unit_img Image and animations functions
1541  * @{
1542  */
1543 
1544 public:
1545  /** @todo Document this */
1547  {
1548  return *anim_comp_;
1549  }
1550 
1551  /** The name of the file to game_display (used in menus). */
1552  std::string absolute_image() const;
1553 
1554  /** The default image to use for animation frames with no defined image. */
1555  std::string default_anim_image() const;
1556 
1557  /** Get the unit's halo image. */
1558  std::string image_halo() const
1559  {
1560  return halo_.value_or("");
1561  }
1562 
1563  const std::vector<std::string> halo_or_icon_abilities(const std::string& image_type) const;
1564 
1565  /** Get the [halo] abilities halo image(s). */
1566  const std::vector<std::string> halo_abilities() const
1567  {
1568  return halo_or_icon_abilities("halo");
1569  }
1570 
1571  /** Set the unit's halo image. */
1572  void set_image_halo(const std::string& halo);
1573 
1574  /** Get the unit's ellipse image. */
1575  std::string image_ellipse() const
1576  {
1577  return ellipse_.value_or("");
1578  }
1579 
1580  /** Set the unit's ellipse image. */
1581  void set_image_ellipse(const std::string& ellipse)
1582  {
1583  appearance_changed_ = true;
1584  ellipse_ = ellipse;
1585  }
1586 
1587  /**
1588  * Get the source color palette to use when recoloring the unit's image.
1589  */
1590  const std::string& flag_rgb() const;
1591 
1592  /** Constructs a recolor (RC) IPF string for this unit's team color. */
1593  std::string TC_image_mods() const;
1594 
1595  /** Gets any IPF image mods applied by effects. */
1596  const std::string& effect_image_mods() const
1597  {
1598  return image_mods_;
1599  }
1600 
1601  /**
1602  * Gets an IPF string containing all IPF image mods.
1603  *
1604  * @returns An amalgamation of @ref effect_image_mods followed by @ref TC_image_mods.
1605  */
1606  std::string image_mods() const;
1607 
1608  /** Get the unit's overlay images. */
1609  const std::vector<std::string>& overlays() const
1610  {
1611  return overlays_;
1612  }
1613 
1614  /** Get the [overlay] ability overlay images. */
1615  const std::vector<std::string> overlays_abilities() const
1616  {
1617  return halo_or_icon_abilities("overlay");
1618  }
1619  /**
1620  * Color for this unit's *current* hitpoints.
1621  *
1622  * @returns A color between green and red representing how wounded this unit is.
1623  * The maximum_hitpoints are considered as base.
1624  */
1625  color_t hp_color() const;
1626  static color_t hp_color_max();
1627 
1628  /**
1629  * Color for this unit's hitpoints.
1630  *
1631  * @param hitpoints The number of hitpoints the color represents.
1632  * @returns The color considering the current hitpoints as base.
1633  */
1634  color_t hp_color(int hitpoints) const;
1635 
1636  /**
1637  * Color for this unit's XP. See also @ref hp_color
1638  */
1639  color_t xp_color() const;
1640  static color_t xp_color(int xp_to_advance, bool can_advance, bool has_amla);
1641 
1642  /**
1643  * @}
1644  * @defgroup unit_abil Ability functions
1645  * @{
1646  */
1647 
1648 public:
1649  /**
1650  * Checks whether this unit currently possesses or is affected by a given ability.
1651  *
1652  * This means that the ability could be owned by this unit itself or by an adjacent unit, should
1653  * the ability affect an AoE in which this unit happens to be.
1654  *
1655  * @param tag_name The name of the ability to check for.
1656  * @param loc The location around which to check for affected units. This may or
1657  * may not be the location of this unit.
1658  */
1659  bool get_ability_bool(const std::string& tag_name, const map_location& loc) const;
1660 
1661  /**
1662  * Checks whether this unit currently possesses or is affected by a given ability.
1663  *
1664  * This means that the ability could be owned by this unit itself or by an adjacent unit, should
1665  * the ability affect an AoE in which this unit happens to be.
1666  *
1667  * This overload uses the location of this unit for calculations.
1668  *
1669  * @param tag_name The name of the ability to check for.
1670  */
1671  bool get_ability_bool(const std::string& tag_name) const
1672  {
1673  return get_ability_bool(tag_name, loc_);
1674  }
1675 
1676  /** Checks whether this unit currently possesses a given ability used like weapon
1677  * @return True if the ability @a tag_name is active.
1678  * @param special the const config to one of abilities @a tag_name checked.
1679  * @param tag_name name of ability type checked.
1680  * @param loc location of the unit checked.
1681  */
1682  bool get_self_ability_bool(const config& special, const std::string& tag_name, const map_location& loc) const;
1683  /** Checks whether this unit currently possesses a given ability of leadership type
1684  * @return True if the ability @a tag_name is active.
1685  * @param special the const config to one of abilities @a tag_name checked.
1686  * @param tag_name name of ability type checked.
1687  * @param loc location of the unit checked.
1688  * @param weapon the attack used by unit checked in this function.
1689  * @param opp_weapon the attack used by opponent to unit checked.
1690  */
1691  bool get_self_ability_bool_weapon(const config& special, const std::string& tag_name, const map_location& loc, const_attack_ptr weapon = nullptr, const_attack_ptr opp_weapon = nullptr) const;
1692  /** Checks whether this unit is affected by a given ability used like weapon
1693  * @return True if the ability @a tag_name is active.
1694  * @param special the const config to one of abilities @a tag_name checked.
1695  * @param tag_name name of ability type checked.
1696  * @param loc location of the unit checked.
1697  * @param from unit adjacent to @a this is checked in case of [affect_adjacent] abilities.
1698  * @param dir direction to research a unit adjacent to @a this.
1699  */
1700  bool get_adj_ability_bool(const config& special, const std::string& tag_name, int dir, const map_location& loc, const unit& from) const;
1701  /** Checks whether this unit is affected by a given ability of leadership type
1702  * @return True if the ability @a tag_name is active.
1703  * @param special the const config to one of abilities @a tag_name checked.
1704  * @param tag_name name of ability type checked.
1705  * @param loc location of the unit checked.
1706  * @param from unit adjacent to @a this is checked in case of [affect_adjacent] abilities.
1707  * @param dir direction to research a unit adjacent to @a this.
1708  * @param weapon the attack used by unit checked in this function.
1709  * @param opp_weapon the attack used by opponent to unit checked.
1710  */
1711  bool get_adj_ability_bool_weapon(const config& special, const std::string& tag_name, int dir, const map_location& loc, const unit& from, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon = nullptr) const;
1712 
1713  /**
1714  * Gets the unit's active abilities of a particular type if it were on a specified location.
1715  * @param tag_name The type of ability to check for
1716  * @param loc The location to use for resolving abilities
1717  * @return A list of active abilities, paired with the location they are active on
1718  */
1719  unit_ability_list get_abilities(const std::string& tag_name, const map_location& loc) const;
1720 
1721  /**
1722  * Gets the unit's active abilities of a particular type.
1723  * @param tag_name The type of ability to check for
1724  * @return A list of active abilities, paired with the location they are active on
1725  */
1726  unit_ability_list get_abilities(const std::string& tag_name) const
1727  {
1728  return get_abilities(tag_name, loc_);
1729  }
1730 
1731  unit_ability_list get_abilities_weapons(const std::string& tag_name, const map_location& loc, const_attack_ptr weapon = nullptr, const_attack_ptr opp_weapon = nullptr) const;
1732 
1733  unit_ability_list get_abilities_weapons(const std::string& tag_name, const_attack_ptr weapon = nullptr, const_attack_ptr opp_weapon = nullptr) const
1734  {
1735  return get_abilities_weapons(tag_name, loc_, weapon, opp_weapon);
1736  }
1737 
1738  const config &abilities() const { return abilities_; }
1739 
1740  const std::set<std::string>& checking_tags() const { return checking_tags_; };
1741 
1742  /**
1743  * Gets the names and descriptions of this unit's abilities. Location-independent variant
1744  * with all abilities shown as active.
1745  *
1746  * @returns A list of quadruples consisting of (in order) id, base name,
1747  * male or female name as appropriate for the unit, and description.
1748  */
1749  std::vector<std::tuple<std::string, t_string, t_string, t_string>>
1750  ability_tooltips() const;
1751 
1752  /**
1753  * Gets the names and descriptions of this unit's abilities.
1754  *
1755  * @param active_list This vector will be the same length as the returned one and will
1756  * indicate whether or not the corresponding ability is active.
1757  *
1758  * @param loc The location on which to resolve the ability.
1759  *
1760  * @returns A list of quadruples consisting of (in order) id, base name,
1761  * male or female name as appropriate for the unit, and description.
1762  */
1763  std::vector<std::tuple<std::string, t_string, t_string, t_string>>
1764  ability_tooltips(boost::dynamic_bitset<>& active_list, const map_location& loc) const;
1765 
1766  /** Get a list of all abilities by ID. */
1767  std::vector<std::string> get_ability_list() const;
1768 
1769  /**
1770  * Check if the unit has an ability of a specific type.
1771  * @param ability The type of ability (tag name) to check for.
1772  * @returns true if the ability is present
1773  */
1774  bool has_ability_type(const std::string& ability) const;
1775 
1776  /**
1777  * Check if the unit has an ability of a specific ID.
1778  * @param ability The ID of ability to check for.
1779  * @returns true if the ability is present
1780  */
1781  bool has_ability_by_id(const std::string& ability) const;
1782 
1783  /**
1784  * Removes a unit's abilities with a specific ID.
1785  * @param ability The type of ability (tag name) to remove.
1786  */
1787  void remove_ability_by_id(const std::string& ability);
1788 
1789  /**
1790  * Removes a unit's abilities with a specific ID or other attribute.
1791  * @param filter the config of ability to remove.
1792  */
1793  void remove_ability_by_attribute(const config& filter);
1794 
1795  /**
1796  * Verify what abilities attributes match with filter.
1797  * @param cfg the config of ability to check.
1798  * @param tag_name the tag name of ability to check.
1799  * @param filter the filter used for checking.
1800  */
1801  bool ability_matches_filter(const config & cfg, const std::string& tag_name, const config & filter) const;
1802 
1803 
1804 private:
1805 
1806  const std::set<std::string> checking_tags_{"attacks", "damage", "chance_to_hit", "berserk", "swarm", "drains", "heal_on_hit", "plague", "slow", "petrifies", "firststrike", "poison", "damage_type"};
1807  /**
1808  * Check if an ability is active.
1809  * @param ability The type (tag name) of the ability
1810  * @param cfg an ability WML structure
1811  * @param loc The location on which to resolve the ability
1812  * @returns true if it is active
1813  */
1814  bool ability_active(const std::string& ability, const config& cfg, const map_location& loc) const;
1815 
1816  /**
1817  * Check if an ability affects adjacent units.
1818  * @param ability The type (tag name) of the ability
1819  * @param cfg an ability WML structure
1820  * @param loc The location on which to resolve the ability
1821  * @param from The "other unit" for filter matching
1822  * @param dir The direction the unit is facing
1823  */
1824  bool ability_affects_adjacent(const std::string& ability, const config& cfg, int dir, const map_location& loc, const unit& from) const;
1825 
1826  /**
1827  * Check if an ability affects the owning unit.
1828  * @param ability The type (tag name) of the ability
1829  * @param cfg an ability WML structure
1830  * @param loc The location on which to resolve the ability
1831  */
1832  bool ability_affects_self(const std::string& ability, const config& cfg, const map_location& loc) const;
1833 
1834  /**
1835  * filters the weapons that condition the use of abilities for combat ([resistance],[leadership] or abilities used like specials
1836  * (deprecated in two last cases)
1837  */
1838  bool ability_affects_weapon(const config& cfg, const_attack_ptr weapon, bool is_opp) const;
1839 
1840 public:
1841  /** Get the unit formula manager. */
1843  {
1844  return *formula_man_;
1845  }
1846 
1847  /** Generates a random race-appropriate name if one has not already been provided. */
1848  void generate_name();
1849 
1850  // Only see_all = true use caching
1851  bool invisible(const map_location& loc, bool see_all = true) const;
1852 
1853  bool is_visible_to_team(const team& team, bool const see_all = true) const;
1854  /** Return true if the unit would be visible to team if its location were loc. */
1855  bool is_visible_to_team(const map_location& loc, const team& team, bool const see_all = true) const;
1856 
1857  /**
1858  * Serializes the current unit metadata values.
1859  *
1860  * @param cfg The config to write to.
1861  * @param write_all set this to false to not write unchanged attributes.
1862  */
1863  void write(config& cfg, bool write_all = true) const;
1864 
1865  /**
1866  * Mark this unit as clone so it can be inserted to unit_map.
1867  *
1868  * @returns self (for convenience)
1869  */
1870  unit& mark_clone(bool is_temporary);
1871 
1872 
1873  void set_appearance_changed(bool value) { appearance_changed_ = value; }
1874  bool appearance_changed() const { return appearance_changed_; }
1875 
1876 protected:
1877 
1878 private:
1880 
1881  std::vector<std::string> advances_to_;
1882 
1883  /** Never nullptr. Adjusted for gender and variation. */
1885 
1886  /** The displayed name of this unit type. */
1888 
1889  /** Never nullptr, but may point to the null race. */
1891 
1892  std::string id_;
1895 
1896  std::string undead_variation_;
1897  std::string variation_;
1898 
1903 
1904  int level_;
1905 
1908  std::vector<std::string> recruit_list_;
1910 
1911  std::string flag_rgb_;
1912  std::string image_mods_;
1913 
1915 
1916  int side_;
1917 
1919 
1920  std::unique_ptr<unit_formula_manager> formula_man_;
1921 
1924  int vision_;
1926 
1928 
1931  bool resting_;
1932 
1935 
1936  std::set<std::string> states_;
1937 
1938  static const std::size_t num_bool_states = state_t::NUMBER_OF_STATES;
1939 
1940  std::bitset<num_bool_states> known_boolean_states_;
1941  static std::map<std::string, state_t> known_boolean_state_names_;
1942 
1946 
1948 
1949  std::vector<std::string> overlays_;
1950 
1951  std::string role_;
1953 
1954 protected:
1955  // TODO: I think we actually consider this to be part of the gamestate, so it might be better if it's not mutable,
1956  // but it's not easy to separate this guy from the animation code right now.
1958 
1959 private:
1960  std::vector<t_string> trait_names_;
1961  std::vector<t_string> trait_descriptions_;
1962 
1965 
1967 
1969 
1970  // Animations:
1972 
1973  std::unique_ptr<unit_animation_component> anim_comp_;
1974 
1975  mutable bool hidden_;
1977 
1980 
1981  std::vector<config> advancements_;
1982 
1984  std::vector<t_string> special_notes_;
1985 
1986  std::optional<std::string> usage_;
1987  std::optional<std::string> halo_;
1988  std::optional<std::string> ellipse_;
1989 
1992 
1994 
1995  std::string profile_;
1996  std::string small_profile_;
1997 
1998  //Used to check whether the moving units during a move needs to be updated
1999  mutable bool appearance_changed_ = true;
2000  std::bitset<UA_COUNT> changed_attributes_;
2001 
2004 
2005  /**
2006  * Hold the visibility status cache for a unit, when not uncovered.
2007  * This is mutable since it is a cache.
2008  */
2009  mutable std::map<map_location, bool> invisibility_cache_;
2010 
2011  /**
2012  * Clears the cache.
2013  *
2014  * Since we don't change the state of the object we're marked const (also
2015  * required since the objects in the cache need to be marked const).
2016  */
2018  {
2019  invisibility_cache_.clear();
2020  }
2021 };
2022 
2023 /**
2024  * Object which temporarily resets a unit's movement.
2025  *
2026  * @warning A unit whose movement is reset may not be deleted while held in a
2027  * @ref unit_movement_resetter object, so it's best to use thus only in a small scope.
2028  */
2030 {
2033 
2034  unit_movement_resetter(const unit& u, bool operate = true);
2036 
2037 private:
2039  int moves_;
2040 };
2041 
2043 {
2044 /**
2045  * Optional parameter for get_checksum to use the algorithm of an older version of Wesnoth,
2046  * thus preventing spurious OOS warnings while watching old replays.
2047  */
2049  current,
2050  version_1_16_or_older /**< Included some of the flavortext from weapon specials. */
2051 };
2052 
2053 } // namespace backwards_compatibility
2054 
2055 /**
2056  * Gets a checksum for a unit.
2057  *
2058  * In MP games the descriptions are locally generated and might differ, so it
2059  * should be possible to discard them. Not sure whether replays suffer the
2060  * same problem.
2061  *
2062  * @param u this unit
2063  * @param version allows the checksum expected in older replays to be used
2064  *
2065  * @returns the checksum for a unit
2066  */
2067 std::string get_checksum(const unit& u,
double t
Definition: astarsearch.cpp:65
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)
const std::string & type() const
Definition: attack_type.hpp:45
Variant for storing WML attributes.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:161
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:87
The basic "size" of the unit - flying, small land, large land, etc.
Definition: movetype.hpp:45
int jamming_cost(const t_translation::terrain_code &terrain, bool slowed=false) const
Returns the cost to "jam" through the indicated terrain.
Definition: movetype.hpp:288
int vision_cost(const t_translation::terrain_code &terrain, bool slowed=false) const
Returns the cost to see through the indicated terrain.
Definition: movetype.hpp:285
int movement_cost(const t_translation::terrain_code &terrain, bool slowed=false) const
Returns the cost to move through the indicated terrain.
Definition: movetype.hpp:282
utils::string_map_res damage_table() const
Returns a map from attack types to resistances.
Definition: movetype.hpp:302
bool is_flying() const
Returns whether or not *this is flagged as a flying movement type.
Definition: movetype.hpp:277
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:76
Visitor helper class to parse the upkeep value from a config.
Definition: unit.hpp:1196
Visitor helper class to fetch the appropriate upkeep value.
Definition: unit.hpp:1146
void append(const unit_ability_list &other)
Appends the abilities from other to this, ignores other.loc()
Definition: unit.hpp:108
iterator erase(const iterator &erase_it)
Definition: unit.hpp:99
unit_ability & back()
Definition: unit.hpp:95
iterator erase(const iterator &first, const iterator &last)
Definition: unit.hpp:100
std::pair< int, map_location > lowest(const std::string &key, int def=0) const
Definition: unit.hpp:74
const_iterator begin() const
Definition: unit.hpp:87
unit_ability & front()
Definition: unit.hpp:93
std::vector< unit_ability > cfgs_
Definition: unit.hpp:127
const unit_ability & back() const
Definition: unit.hpp:96
const unit_ability & front() const
Definition: unit.hpp:94
std::vector< unit_ability >::const_iterator const_iterator
Definition: unit.hpp:84
iterator begin()
Definition: unit.hpp:86
iterator end()
Definition: unit.hpp:88
const map_location & loc() const
Definition: unit.hpp:105
std::vector< unit_ability >::iterator iterator
Definition: unit.hpp:83
void emplace_back(T &&... args)
Definition: unit.hpp:103
std::pair< int, map_location > highest(const std::string &key, int def=0) const
Definition: unit.hpp:70
const_iterator end() const
Definition: unit.hpp:89
std::size_t size()
Definition: unit.hpp:97
bool empty() const
Definition: unit.hpp:92
unit_ability_list(const map_location &loc=map_location())
Definition: unit.hpp:67
map_location loc_
Definition: unit.hpp:128
void append_if(const unit_ability_list &other, const Predicate &predicate)
Appends any abilities from other for which the given condition returns true to this,...
Definition: unit.hpp:120
std::pair< int, map_location > get_extremum(const std::string &key, int def, const TComp &comp) const
Definition: abilities.cpp:605
@ NUM_GENDERS
Definition: race.hpp:27
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
unit_ptr clone() const
Definition: unit.hpp:223
unit & operator=(const unit &)=delete
UNIT_ATTRIBUTE
Definition: unit.hpp:163
static void clear_status_caches()
Clear this unit status cache for all units.
Definition: unit.cpp:679
void set_attr_changed(UNIT_ATTRIBUTE attr)
Definition: unit.hpp:187
virtual ~unit()
Definition: unit.cpp:713
bool get_attr_changed(UNIT_ATTRIBUTE attr) const
Definition: unit.hpp:194
void clear_changed_attributes()
Definition: unit.cpp:2834
void init(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Definition: unit.cpp:382
static unit_ptr create(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Initializes a unit from a config.
Definition: unit.hpp:203
static const std::string & leader_crown()
The path to the leader crown overlay.
Definition: unit.cpp:1051
bool get_attacks_changed() const
Definition: unit.cpp:1547
unit()=delete
static unit_ptr create(const unit_type &t, int side, bool real_unit, unit_race::GENDER gender=unit_race::NUM_GENDERS, const std::string &variation="")
Initializes a unit from a unit type.
Definition: unit.hpp:215
A variable-expanding proxy for the config class.
Definition: variable.hpp:45
int hit_points_
Definition: unit.hpp:1899
unit_ability_list get_abilities(const std::string &tag_name) const
Gets the unit's active abilities of a particular type.
Definition: unit.hpp:1726
int movement_
Definition: unit.hpp:1922
void generate_name()
Generates a random race-appropriate name if one has not already been provided.
Definition: unit.cpp:731
std::vector< t_string > trait_names_
Definition: unit.hpp:1960
bool get_self_ability_bool_weapon(const config &special, const std::string &tag_name, const map_location &loc, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
Checks whether this unit currently possesses a given ability of leadership type.
Definition: abilities.cpp:1512
int unit_value_
Definition: unit.hpp:1963
int attacks_left_
Definition: unit.hpp:1933
bool generate_name_
Definition: unit.hpp:1991
void clear_visibility_cache() const
Clears the cache.
Definition: unit.hpp:2017
bool get_adj_ability_bool_weapon(const config &special, const std::string &tag_name, int dir, const map_location &loc, const unit &from, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
Checks whether this unit is affected by a given ability of leadership type.
Definition: abilities.cpp:1517
movetype movement_type_
Definition: unit.hpp:1927
config variables_
Definition: unit.hpp:1943
bool unrenamable_
Definition: unit.hpp:1914
int experience_
Definition: unit.hpp:1901
int vision_
Definition: unit.hpp:1924
void remove_ability_by_attribute(const config &filter)
Removes a unit's abilities with a specific ID or other attribute.
Definition: unit.cpp:1534
std::string undead_variation_
Definition: unit.hpp:1896
bool ability_active(const std::string &ability, const config &cfg, const map_location &loc) const
Check if an ability is active.
Definition: abilities.cpp:354
t_string type_name_
The displayed name of this unit type.
Definition: unit.hpp:1887
map_location interrupted_move_
Definition: unit.hpp:1964
std::optional< std::string > ellipse_
Definition: unit.hpp:1988
map_location::DIRECTION facing_
Definition: unit.hpp:1957
bool ability_affects_self(const std::string &ability, const config &cfg, const map_location &loc) const
Check if an ability affects the owning unit.
Definition: abilities.cpp:453
unit_movement_resetter(const unit_movement_resetter &)=delete
bool random_traits_
Definition: unit.hpp:1990
void write(config &cfg, bool write_all=true) const
Serializes the current unit metadata values.
Definition: unit.cpp:1557
std::bitset< UA_COUNT > changed_attributes_
Definition: unit.hpp:2000
std::string small_profile_
Definition: unit.hpp:1996
void write_upkeep(config::attribute_value &upkeep) const
Definition: unit.cpp:2829
bool get_ability_bool(const std::string &tag_name, const map_location &loc) const
Checks whether this unit currently possesses or is affected by a given ability.
Definition: abilities.cpp:182
std::string id_
Definition: unit.hpp:1892
std::vector< t_string > special_notes_
Definition: unit.hpp:1984
bool canrecruit_
Definition: unit.hpp:1907
std::string image_mods_
Definition: unit.hpp:1912
double hp_bar_scaling_
Definition: unit.hpp:1976
std::string flag_rgb_
Definition: unit.hpp:1911
bool ability_affects_adjacent(const std::string &ability, const config &cfg, int dir, const map_location &loc, const unit &from) const
Check if an ability affects adjacent units.
Definition: abilities.cpp:426
static std::map< std::string, state_t > known_boolean_state_names_
Definition: unit.hpp:1941
@ UA_IS_HEALTHY
Definition: unit.hpp:168
@ UA_SMALL_PROFILE
Definition: unit.hpp:181
@ UA_MAX_MP
Definition: unit.hpp:165
@ UA_ATTACKS
Definition: unit.hpp:178
@ UA_ZOC
Definition: unit.hpp:172
@ UA_MOVEMENT_TYPE
Definition: unit.hpp:171
@ UA_PROFILE
Definition: unit.hpp:180
@ UA_LEVEL
Definition: unit.hpp:170
@ UA_MAX_XP
Definition: unit.hpp:167
@ UA_IS_FEARLESS
Definition: unit.hpp:169
@ UA_ADVANCE_TO
Definition: unit.hpp:173
@ UA_MAX_AP
Definition: unit.hpp:166
@ UA_COUNT
Definition: unit.hpp:184
@ UA_ADVANCEMENTS
Definition: unit.hpp:174
@ UA_MAX_HP
Definition: unit.hpp:164
@ UA_ABILITIES
Definition: unit.hpp:182
@ UA_UNDEAD_VARIATION
Definition: unit.hpp:176
@ UA_UPKEEP
Definition: unit.hpp:183
@ UA_NOTES
Definition: unit.hpp:179
@ UA_ALIGNMENT
Definition: unit.hpp:175
void set_appearance_changed(bool value)
Definition: unit.hpp:1873
std::vector< std::tuple< std::string, t_string, t_string, t_string > > ability_tooltips() const
Gets the names and descriptions of this unit's abilities.
Definition: abilities.cpp:326
config events_
Definition: unit.hpp:1944
bool hidden_
Definition: unit.hpp:1975
bool is_healthy_
Definition: unit.hpp:1966
bool is_fearless_
Definition: unit.hpp:1966
config abilities_
Definition: unit.hpp:1979
unit_ability_list get_abilities_weapons(const std::string &tag_name, const map_location &loc, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
Definition: abilities.cpp:260
const unit_type * type_
Never nullptr.
Definition: unit.hpp:1884
std::bitset< num_bool_states > known_boolean_states_
Definition: unit.hpp:1940
int side_
Definition: unit.hpp:1916
const unit_race * race_
Never nullptr, but may point to the null race.
Definition: unit.hpp:1890
bool appearance_changed_
Definition: unit.hpp:1999
int operator()(const upkeep_loyal &) const
Loyal units cost no upkeep.
Definition: unit.hpp:1157
double xp_bar_scaling_
Definition: unit.hpp:1976
bool appearance_changed() const
Definition: unit.hpp:1874
unit_alignments::type alignment_
Definition: unit.hpp:1909
bool get_ability_bool(const std::string &tag_name) const
Checks whether this unit currently possesses or is affected by a given ability.
Definition: unit.hpp:1671
bool ability_affects_weapon(const config &cfg, const_attack_ptr weapon, bool is_opp) const
filters the weapons that condition the use of abilities for combat ([resistance],[leadership] or abil...
Definition: abilities.cpp:461
bool invisible(const map_location &loc, bool see_all=true) const
Definition: unit.cpp:2598
bool is_visible_to_team(const team &team, bool const see_all=true) const
Definition: unit.cpp:2641
std::enable_if_t<!std::is_same_v< int, T >, std::string > operator()(T &) const
Definition: unit.hpp:1179
n_unit::unit_id underlying_id_
Definition: unit.hpp:1894
std::string variation_
Definition: unit.hpp:1897
unit & mark_clone(bool is_temporary)
Mark this unit as clone so it can be inserted to unit_map.
Definition: unit.cpp:2699
bool has_ability_type(const std::string &ability) const
Check if the unit has an ability of a specific type.
Definition: abilities.cpp:474
std::enable_if_t< std::is_convertible_v< B, bool > &&!std::is_arithmetic_v< B >, upkeep_t > operator()(B b) const
Definition: unit.hpp:1209
static const std::size_t num_bool_states
Definition: unit.hpp:1938
config filter_recall_
Definition: unit.hpp:1945
int max_experience_
Definition: unit.hpp:1902
unit_ability_list get_abilities(const std::string &tag_name, const map_location &loc) const
Gets the unit's active abilities of a particular type if it were on a specified location.
Definition: abilities.cpp:220
bool get_adj_ability_bool(const config &special, const std::string &tag_name, int dir, const map_location &loc, const unit &from) const
Checks whether this unit is affected by a given ability used like weapon.
Definition: abilities.cpp:1506
unit_race::GENDER gender_
Definition: unit.hpp:1918
int operator()(int v) const
Definition: unit.hpp:1162
t_string description_
Definition: unit.hpp:1983
int level_
Definition: unit.hpp:1904
std::string role_
Definition: unit.hpp:1951
std::map< map_location, bool > invisibility_cache_
Hold the visibility status cache for a unit, when not uncovered.
Definition: unit.hpp:2009
upkeep_t operator()(const std::string &s) const
Definition: unit.hpp:1219
bool end_turn_
Definition: unit.hpp:1930
std::vector< std::string > advances_to_
Definition: unit.hpp:1881
std::unique_ptr< unit_animation_component > anim_comp_
Definition: unit.hpp:1973
std::enable_if_t< std::is_arithmetic_v< N >, upkeep_t > operator()(N n) const
Definition: unit.hpp:1200
int recall_cost_
Definition: unit.hpp:1906
static std::string type()
Definition: unit.hpp:1136
const std::set< std::string > checking_tags_
Definition: unit.hpp:1806
attack_list attacks_
Definition: unit.hpp:1952
std::vector< std::string > get_ability_list() const
Get a list of all abilities by ID.
Definition: abilities.cpp:269
unit_ability_list get_abilities_weapons(const std::string &tag_name, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
Definition: unit.hpp:1733
void remove_ability_by_id(const std::string &ability)
Removes a unit's abilities with a specific ID.
Definition: unit.cpp:1411
map_location loc_
Definition: unit.hpp:1879
static std::string type()
Definition: unit.hpp:1131
std::vector< std::string > overlays_
Definition: unit.hpp:1949
unit_formula_manager & formula_manager() const
Get the unit formula manager.
Definition: unit.hpp:1842
config modifications_
Definition: unit.hpp:1978
bool has_ability_by_id(const std::string &ability) const
Check if the unit has an ability of a specific ID.
Definition: unit.cpp:1400
bool hold_position_
Definition: unit.hpp:1929
const config & abilities() const
Definition: unit.hpp:1738
upkeep_value_visitor(const unit &unit)
Definition: unit.hpp:1148
std::string operator()(int v) const
Definition: unit.hpp:1185
void parse_upkeep(const config::attribute_value &upkeep)
Definition: unit.cpp:2815
std::vector< std::string > recruit_list_
Definition: unit.hpp:1908
const std::set< std::string > & checking_tags() const
Definition: unit.hpp:1740
std::vector< config > advancements_
Definition: unit.hpp:1981
utils::string_map modification_descriptions_
Definition: unit.hpp:1968
upkeep_t operator()(utils::monostate) const
Definition: unit.hpp:1214
bool get_self_ability_bool(const config &special, const std::string &tag_name, const map_location &loc) const
Checks whether this unit currently possesses a given ability used like weapon.
Definition: abilities.cpp:1501
unit_checksum_version
Optional parameter for get_checksum to use the algorithm of an older version of Wesnoth,...
Definition: unit.hpp:2048
upkeep_t upkeep_
Definition: unit.hpp:1993
int operator()(const upkeep_full &) const
Full upkeep equals the unit's level.
Definition: unit.hpp:1151
std::set< std::string > states_
Definition: unit.hpp:1936
std::string profile_
Definition: unit.hpp:1995
int jamming_
Definition: unit.hpp:1925
std::optional< std::string > halo_
Definition: unit.hpp:1987
map_location goto_
Definition: unit.hpp:1964
t_string name_
Definition: unit.hpp:1893
int max_attacks_
Definition: unit.hpp:1934
bool ability_matches_filter(const config &cfg, const std::string &tag_name, const config &filter) const
Verify what abilities attributes match with filter.
Definition: unit.cpp:1510
int max_hit_points_
Definition: unit.hpp:1900
std::unique_ptr< unit_formula_manager > formula_man_
Definition: unit.hpp:1920
int max_movement_
Definition: unit.hpp:1923
bool resting_
Definition: unit.hpp:1931
std::vector< t_string > trait_descriptions_
Definition: unit.hpp:1961
bool emit_zoc_
Definition: unit.hpp:1947
unit_movement_resetter & operator=(const unit_movement_resetter &)=delete
std::optional< std::string > usage_
Definition: unit.hpp:1986
@ version_1_16_or_older
Included some of the flavortext from weapon specials.
void set_big_profile(const std::string &value)
Definition: unit.cpp:1943
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:507
void heal(int amount)
Heal the unit.
Definition: unit.cpp:1295
bool user_end_turn() const
Check whether the user ended their turn.
Definition: unit.hpp:794
void set_role(const std::string &role)
Sets a unit's role.
Definition: unit.hpp:677
unit_alignments::type alignment() const
The alignment of this unit.
Definition: unit.hpp:477
void toggle_user_end_turn()
Toggle whether the user ended their turn.
Definition: unit.hpp:782
bool incapacitated() const
Check if the unit has been petrified.
Definition: unit.hpp:907
void set_state(const std::string &state, bool value)
Set whether the unit is affected by a status effect.
Definition: unit.cpp:1377
int level() const
The current level of this unit.
Definition: unit.hpp:561
std::string usage() const
Gets this unit's usage.
Definition: unit.hpp:688
const std::string & get_role() const
Gets this unit's role.
Definition: unit.hpp:671
const t_string & type_name() const
Gets the translatable name of this unit's type.
Definition: unit.hpp:371
void new_turn()
Refresh unit for the beginning of a turn.
Definition: unit.cpp:1256
const std::vector< std::string > & recruits() const
The type IDs of the other units this unit may recruit, if possible.
Definition: unit.hpp:626
void set_max_experience(int value)
Definition: unit.hpp:536
void set_max_hitpoints(int value)
Definition: unit.hpp:512
void set_hitpoints(int hp)
Sets the current hitpoint amount.
Definition: unit.hpp:519
bool unrenamable() const
Whether this unit can be renamed.
Definition: unit.hpp:438
const config & recall_filter() const
Gets the filter constraints upon which units this unit may recall, if able.
Definition: unit.hpp:654
int recall_cost() const
How much gold it costs to recall this unit, or -1 if the side's default recall cost is used.
Definition: unit.hpp:642
std::string big_profile() const
An optional profile image displays when this unit is 'speaking' via [message].
Definition: unit.cpp:1029
static state_t get_known_boolean_state_id(const std::string &state)
Convert a string status effect ID to a built-in status effect ID.
Definition: unit.cpp:1356
void set_level(int level)
Sets the current level of this unit.
Definition: unit.hpp:567
void rename(const std::string &name)
Attempts to rename this unit's translatable display name, taking the 'unrenamable' flag into account.
Definition: unit.hpp:426
void set_hidden(bool state) const
Sets whether the unit is hidden on the map.
Definition: unit.cpp:2795
void set_recall_filter(const config &filter)
Sets the filter constraints upon which units this unit may recall, if able.
Definition: unit.hpp:660
const std::string & variation() const
The ID of the variation of this unit's type.
Definition: unit.hpp:574
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:501
int cost() const
How much gold is required to recruit this unit.
Definition: unit.hpp:635
bool hold_position() const
Whether the unit has been instructed to hold its position.
Definition: unit.hpp:753
bool slowed() const
Check if the unit has been slowed.
Definition: unit.hpp:916
bool get_state(const std::string &state) const
Check if the unit is affected by a status effect.
Definition: unit.cpp:1328
unsigned int experience_overflow() const
The number of experience points over max this unit has, or 0 if current XP < max XP.
Definition: unit.hpp:549
std::string small_profile() const
An optional profile image to display in Help.
Definition: unit.cpp:1038
void heal_fully()
Fully heal the unit, restoring it to max hitpoints.
Definition: unit.hpp:833
void set_undead_variation(const std::string &value)
The ID of the undead variation (ie, dwarf, swimmer) of this unit.
Definition: unit.hpp:580
void toggle_hold_position()
Toggle the unit's hold position status.
Definition: unit.hpp:761
const std::string & type_id() const
The id of this unit's type.
Definition: unit.cpp:1938
void set_alignment(unit_alignments::type alignment)
Sets the alignment of this unit.
Definition: unit.hpp:483
bool get_hidden() const
Gets whether this unit is currently hidden on the map.
Definition: unit.hpp:722
void set_name(const t_string &name)
Sets this unit's translatable display name.
Definition: unit.hpp:415
void set_can_recruit(bool canrecruit)
Sets whether this unit can recruit other units.
Definition: unit.hpp:620
const std::set< std::string > get_states() const
Get the status effects currently affecting the unit.
Definition: unit.cpp:1311
void set_side(unsigned int new_side)
Sets the side this unit belongs to.
Definition: unit.hpp:351
void new_scenario()
Refresh unit for the beginning of a new scenario.
Definition: unit.cpp:1280
void end_turn()
Refresh unit for the end of a turn.
Definition: unit.cpp:1266
bool take_hit(int damage)
Damage the unit.
Definition: unit.hpp:818
const config & variables() const
Const overload of variables.
Definition: unit.hpp:711
const std::string & undead_variation() const
Definition: unit.hpp:585
const unit_race * race() const
Gets this unit's race.
Definition: unit.hpp:495
const unit_type & type() const
This unit's type, accounting for gender and variation.
Definition: unit.hpp:357
int experience() const
The current number of experience points this unit has.
Definition: unit.hpp:525
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
Definition: unit.hpp:614
void set_experience(int xp)
Sets the current experience point amount.
Definition: unit.hpp:555
void set_user_end_turn(bool value=true)
Set whether the user ended their turn.
Definition: unit.hpp:773
const std::string & id() const
Gets this unit's id.
Definition: unit.hpp:382
void set_underlying_id(n_unit::id_manager &id_manager)
Sets the internal ID.
Definition: unit.cpp:2682
int side() const
The side this unit belongs to.
Definition: unit.hpp:345
bool poisoned() const
Check if the unit has been poisoned.
Definition: unit.hpp:898
unsigned int experience_to_advance() const
The number of experience points this unit needs to level up, or 0 if current XP > max XP.
Definition: unit.hpp:543
state_t
Built-in status effects known to the engine.
Definition: unit.hpp:861
double xp_bar_scaling() const
The factor by which the XP bar should be scaled.
Definition: unit.hpp:743
void set_unit_description(const t_string &new_desc)
A detailed description of this unit.
Definition: unit.hpp:458
void set_unrenamable(bool unrenamable)
Sets the 'unrenamable' flag.
Definition: unit.hpp:446
void set_recruits(const std::vector< std::string > &recruits)
Sets the recruit list.
Definition: unit.cpp:1165
std::vector< t_string > unit_special_notes() const
The unit's special notes.
Definition: unit.cpp:2842
void set_id(const std::string &id)
Sets this unit's string ID.
Definition: unit.hpp:388
config & variables()
Gets any user-defined variables this unit 'owns'.
Definition: unit.hpp:705
void set_recall_cost(int recall_cost)
Sets the cost of recalling this unit.
Definition: unit.hpp:648
std::size_t underlying_id() const
This unit's unique internal ID.
Definition: unit.hpp:394
double hp_bar_scaling() const
The factor by which the HP bar should be scaled.
Definition: unit.hpp:734
void set_usage(const std::string &usage)
Sets this unit's usage.
Definition: unit.hpp:694
int max_experience() const
The max number of experience points this unit can have.
Definition: unit.hpp:531
void set_small_profile(const std::string &value)
Definition: unit.hpp:598
unit_race::GENDER gender() const
The gender of this unit.
Definition: unit.hpp:467
const t_string & name() const
Gets this unit's translatable display name.
Definition: unit.hpp:405
t_string unit_description() const
A detailed description of this unit.
Definition: unit.hpp:452
@ STATE_SLOWED
Definition: unit.hpp:862
@ STATE_UNKNOWN
To set the size of known_boolean_states_.
Definition: unit.hpp:871
@ STATE_NOT_MOVED
The unit is uncovered - it was hiding but has been spotted.
Definition: unit.hpp:866
@ STATE_GUARDIAN
The unit cannot be healed.
Definition: unit.hpp:868
@ STATE_INVULNERABLE
The unit is a guardian - it won't move unless a target is sighted.
Definition: unit.hpp:869
@ STATE_PETRIFIED
The unit is poisoned - it loses health each turn.
Definition: unit.hpp:864
@ NUMBER_OF_STATES
The unit is invulnerable - it cannot be hit by any attack.
Definition: unit.hpp:870
@ STATE_UNHEALABLE
The unit has not moved.
Definition: unit.hpp:867
@ STATE_POISONED
The unit is slowed - it moves slower and does less damage.
Definition: unit.hpp:863
@ STATE_UNCOVERED
The unit is petrified - it cannot move or be attacked.
Definition: unit.hpp:865
std::vector< std::string > advances_to_t
Definition: unit.hpp:240
std::vector< config > get_modification_advances() const
Gets any non-typed advanced options set by modifications.
Definition: unit.cpp:1867
std::vector< std::pair< std::string, std::string > > amla_icons() const
Gets the image and description data for modification advancements.
Definition: unit.cpp:1850
const advances_to_t & advances_to() const
Gets the possible types this unit can advance to on level-up.
Definition: unit.hpp:246
bool can_advance() const
Checks whether this unit has any options to advance to.
Definition: unit.hpp:274
bool advances() const
Checks whether this unit is eligible for level-up.
Definition: unit.hpp:285
void set_advancements(std::vector< config > advancements)
Sets the raw modification advancement option data.
Definition: unit.cpp:1932
void set_advances_to(const std::vector< std::string > &advances_to)
Sets this unit's advancement options.
Definition: unit.cpp:1186
const std::vector< config > & modification_advancements() const
The raw, unparsed data for modification advancements.
Definition: unit.hpp:325
std::map< std::string, std::string > advancement_icons() const
Gets and image path and and associated description for each advancement option.
Definition: unit.cpp:1810
const std::vector< std::string > advances_to_translated() const
Gets the names of the possible types this unit can advance to on level-up.
Definition: unit.cpp:1171
void advance_to(const unit_type &t, bool use_traits=false)
Advances this unit to another type.
Definition: unit.cpp:893
void remove_attacks_ai()
Set the unit to have no attacks left for this turn.
Definition: unit.cpp:2777
attack_ptr add_attack(attack_itors::iterator position, Args &&... args)
Adds a new attack to the unit.
Definition: unit.hpp:946
bool resistance_filter_matches(const config &cfg, bool attacker, const std::string &damage_name, int res) const
Definition: unit.cpp:1761
int resistance_against(const attack_type &atk, bool attacker, const map_location &loc, const_attack_ptr weapon=nullptr) const
The unit's resistance against a given attack.
Definition: unit.hpp:1045
void set_max_attacks(int value)
Definition: unit.hpp:985
int attacks_left(bool base_value) const
Gets the remaining number of attacks this unit can perform this turn.
Definition: unit.hpp:1008
int damage_from(const attack_type &attack, bool attacker, const map_location &loc, const_attack_ptr weapon=nullptr) const
Calculates the damage this unit would take from a certain attack.
Definition: unit.hpp:974
int defense_modifier(const t_translation::terrain_code &terrain) const
The unit's defense on a given terrain.
Definition: unit.cpp:1746
bool remove_attack(attack_ptr atk)
Remove an attack from the unit.
Definition: unit.cpp:2766
attack_itors attacks()
Gets an iterator over this unit's attacks.
Definition: unit.hpp:929
utils::string_map_res get_base_resistances() const
Gets resistances without any abilities applied.
Definition: unit.hpp:1051
int max_attacks() const
The maximum number of attacks this unit may perform per turn, usually 1.
Definition: unit.hpp:980
int resistance_against(const std::string &damage_name, bool attacker, const map_location &loc, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
The unit's resistance against a given damage type.
Definition: unit.cpp:1789
const_attack_itors attacks() const
Const overload of attacks.
Definition: unit.hpp:935
int attacks_left() const
Gets the remaining number of attacks this unit can perform this turn.
Definition: unit.hpp:996
void set_attacks(int left)
Sets the number of attacks this unit has left this turn.
Definition: unit.hpp:1017
const std::vector< std::string > halo_abilities() const
Get the [halo] abilities halo image(s).
Definition: unit.hpp:1566
color_t xp_color() const
Color for this unit's XP.
Definition: unit.cpp:1153
unit_animation_component & anim_comp() const
Definition: unit.hpp:1546
const std::string & effect_image_mods() const
Gets any IPF image mods applied by effects.
Definition: unit.hpp:1596
color_t hp_color() const
Color for this unit's current hitpoints.
Definition: unit.cpp:1099
const std::vector< std::string > halo_or_icon_abilities(const std::string &image_type) const
Definition: abilities.cpp:489
std::string TC_image_mods() const
Constructs a recolor (RC) IPF string for this unit's team color.
Definition: unit.cpp:2751
const std::vector< std::string > overlays_abilities() const
Get the [overlay] ability overlay images.
Definition: unit.hpp:1615
static color_t hp_color_max()
Definition: unit.cpp:1109
const std::string & flag_rgb() const
Get the source color palette to use when recoloring the unit's image.
Definition: unit.cpp:1056
std::string image_ellipse() const
Get the unit's ellipse image.
Definition: unit.hpp:1575
std::string image_mods() const
Gets an IPF string containing all IPF image mods.
Definition: unit.cpp:2756
std::string default_anim_image() const
The default image to use for animation frames with no defined image.
Definition: unit.cpp:2580
std::string image_halo() const
Get the unit's halo image.
Definition: unit.hpp:1558
const std::vector< std::string > & overlays() const
Get the unit's overlay images.
Definition: unit.hpp:1609
std::string absolute_image() const
The name of the file to game_display (used in menus).
Definition: unit.cpp:2575
void set_image_ellipse(const std::string &ellipse)
Set the unit's ellipse image.
Definition: unit.hpp:1581
void set_image_halo(const std::string &halo)
Set the unit's halo image.
Definition: unit.cpp:2808
void apply_builtin_effect(std::string type, const config &effect)
Apply a builtin effect to the unit.
Definition: unit.cpp:2041
void add_modification(const std::string &type, const config &modification, bool no_add=false)
Add a new modification to the unit.
Definition: unit.cpp:2422
static const std::set< std::string > builtin_effects
Definition: unit.hpp:1519
const config & get_modifications() const
Set the raw modifications.
Definition: unit.hpp:1487
std::string describe_builtin_effect(std::string type, const config &effect)
Construct a string describing a built-in effect.
Definition: unit.cpp:1976
config & get_modifications()
Get the raw modifications.
Definition: unit.hpp:1481
void apply_modifications()
Re-apply all saved modifications.
Definition: unit.cpp:2585
void expire_modifications(const std::string &duration)
Clears those modifications whose duration has expired.
Definition: unit.cpp:1219
std::size_t modification_count(const std::string &type, const std::string &id) const
Count modifications of a particular type.
Definition: unit.cpp:1950
bool emits_zoc() const
Tests whether the unit has a zone-of-control, considering incapacitated.
Definition: unit.hpp:1340
bool get_emit_zoc() const
Gets the raw zone-of-control flag, disregarding incapacitated.
Definition: unit.hpp:1346
int jamming() const
Gets the unit's jamming points.
Definition: unit.hpp:1408
bool has_goto() const
Gets whether this unit has a multi-turn destination set.
Definition: unit.hpp:1384
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1359
bool has_moved() const
Checks if this unit has moved.
Definition: unit.hpp:1314
void set_facing(map_location::DIRECTION dir) const
The this unit's facing.
Definition: unit.cpp:1722
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
Definition: unit.hpp:1442
const movetype & movement_type() const
Get the unit's movement type.
Definition: unit.hpp:1432
map_location::DIRECTION facing() const
The current direction this unit is facing within its hex.
Definition: unit.hpp:1375
void set_movement(int moves, bool unit_action=false)
Set this unit's remaining movement to moves.
Definition: unit.cpp:1193
const map_location & get_interrupted_move() const
Get the target location of the unit's interrupted move.
Definition: unit.hpp:1420
int vision_cost(const t_translation::terrain_code &terrain) const
Get the unit's vision cost on a particular terrain.
Definition: unit.hpp:1452
void set_resting(bool rest)
Sets this unit's resting status.
Definition: unit.hpp:1334
void set_total_movement(int value)
Definition: unit.hpp:1273
void set_emit_zoc(bool val)
Sets the raw zone-of-control flag.
Definition: unit.hpp:1352
void set_goto(const map_location &new_goto)
Sets this unit's long term destination.
Definition: unit.hpp:1396
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition: unit.hpp:1284
int movement_left(bool base_value) const
Gets how far a unit can move.
Definition: unit.hpp:1296
int total_movement() const
The maximum moves this unit has.
Definition: unit.hpp:1268
int jamming_cost(const t_translation::terrain_code &terrain) const
Get the unit's jamming cost on a particular terrain.
Definition: unit.hpp:1462
void set_location(const map_location &loc)
Sets this unit's map location.
Definition: unit.hpp:1369
void remove_movement_ai()
Sets the unit to have no moves left for this turn.
Definition: unit.cpp:2786
bool move_interrupted() const
Check whether the unit's move has been interrupted.
Definition: unit.hpp:1414
int vision() const
Gets the unit's vision points.
Definition: unit.hpp:1402
const map_location & get_goto() const
The map location to which this unit is moving over multiple turns, if any.
Definition: unit.hpp:1390
bool resting() const
Checks whether this unit is 'resting'.
Definition: unit.hpp:1328
void set_interrupted_move(const map_location &interrupted_move)
Set the target location of the unit's interrupted move.
Definition: unit.hpp:1426
bool is_flying() const
Check if the unit is a flying unit.
Definition: unit.hpp:1468
int upkeep() const
Gets the amount of gold this unit costs a side per turn.
Definition: unit.cpp:1731
void add_trait_description(const config &trait, const t_string &description)
Register a trait's name and its description for the UI's use.
Definition: unit.cpp:2562
bool is_healthy() const
Gets whether this unit is healthy - ie, always rest heals.
Definition: unit.hpp:1255
bool is_fearless() const
Gets whether this unit is fearless - ie, unaffected by time of day.
Definition: unit.hpp:1249
std::vector< std::string > get_traits_list() const
Gets a list of the traits this unit currently has.
Definition: unit.cpp:873
utils::variant< upkeep_full, upkeep_loyal, int > upkeep_t
Definition: unit.hpp:1139
const std::vector< t_string > & trait_descriptions() const
Gets the descriptions of the currently registered traits.
Definition: unit.hpp:1095
const std::vector< t_string > & trait_names() const
Gets the names of the currently registered traits.
Definition: unit.hpp:1085
void generate_traits(bool must_have_only=false)
Applies mandatory traits (e.g.
Definition: unit.cpp:740
upkeep_t upkeep_raw() const
Gets the raw variant controlling the upkeep value.
Definition: unit.hpp:1234
bool loyal() const
Gets whether this unit is loyal - ie, it costs no upkeep.
Definition: unit.cpp:1741
void set_upkeep(upkeep_t v)
Sets the upkeep value to a specific value value.
Definition: unit.hpp:1240
Definition: display.hpp:45
std::map< std::string, t_string, res_compare > string_map_res
std::map< std::string, t_string > string_map
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
std::shared_ptr< const attack_type > const_attack_ptr
Definition: ptr.hpp:34
std::shared_ptr< attack_type > attack_ptr
Definition: ptr.hpp:33
std::shared_ptr< unit > unit_ptr
Definition: ptr.hpp:26
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
Encapsulates the map of the game.
Definition: location.hpp:38
DIRECTION
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:40
bool valid() const
Definition: location.hpp:89
std::size_t value
Definition: id.hpp:27
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
Visitor helper struct to fetch the upkeep type flag if applicable, or the the value otherwise.
Definition: unit.hpp:1176
Data typedef for unit_ability_list.
Definition: unit.hpp:40
map_location student_loc
Used by the formula in the ability.
Definition: unit.hpp:54
unit_ability(const config *ability_cfg, map_location student_loc, map_location teacher_loc)
Definition: unit.hpp:41
const config * ability_cfg
The contents of the ability tag, never nullptr.
Definition: unit.hpp:61
map_location teacher_loc
The location of the teacher, that is the unit who owns the ability tags (different from student becau...
Definition: unit.hpp:59
Object which temporarily resets a unit's movement.
Definition: unit.hpp:2030
static map_location::DIRECTION n
static map_location::DIRECTION s
std::string get_checksum(const unit &u, backwards_compatibility::unit_checksum_version version=backwards_compatibility::unit_checksum_version::current)
Gets a checksum for a unit.
Definition: unit.cpp:2848
MacOS doesn't support std::visit when targing MacOS < 10.14 (currently we target 10....
#define b