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