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  * The unit's resistance against a given damage type
1028  * @param damage_name The damage type
1029  * @param attacker True if this unit is on the offensive (to resolve [resistance] abilities)
1030  * @param loc The unit's location (to resolve [resistance] abilities)
1031  * @param weapon The weapon to check for any abilities or weapon specials
1032  * @param opp_weapon The opponent's weapon to check for any abilities or weapon specials
1033  */
1034  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;
1035 
1036  /**
1037  * The unit's resistance against a given attack
1038  * @param atk The attack
1039  * @param attacker True if this unit is on the offensive (to resolve [resistance] abilities)
1040  * @param loc The unit's location (to resolve [resistance] abilities)
1041  * @param weapon The weapon to check for any abilities or weapon specials
1042  */
1043  int resistance_against(const attack_type& atk, bool attacker, const map_location& loc, const_attack_ptr weapon = nullptr) const
1044  {
1045  return resistance_against(atk.type(), attacker, loc , weapon, atk.shared_from_this());
1046  }
1047 
1048  /** Gets resistances without any abilities applied. */
1050  {
1051  return movement_type_.damage_table();
1052  }
1053 
1054 private:
1055  bool resistance_filter_matches(const config& cfg, bool attacker, const std::string& damage_name, int res) const;
1056 
1057  /**
1058  * @}
1059  * @defgroup unit_trait Trait and upkeep functions
1060  * @{
1061  */
1062 public:
1063  /**
1064  * Applies mandatory traits (e.g. undead, mechanical) to a unit and then fills in the remaining traits
1065  * traits until no more are available (leaders have a restricted set of available traits) or the unit has
1066  * its maximum number of traits.
1067  *
1068  * This routine does not apply the effects of added traits to a unit; that must be done by the caller.
1069  *
1070  * Note that random numbers used in config files don't work in multiplayer, so leaders should be barred
1071  * from all random traits until that is fixed. Later the restrictions will be based on play balance.
1072  *
1073  * @param must_have_only Whether random or optional traits should be included or not. If false only
1074  * mandatory traits will be used.
1075  */
1076  void generate_traits(bool must_have_only = false);
1077 
1078  /**
1079  * Gets the names of the currently registered traits.
1080  *
1081  * @returns A list of translatable trait names.
1082  */
1083  const std::vector<t_string>& trait_names() const
1084  {
1085  return trait_names_;
1086  }
1087 
1088  /**
1089  * Gets the descriptions of the currently registered traits.
1090  *
1091  * @returns A list of translatable trait descriptions.
1092  */
1093  const std::vector<t_string>& trait_descriptions() const
1094  {
1095  return trait_descriptions_;
1096  }
1097 
1098  /**
1099  * Gets a list of the traits this unit currently has.
1100  *
1101  * @returns A list of trait IDs.
1102  */
1103  std::vector<std::string> get_traits_list() const;
1104 
1105  /**
1106  * Register a trait's name and its description for the UI's use.
1107  *
1108  * The resulting data can be fetched with @ref trait_names and @ref trait_descriptions.
1109  *
1110  * @param trait A config containing the trait's attributes.
1111  * @param description The translatable description of the trait.
1112  */
1113  void add_trait_description(const config& trait, const t_string& description);
1114 
1115  /**
1116  * Gets the amount of gold this unit costs a side per turn.
1117  *
1118  * This fetches an actual numeric gold value:
1119  * - If can_recruit is true, no upkeep is paid (0 is returned).
1120  * - If a special upkeep flag is set, the associated gold amount is returned (see @ref upkeep_value_visitor).
1121  * - If a numeric value is already set, it is returned directly.
1122  *
1123  * @returns A gold value, evaluated based on the state of @ref upkeep_raw.
1124  */
1125  int upkeep() const;
1126 
1128  {
1129  static std::string type() { static std::string v = "full"; return v; }
1130  };
1131 
1133  {
1134  static std::string type() { static std::string v = "loyal"; return v; }
1135  };
1136 
1137  using upkeep_t = utils::variant<upkeep_full, upkeep_loyal, int>;
1138 
1139  /** Visitor helper class to fetch the appropriate upkeep value. */
1141 #ifdef USING_BOOST_VARIANT
1142  : public boost::static_visitor<int>
1143 #endif
1144  {
1145  public:
1146  explicit upkeep_value_visitor(const unit& unit) : u_(unit) {}
1147 
1148  /** Full upkeep equals the unit's level. */
1149  int operator()(const upkeep_full&) const
1150  {
1151  return u_.level();
1152  }
1153 
1154  /** Loyal units cost no upkeep. */
1155  int operator()(const upkeep_loyal&) const
1156  {
1157  return 0;
1158  }
1159 
1160  int operator()(int v) const
1161  {
1162  return v;
1163  }
1164 
1165  private:
1166  const unit& u_;
1167  };
1168 
1169  /** Visitor helper struct to fetch the upkeep type flag if applicable, or the the value otherwise. */
1171 #ifdef USING_BOOST_VARIANT
1172  : public boost::static_visitor<std::string>
1173 #endif
1174  {
1175  template<typename T>
1176  std::enable_if_t<!std::is_same_v<int, T>, std::string>
1177  operator()(T&) const
1178  {
1179  // Any special upkeep type should have an associated @ref type getter in its helper struct.
1180  return T::type();
1181  }
1182 
1183  std::string operator()(int v) const
1184  {
1185  return std::to_string(v);
1186  }
1187  };
1188 
1189  /** Visitor helper class to parse the upkeep value from a config. */
1191 #ifdef USING_BOOST_VARIANT
1192  : public boost::static_visitor<upkeep_t>
1193 #endif
1194  {
1195  public:
1196  template<typename N>
1197  std::enable_if_t<std::is_arithmetic_v<N>, upkeep_t>
1198  operator()(N n) const
1199  {
1200  if(n == 0) return upkeep_loyal();
1201  if(n < 0) throw std::invalid_argument(std::to_string(n));
1202  return static_cast<int>(n);
1203  }
1204 
1205  template<typename B>
1206  std::enable_if_t<std::is_convertible_v<B, bool> && !std::is_arithmetic_v<B>, upkeep_t>
1207  operator()(B b) const
1208  {
1209  throw std::invalid_argument(b.str());
1210  }
1211 
1212  upkeep_t operator()(utils::monostate) const
1213  {
1214  return upkeep_full();
1215  }
1216 
1217  upkeep_t operator()(const std::string& s) const
1218  {
1219  if(s == "loyal" || s == "free")
1220  return upkeep_loyal();
1221  if(s == "full")
1222  return upkeep_full();
1223  throw std::invalid_argument(s);
1224  }
1225  };
1226 
1227  /**
1228  * Gets the raw variant controlling the upkeep value.
1229  *
1230  * This should not usually be called directly. To get an actual numeric value of upkeep use @ref upkeep.
1231  */
1233  {
1234  return upkeep_;
1235  }
1236 
1237  /** Sets the upkeep value to a specific value value. Does not necessarily need to be numeric */
1239  {
1240  upkeep_ = v;
1241  }
1242 
1243  /** Gets whether this unit is loyal - ie, it costs no upkeep. */
1244  bool loyal() const;
1245 
1246  /** Gets whether this unit is fearless - ie, unaffected by time of day. */
1247  bool is_fearless() const
1248  {
1249  return is_fearless_;
1250  }
1251 
1252  /** Gets whether this unit is healthy - ie, always rest heals. */
1253  bool is_healthy() const
1254  {
1255  return is_healthy_;
1256  }
1257 
1258  /**
1259  * @}
1260  * @defgroup unit_mvmt Movement and location functions
1261  * @{
1262  */
1263 
1264 public:
1265  /** The maximum moves this unit has. */
1266  int total_movement() const
1267  {
1268  return max_movement_;
1269  }
1270 
1271  void set_total_movement(int value)
1272  {
1274  max_movement_ = value;
1275  }
1276 
1277  /**
1278  * Gets how far a unit can move, considering the `incapacitated` flag.
1279  *
1280  * @returns The remaining movement, or zero if incapacitated.
1281  */
1282  int movement_left() const
1283  {
1284  return (movement_ == 0 || incapacitated()) ? 0 : movement_;
1285  }
1286 
1287  /**
1288  * Gets how far a unit can move.
1289  *
1290  * @param base_value If false, consider the `incapacitated` flag.
1291  *
1292  * @returns If @a base_value is true, the raw value is returned.
1293  */
1294  int movement_left(bool base_value) const
1295  {
1296  return base_value ? movement_ : movement_left();
1297  }
1298 
1299  /**
1300  * Set this unit's remaining movement to @a moves.
1301  *
1302  * This does not affect maximum movement.
1303  *
1304  * @param moves The new number of moves
1305  * @param unit_action If to true, the "end turn" and "hold position" flags will be cleared
1306  * (as they should be if a unit acts, as opposed to the movement being set
1307  * by the engine for other reasons).
1308  */
1309  void set_movement(int moves, bool unit_action = false);
1310 
1311  /** Checks if this unit has moved. */
1312  bool has_moved() const
1313  {
1314  return movement_left() != total_movement();
1315  }
1316 
1317  /** Sets the unit to have no moves left for this turn. */
1318  void remove_movement_ai();
1319 
1320  /**
1321  * Checks whether this unit is 'resting'.
1322  *
1323  * Resting refers to whether this unit has not moved yet this turn. Note that this can be true even
1324  * if @ref movement_left is not equal to @ref total_movement.
1325  */
1326  bool resting() const
1327  {
1328  return resting_;
1329  }
1330 
1331  /** Sets this unit's resting status. */
1332  void set_resting(bool rest)
1333  {
1334  resting_ = rest;
1335  }
1336 
1337  /** Tests whether the unit has a zone-of-control, considering @ref incapacitated. */
1338  bool emits_zoc() const
1339  {
1340  return emit_zoc_ && !incapacitated();
1341  }
1342 
1343  /** Gets the raw zone-of-control flag, disregarding @ref incapacitated. */
1344  bool get_emit_zoc() const
1345  {
1346  return emit_zoc_;
1347  }
1348 
1349  /** Sets the raw zone-of-control flag. */
1350  void set_emit_zoc(bool val)
1351  {
1353  emit_zoc_ = val;
1354  }
1355 
1356  /** The current map location this unit is at. */
1358  {
1359  return loc_;
1360  }
1361 
1362  /**
1363  * Sets this unit's map location.
1364  *
1365  * Note this should only be called by unit_map or for temporary units.
1366  */
1367  void set_location(const map_location& loc)
1368  {
1369  loc_ = loc;
1370  }
1371 
1372  /** The current direction this unit is facing within its hex. */
1374  {
1375  return facing_;
1376  }
1377 
1378  /** The this unit's facing. */
1379  void set_facing(map_location::DIRECTION dir) const;
1380 
1381  /** Gets whether this unit has a multi-turn destination set. */
1382  bool has_goto() const
1383  {
1384  return get_goto().valid();
1385  }
1386 
1387  /** The map location to which this unit is moving over multiple turns, if any. */
1388  const map_location& get_goto() const
1389  {
1390  return goto_;
1391  }
1392 
1393  /** Sets this unit's long term destination. */
1394  void set_goto(const map_location& new_goto)
1395  {
1396  goto_ = new_goto;
1397  }
1398 
1399  /** Gets the unit's vision points. */
1400  int vision() const
1401  {
1402  return vision_ < 0 ? max_movement_ : vision_;
1403  }
1404 
1405  /** Gets the unit's jamming points. */
1406  int jamming() const
1407  {
1408  return jamming_;
1409  }
1410 
1411  /** Check whether the unit's move has been interrupted. */
1412  bool move_interrupted() const
1413  {
1414  return movement_left() > 0 && interrupted_move_.x >= 0 && interrupted_move_.y >= 0;
1415  }
1416 
1417  /** Get the target location of the unit's interrupted move. */
1419  {
1420  return interrupted_move_;
1421  }
1422 
1423  /** Set the target location of the unit's interrupted move. */
1424  void set_interrupted_move(const map_location& interrupted_move)
1425  {
1426  interrupted_move_ = interrupted_move;
1427  }
1428 
1429  /** Get the unit's movement type. */
1430  const movetype& movement_type() const
1431  {
1432  return movement_type_;
1433  }
1434 
1435  /**
1436  * Get the unit's movement cost on a particular terrain
1437  * @param terrain The terrain to check
1438  * @returns the number of movement points to enter that terrain
1439  */
1440  int movement_cost(const t_translation::terrain_code& terrain) const
1441  {
1443  }
1444 
1445  /**
1446  * Get the unit's vision cost on a particular terrain
1447  * @param terrain The terrain to check
1448  * @returns the number of vision points to see into that terrain
1449  */
1450  int vision_cost(const t_translation::terrain_code& terrain) const
1451  {
1453  }
1454 
1455  /**
1456  * Get the unit's jamming cost on a particular terrain
1457  * @param terrain The terrain to check
1458  * @returns the number of jamming points to jam that terrain
1459  */
1460  int jamming_cost(const t_translation::terrain_code& terrain) const
1461  {
1463  }
1464 
1465  /** Check if the unit is a flying unit. */
1466  bool is_flying() const
1467  {
1468  return movement_type_.is_flying();
1469  }
1470 
1471  /**
1472  * @}
1473  * @defgroup unit_mod Modification functions
1474  * @{
1475  */
1476 
1477 public:
1478  /** Get the raw modifications. */
1480  {
1481  return modifications_;
1482  }
1483 
1484  /** Set the raw modifications. */
1485  const config& get_modifications() const
1486  {
1487  return modifications_;
1488  }
1489 
1490  /**
1491  * Count modifications of a particular type.
1492  * @param type The type of modification to count.
1493  * Valid values are "advancement", "trait", "object"
1494  * @param id The ID of the modification to count
1495  * @return The total number of modifications of that type and ID.
1496  */
1497  std::size_t modification_count(const std::string& type, const std::string& id) const;
1498 
1499  /**
1500  * Add a new modification to the unit.
1501  * @param type The type of modification to add.
1502  * Valid values are "advancement", "trait", "object"
1503  * @param modification The details of the modification
1504  * @param no_add If true, apply the modification but don't save it for unit rebuild time.
1505  * Defaults to false.
1506  */
1507  void add_modification(const std::string& type, const config& modification, bool no_add = false);
1508 
1509  /**
1510  * Clears those modifications whose duration has expired.
1511  *
1512  * @param duration If empty, all temporary modifications (those not lasting forever) expire.
1513  * Otherwise, modifications whose duration equals @a duration expire.
1514  */
1515  void expire_modifications(const std::string& duration);
1516 
1517  static const std::set<std::string> builtin_effects;
1518 
1519  /**
1520  * Apply a builtin effect to the unit.
1521  * @param type The effect to apply. Must be one of the effects in @ref builtin_effects.
1522  * @param effect The details of the effect
1523  */
1524  void apply_builtin_effect(std::string type, const config& effect);
1525 
1526  /**
1527  * Construct a string describing a built-in effect.
1528  * @param type The effect to describe. Must be one of the effects in @ref builtin_effects.
1529  * @param effect The details of the effect
1530  */
1531  std::string describe_builtin_effect(std::string type, const config& effect);
1532 
1533  /** Re-apply all saved modifications. */
1534  void apply_modifications();
1535 
1536  /**
1537  * @}
1538  * @defgroup unit_img Image and animations functions
1539  * @{
1540  */
1541 
1542 public:
1543  /** @todo Document this */
1545  {
1546  return *anim_comp_;
1547  }
1548 
1549  /** The name of the file to game_display (used in menus). */
1550  std::string absolute_image() const;
1551 
1552  /** The default image to use for animation frames with no defined image. */
1553  std::string default_anim_image() const;
1554 
1555  /** Get the unit's halo image. */
1556  std::string image_halo() const
1557  {
1558  return halo_.value_or("");
1559  }
1560 
1561  const std::vector<std::string> halo_or_icon_abilities(const std::string& image_type) const;
1562 
1563  /** Get the [halo] abilities halo image(s). */
1564  const std::vector<std::string> halo_abilities() const
1565  {
1566  return halo_or_icon_abilities("halo");
1567  }
1568 
1569  /** Set the unit's halo image. */
1570  void set_image_halo(const std::string& halo);
1571 
1572  /** Get the unit's ellipse image. */
1573  std::string image_ellipse() const
1574  {
1575  return ellipse_.value_or("");
1576  }
1577 
1578  /** Set the unit's ellipse image. */
1579  void set_image_ellipse(const std::string& ellipse)
1580  {
1581  appearance_changed_ = true;
1582  ellipse_ = ellipse;
1583  }
1584 
1585  /**
1586  * Get the source color palette to use when recoloring the unit's image.
1587  */
1588  const std::string& flag_rgb() const;
1589 
1590  /** Constructs a recolor (RC) IPF string for this unit's team color. */
1591  std::string TC_image_mods() const;
1592 
1593  /** Gets any IPF image mods applied by effects. */
1594  const std::string& effect_image_mods() const
1595  {
1596  return image_mods_;
1597  }
1598 
1599  /**
1600  * Gets an IPF string containing all IPF image mods.
1601  *
1602  * @returns An amalgamation of @ref effect_image_mods followed by @ref TC_image_mods.
1603  */
1604  std::string image_mods() const;
1605 
1606  /** Get the unit's overlay images. */
1607  const std::vector<std::string>& overlays() const
1608  {
1609  return overlays_;
1610  }
1611 
1612  /** Get the [overlay] ability overlay images. */
1613  const std::vector<std::string> overlays_abilities() const
1614  {
1615  return halo_or_icon_abilities("overlay");
1616  }
1617  /**
1618  * Color for this unit's *current* hitpoints.
1619  *
1620  * @returns A color between green and red representing how wounded this unit is.
1621  * The maximum_hitpoints are considered as base.
1622  */
1623  color_t hp_color() const;
1624  static color_t hp_color_max();
1625 
1626  /**
1627  * Color for this unit's hitpoints.
1628  *
1629  * @param hitpoints The number of hitpoints the color represents.
1630  * @returns The color considering the current hitpoints as base.
1631  */
1632  color_t hp_color(int hitpoints) const;
1633 
1634  /**
1635  * Color for this unit's XP. See also @ref hp_color
1636  */
1637  color_t xp_color() const;
1638  static color_t xp_color(int xp_to_advance, bool can_advance, bool has_amla);
1639 
1640  /**
1641  * @}
1642  * @defgroup unit_abil Ability functions
1643  * @{
1644  */
1645 
1646 public:
1647  /**
1648  * Checks whether this unit currently possesses or is affected by a given ability.
1649  *
1650  * This means that the ability could be owned by this unit itself or by an adjacent unit, should
1651  * the ability affect an AoE in which this unit happens to be.
1652  *
1653  * @param tag_name The name of the ability to check for.
1654  * @param loc The location around which to check for affected units. This may or
1655  * may not be the location of this unit.
1656  */
1657  bool get_ability_bool(const std::string& tag_name, const map_location& loc) const;
1658 
1659  /**
1660  * Checks whether this unit currently possesses or is affected by a given ability.
1661  *
1662  * This means that the ability could be owned by this unit itself or by an adjacent unit, should
1663  * the ability affect an AoE in which this unit happens to be.
1664  *
1665  * This overload uses the location of this unit for calculations.
1666  *
1667  * @param tag_name The name of the ability to check for.
1668  */
1669  bool get_ability_bool(const std::string& tag_name) const
1670  {
1671  return get_ability_bool(tag_name, loc_);
1672  }
1673 
1674  /** Checks whether this unit currently possesses a given ability used like weapon
1675  * @return True if the ability @a tag_name is active.
1676  * @param special the const config to one of abilities @a tag_name checked.
1677  * @param tag_name name of ability type checked.
1678  * @param loc location of the unit checked.
1679  */
1680  bool get_self_ability_bool(const config& special, const std::string& tag_name, const map_location& loc) const;
1681  /** Checks whether this unit currently possesses a given ability of leadership type
1682  * @return True if the ability @a tag_name is active.
1683  * @param special the const config to one of abilities @a tag_name checked.
1684  * @param tag_name name of ability type checked.
1685  * @param loc location of the unit checked.
1686  * @param weapon the attack used by unit checked in this function.
1687  * @param opp_weapon the attack used by opponent to unit checked.
1688  */
1689  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;
1690  /** Checks whether this unit is affected by a given ability used like weapon
1691  * @return True if the ability @a tag_name is active.
1692  * @param special the const config to one of abilities @a tag_name checked.
1693  * @param tag_name name of ability type checked.
1694  * @param loc location of the unit checked.
1695  * @param from unit adjacent to @a this is checked in case of [affect_adjacent] abilities.
1696  * @param dir direction to research a unit adjacent to @a this.
1697  */
1698  bool get_adj_ability_bool(const config& special, const std::string& tag_name, int dir, const map_location& loc, const unit& from) const;
1699  /** Checks whether this unit is affected by a given ability of leadership type
1700  * @return True if the ability @a tag_name is active.
1701  * @param special the const config to one of abilities @a tag_name checked.
1702  * @param tag_name name of ability type checked.
1703  * @param loc location of the unit checked.
1704  * @param from unit adjacent to @a this is checked in case of [affect_adjacent] abilities.
1705  * @param dir direction to research a unit adjacent to @a this.
1706  * @param weapon the attack used by unit checked in this function.
1707  * @param opp_weapon the attack used by opponent to unit checked.
1708  */
1709  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;
1710 
1711  /**
1712  * Gets the unit's active abilities of a particular type if it were on a specified location.
1713  * @param tag_name The type of ability to check for
1714  * @param loc The location to use for resolving abilities
1715  * @return A list of active abilities, paired with the location they are active on
1716  */
1717  unit_ability_list get_abilities(const std::string& tag_name, const map_location& loc) const;
1718 
1719  /**
1720  * Gets the unit's active abilities of a particular type.
1721  * @param tag_name The type of ability to check for
1722  * @return A list of active abilities, paired with the location they are active on
1723  */
1724  unit_ability_list get_abilities(const std::string& tag_name) const
1725  {
1726  return get_abilities(tag_name, loc_);
1727  }
1728 
1729  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;
1730 
1731  unit_ability_list get_abilities_weapons(const std::string& tag_name, const_attack_ptr weapon = nullptr, const_attack_ptr opp_weapon = nullptr) const
1732  {
1733  return get_abilities_weapons(tag_name, loc_, weapon, opp_weapon);
1734  }
1735 
1736  const config &abilities() const { return abilities_; }
1737 
1738  const std::set<std::string>& checking_tags() const { return checking_tags_; };
1739 
1740  /**
1741  * Gets the names and descriptions of this unit's abilities. Location-independent variant
1742  * with all abilities shown as active.
1743  *
1744  * @returns A list of quadruples consisting of (in order) id, base name,
1745  * male or female name as appropriate for the unit, and description.
1746  */
1747  std::vector<std::tuple<std::string, t_string, t_string, t_string>>
1748  ability_tooltips() const;
1749 
1750  /**
1751  * Gets the names and descriptions of this unit's abilities.
1752  *
1753  * @param active_list This vector will be the same length as the returned one and will
1754  * indicate whether or not the corresponding ability is active.
1755  *
1756  * @param loc The location on which to resolve the ability.
1757  *
1758  * @returns A list of quadruples consisting of (in order) id, base name,
1759  * male or female name as appropriate for the unit, and description.
1760  */
1761  std::vector<std::tuple<std::string, t_string, t_string, t_string>>
1762  ability_tooltips(boost::dynamic_bitset<>& active_list, const map_location& loc) const;
1763 
1764  /** Get a list of all abilities by ID. */
1765  std::vector<std::string> get_ability_list() const;
1766 
1767  /**
1768  * Check if the unit has an ability of a specific type.
1769  * @param ability The type of ability (tag name) to check for.
1770  * @returns true if the ability is present
1771  */
1772  bool has_ability_type(const std::string& ability) const;
1773 
1774  /**
1775  * Check if the unit has an ability of a specific ID.
1776  * @param ability The ID of ability to check for.
1777  * @returns true if the ability is present
1778  */
1779  bool has_ability_by_id(const std::string& ability) const;
1780 
1781  /**
1782  * Removes a unit's abilities with a specific ID.
1783  * @param ability The type of ability (tag name) to remove.
1784  */
1785  void remove_ability_by_id(const std::string& ability);
1786 
1787  /**
1788  * Removes a unit's abilities with a specific ID or other attribute.
1789  * @param filter the config of ability to remove.
1790  */
1791  void remove_ability_by_attribute(const config& filter);
1792 
1793  /**
1794  * Verify what abilities attributes match with filter.
1795  * @param cfg the config of ability to check.
1796  * @param tag_name the tag name of ability to check.
1797  * @param filter the filter used for checking.
1798  */
1799  bool ability_matches_filter(const config & cfg, const std::string& tag_name, const config & filter) const;
1800 
1801 
1802 private:
1803 
1804  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"};
1805  /**
1806  * Check if an ability is active.
1807  * @param ability The type (tag name) of the ability
1808  * @param cfg an ability WML structure
1809  * @param loc The location on which to resolve the ability
1810  * @returns true if it is active
1811  */
1812  bool ability_active(const std::string& ability, const config& cfg, const map_location& loc) const;
1813 
1814  /**
1815  * Check if an ability affects adjacent units.
1816  * @param ability The type (tag name) of the ability
1817  * @param cfg an ability WML structure
1818  * @param loc The location on which to resolve the ability
1819  * @param from The "other unit" for filter matching
1820  * @param dir The direction the unit is facing
1821  */
1822  bool ability_affects_adjacent(const std::string& ability, const config& cfg, int dir, const map_location& loc, const unit& from) const;
1823 
1824  /**
1825  * Check if an ability affects the owning unit.
1826  * @param ability The type (tag name) of the ability
1827  * @param cfg an ability WML structure
1828  * @param loc The location on which to resolve the ability
1829  */
1830  bool ability_affects_self(const std::string& ability, const config& cfg, const map_location& loc) const;
1831 
1832  /**
1833  * filters the weapons that condition the use of abilities for combat ([resistance],[leadership] or abilities used like specials
1834  * (deprecated in two last cases)
1835  */
1836  bool ability_affects_weapon(const config& cfg, const_attack_ptr weapon, bool is_opp) const;
1837 
1838 public:
1839  /** Get the unit formula manager. */
1841  {
1842  return *formula_man_;
1843  }
1844 
1845  /** Generates a random race-appropriate name if one has not already been provided. */
1846  void generate_name();
1847 
1848  // Only see_all = true use caching
1849  bool invisible(const map_location& loc, bool see_all = true) const;
1850 
1851  bool is_visible_to_team(const team& team, bool const see_all = true) const;
1852  /** Return true if the unit would be visible to team if its location were loc. */
1853  bool is_visible_to_team(const map_location& loc, const team& team, bool const see_all = true) const;
1854 
1855  /**
1856  * Serializes the current unit metadata values.
1857  *
1858  * @param cfg The config to write to.
1859  * @param write_all set this to false to not write unchanged attributes.
1860  */
1861  void write(config& cfg, bool write_all = true) const;
1862 
1863  /**
1864  * Mark this unit as clone so it can be inserted to unit_map.
1865  *
1866  * @returns self (for convenience)
1867  */
1868  unit& mark_clone(bool is_temporary);
1869 
1870 
1871  void set_appearance_changed(bool value) { appearance_changed_ = value; }
1872  bool appearance_changed() const { return appearance_changed_; }
1873 
1874 protected:
1875 
1876 private:
1878 
1879  std::vector<std::string> advances_to_;
1880 
1881  /** Never nullptr. Adjusted for gender and variation. */
1883 
1884  /** The displayed name of this unit type. */
1886 
1887  /** Never nullptr, but may point to the null race. */
1889 
1890  std::string id_;
1893 
1894  std::string undead_variation_;
1895  std::string variation_;
1896 
1901 
1902  int level_;
1903 
1906  std::vector<std::string> recruit_list_;
1908 
1909  std::string flag_rgb_;
1910  std::string image_mods_;
1911 
1913 
1914  int side_;
1915 
1917 
1918  std::unique_ptr<unit_formula_manager> formula_man_;
1919 
1922  int vision_;
1924 
1926 
1929  bool resting_;
1930 
1933 
1934  std::set<std::string> states_;
1935 
1936  static const std::size_t num_bool_states = state_t::NUMBER_OF_STATES;
1937 
1938  std::bitset<num_bool_states> known_boolean_states_;
1939  static std::map<std::string, state_t> known_boolean_state_names_;
1940 
1944 
1946 
1947  std::vector<std::string> overlays_;
1948 
1949  std::string role_;
1951 
1952 protected:
1953  // TODO: I think we actually consider this to be part of the gamestate, so it might be better if it's not mutable,
1954  // but it's not easy to separate this guy from the animation code right now.
1956 
1957 private:
1958  std::vector<t_string> trait_names_;
1959  std::vector<t_string> trait_descriptions_;
1960 
1963 
1965 
1967 
1968  // Animations:
1970 
1971  std::unique_ptr<unit_animation_component> anim_comp_;
1972 
1973  mutable bool hidden_;
1975 
1978 
1979  std::vector<config> advancements_;
1980 
1982  std::vector<t_string> special_notes_;
1983 
1984  std::optional<std::string> usage_;
1985  std::optional<std::string> halo_;
1986  std::optional<std::string> ellipse_;
1987 
1990 
1992 
1993  std::string profile_;
1994  std::string small_profile_;
1995 
1996  //Used to check whether the moving units during a move needs to be updated
1997  mutable bool appearance_changed_ = true;
1998  std::bitset<UA_COUNT> changed_attributes_;
1999 
2002 
2003  /**
2004  * Hold the visibility status cache for a unit, when not uncovered.
2005  * This is mutable since it is a cache.
2006  */
2007  mutable std::map<map_location, bool> invisibility_cache_;
2008 
2009  /**
2010  * Clears the cache.
2011  *
2012  * Since we don't change the state of the object we're marked const (also
2013  * required since the objects in the cache need to be marked const).
2014  */
2016  {
2017  invisibility_cache_.clear();
2018  }
2019 };
2020 
2021 /**
2022  * Object which temporarily resets a unit's movement.
2023  *
2024  * @warning A unit whose movement is reset may not be deleted while held in a
2025  * @ref unit_movement_resetter object, so it's best to use thus only in a small scope.
2026  */
2028 {
2031 
2032  unit_movement_resetter(const unit& u, bool operate = true);
2034 
2035 private:
2037  int moves_;
2038 };
2039 
2041 {
2042 /**
2043  * Optional parameter for get_checksum to use the algorithm of an older version of Wesnoth,
2044  * thus preventing spurious OOS warnings while watching old replays.
2045  */
2047  current,
2048  version_1_16_or_older /**< Included some of the flavortext from weapon specials. */
2049 };
2050 
2051 } // namespace backwards_compatibility
2052 
2053 /**
2054  * Gets a checksum for a unit.
2055  *
2056  * In MP games the descriptions are locally generated and might differ, so it
2057  * should be possible to discard them. Not sure whether replays suffer the
2058  * same problem.
2059  *
2060  * @param u this unit
2061  * @param version allows the checksum expected in older replays to be used
2062  *
2063  * @returns the checksum for a unit
2064  */
2065 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:45
int jamming_cost(const t_translation::terrain_code &terrain, bool slowed=false) const
Returns the cost to "jam" through the indicated terrain.
Definition: movetype.hpp:287
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:284
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:281
utils::string_map_res damage_table() const
Returns a map from attack types to resistances.
Definition: movetype.hpp:301
bool is_flying() const
Returns whether or not *this is flagged as a flying movement type.
Definition: movetype.hpp:276
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:1194
Visitor helper class to fetch the appropriate upkeep value.
Definition: unit.hpp:1144
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:695
void set_attr_changed(UNIT_ATTRIBUTE attr)
Definition: unit.hpp:185
virtual ~unit()
Definition: unit.cpp:729
bool get_attr_changed(UNIT_ATTRIBUTE attr) const
Definition: unit.hpp:192
void clear_changed_attributes()
Definition: unit.cpp:2808
void init(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Definition: unit.cpp:398
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:1058
bool get_attacks_changed() const
Definition: unit.cpp:1550
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:1897
unit_ability_list get_abilities(const std::string &tag_name) const
Gets the unit's active abilities of a particular type.
Definition: unit.hpp:1724
int movement_
Definition: unit.hpp:1920
void generate_name()
Generates a random race-appropriate name if one has not already been provided.
Definition: unit.cpp:747
std::vector< t_string > trait_names_
Definition: unit.hpp:1958
bool get_self_ability_bool_weapon(const config &special, const std::string &tag_name, const map_location &loc, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
Checks whether this unit currently possesses a given ability of leadership type.
Definition: abilities.cpp:1512
int unit_value_
Definition: unit.hpp:1961
int attacks_left_
Definition: unit.hpp:1931
bool generate_name_
Definition: unit.hpp:1989
void clear_visibility_cache() const
Clears the cache.
Definition: unit.hpp:2015
bool get_adj_ability_bool_weapon(const config &special, const std::string &tag_name, int dir, const map_location &loc, const unit &from, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
Checks whether this unit is affected by a given ability of leadership type.
Definition: abilities.cpp:1517
movetype movement_type_
Definition: unit.hpp:1925
config variables_
Definition: unit.hpp:1941
bool unrenamable_
Definition: unit.hpp:1912
int experience_
Definition: unit.hpp:1899
int vision_
Definition: unit.hpp:1922
void remove_ability_by_attribute(const config &filter)
Removes a unit's abilities with a specific ID or other attribute.
Definition: unit.cpp:1537
std::string undead_variation_
Definition: unit.hpp:1894
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:1885
map_location interrupted_move_
Definition: unit.hpp:1962
std::optional< std::string > ellipse_
Definition: unit.hpp:1986
map_location::DIRECTION facing_
Definition: unit.hpp:1955
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:1988
void write(config &cfg, bool write_all=true) const
Serializes the current unit metadata values.
Definition: unit.cpp:1560
std::bitset< UA_COUNT > changed_attributes_
Definition: unit.hpp:1998
std::string small_profile_
Definition: unit.hpp:1994
void write_upkeep(config::attribute_value &upkeep) const
Definition: unit.cpp:2803
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:1890
std::vector< t_string > special_notes_
Definition: unit.hpp:1982
bool canrecruit_
Definition: unit.hpp:1905
std::string image_mods_
Definition: unit.hpp:1910
double hp_bar_scaling_
Definition: unit.hpp:1974
std::string flag_rgb_
Definition: unit.hpp:1909
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:1939
@ 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:1871
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:1942
bool hidden_
Definition: unit.hpp:1973
bool is_healthy_
Definition: unit.hpp:1964
bool is_fearless_
Definition: unit.hpp:1964
config abilities_
Definition: unit.hpp:1977
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:1882
std::bitset< num_bool_states > known_boolean_states_
Definition: unit.hpp:1938
int side_
Definition: unit.hpp:1914
const unit_race * race_
Never nullptr, but may point to the null race.
Definition: unit.hpp:1888
bool appearance_changed_
Definition: unit.hpp:1997
int operator()(const upkeep_loyal &) const
Loyal units cost no upkeep.
Definition: unit.hpp:1155
double xp_bar_scaling_
Definition: unit.hpp:1974
bool appearance_changed() const
Definition: unit.hpp:1872
unit_alignments::type alignment_
Definition: unit.hpp:1907
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:1669
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:2572
bool is_visible_to_team(const team &team, bool const see_all=true) const
Definition: unit.cpp:2615
std::enable_if_t<!std::is_same_v< int, T >, std::string > operator()(T &) const
Definition: unit.hpp:1177
n_unit::unit_id underlying_id_
Definition: unit.hpp:1892
std::string variation_
Definition: unit.hpp:1895
unit & mark_clone(bool is_temporary)
Mark this unit as clone so it can be inserted to unit_map.
Definition: unit.cpp:2673
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:1207
static const std::size_t num_bool_states
Definition: unit.hpp:1936
config filter_recall_
Definition: unit.hpp:1943
int max_experience_
Definition: unit.hpp:1900
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:1506
unit_race::GENDER gender_
Definition: unit.hpp:1916
int operator()(int v) const
Definition: unit.hpp:1160
t_string description_
Definition: unit.hpp:1981
int level_
Definition: unit.hpp:1902
std::string role_
Definition: unit.hpp:1949
std::map< map_location, bool > invisibility_cache_
Hold the visibility status cache for a unit, when not uncovered.
Definition: unit.hpp:2007
upkeep_t operator()(const std::string &s) const
Definition: unit.hpp:1217
bool end_turn_
Definition: unit.hpp:1928
std::vector< std::string > advances_to_
Definition: unit.hpp:1879
std::unique_ptr< unit_animation_component > anim_comp_
Definition: unit.hpp:1971
std::enable_if_t< std::is_arithmetic_v< N >, upkeep_t > operator()(N n) const
Definition: unit.hpp:1198
int recall_cost_
Definition: unit.hpp:1904
static std::string type()
Definition: unit.hpp:1134
const std::set< std::string > checking_tags_
Definition: unit.hpp:1804
attack_list attacks_
Definition: unit.hpp:1950
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:1731
void remove_ability_by_id(const std::string &ability)
Removes a unit's abilities with a specific ID.
Definition: unit.cpp:1414
map_location loc_
Definition: unit.hpp:1877
static std::string type()
Definition: unit.hpp:1129
std::vector< std::string > overlays_
Definition: unit.hpp:1947
unit_formula_manager & formula_manager() const
Get the unit formula manager.
Definition: unit.hpp:1840
config modifications_
Definition: unit.hpp:1976
bool has_ability_by_id(const std::string &ability) const
Check if the unit has an ability of a specific ID.
Definition: unit.cpp:1403
bool hold_position_
Definition: unit.hpp:1927
const config & abilities() const
Definition: unit.hpp:1736
upkeep_value_visitor(const unit &unit)
Definition: unit.hpp:1146
std::string operator()(int v) const
Definition: unit.hpp:1183
void parse_upkeep(const config::attribute_value &upkeep)
Definition: unit.cpp:2789
std::vector< std::string > recruit_list_
Definition: unit.hpp:1906
const std::set< std::string > & checking_tags() const
Definition: unit.hpp:1738
std::vector< config > advancements_
Definition: unit.hpp:1979
utils::string_map modification_descriptions_
Definition: unit.hpp:1966
upkeep_t operator()(utils::monostate) const
Definition: unit.hpp:1212
bool get_self_ability_bool(const config &special, const std::string &tag_name, const map_location &loc) const
Checks whether this unit currently possesses a given ability used like weapon.
Definition: abilities.cpp:1501
unit_checksum_version
Optional parameter for get_checksum to use the algorithm of an older version of Wesnoth,...
Definition: unit.hpp:2046
upkeep_t upkeep_
Definition: unit.hpp:1991
int operator()(const upkeep_full &) const
Full upkeep equals the unit's level.
Definition: unit.hpp:1149
std::set< std::string > states_
Definition: unit.hpp:1934
std::string profile_
Definition: unit.hpp:1993
int jamming_
Definition: unit.hpp:1923
std::optional< std::string > halo_
Definition: unit.hpp:1985
map_location goto_
Definition: unit.hpp:1962
t_string name_
Definition: unit.hpp:1891
int max_attacks_
Definition: unit.hpp:1932
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:1513
int max_hit_points_
Definition: unit.hpp:1898
std::unique_ptr< unit_formula_manager > formula_man_
Definition: unit.hpp:1918
int max_movement_
Definition: unit.hpp:1921
bool resting_
Definition: unit.hpp:1929
std::vector< t_string > trait_descriptions_
Definition: unit.hpp:1959
bool emit_zoc_
Definition: unit.hpp:1945
unit_movement_resetter & operator=(const unit_movement_resetter &)=delete
std::optional< std::string > usage_
Definition: unit.hpp:1984
@ version_1_16_or_older
Included some of the flavortext from weapon specials.
void set_big_profile(const std::string &value)
Definition: unit.cpp:1954
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:1298
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:1380
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:1259
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:1036
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:1359
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:2769
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:1331
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:1045
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:1949
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:1314
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:1283
void end_turn()
Refresh unit for the end of a turn.
Definition: unit.cpp:1269
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:2656
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:1172
std::vector< t_string > unit_special_notes() const
The unit's special notes.
Definition: unit.cpp:2816
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:1878
std::vector< std::pair< std::string, std::string > > amla_icons() const
Gets the image and description data for modification advancements.
Definition: unit.cpp:1861
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:1943
void set_advances_to(const std::vector< std::string > &advances_to)
Sets this unit's advancement options.
Definition: unit.cpp:1193
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:1821
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:1178
void advance_to(const unit_type &t, bool use_traits=false)
Advances this unit to another type.
Definition: unit.cpp:909
void remove_attacks_ai()
Set the unit to have no attacks left for this turn.
Definition: unit.cpp:2751
attack_ptr add_attack(attack_itors::iterator position, Args &&... args)
Adds a new attack to the unit.
Definition: unit.hpp:944
bool resistance_filter_matches(const config &cfg, bool attacker, const std::string &damage_name, int res) const
Definition: unit.cpp:1764
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:1043
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:1749
bool remove_attack(attack_ptr atk)
Remove an attack from the unit.
Definition: unit.cpp:2740
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:1049
int max_attacks() const
The maximum number of attacks this unit may perform per turn, usually 1.
Definition: unit.hpp:978
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:1792
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:1564
color_t xp_color() const
Color for this unit's XP.
Definition: unit.cpp:1160
unit_animation_component & anim_comp() const
Definition: unit.hpp:1544
const std::string & effect_image_mods() const
Gets any IPF image mods applied by effects.
Definition: unit.hpp:1594
color_t hp_color() const
Color for this unit's current hitpoints.
Definition: unit.cpp:1106
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:2725
const std::vector< std::string > overlays_abilities() const
Get the [overlay] ability overlay images.
Definition: unit.hpp:1613
static color_t hp_color_max()
Definition: unit.cpp:1116
const std::string & flag_rgb() const
Get the source color palette to use when recoloring the unit's image.
Definition: unit.cpp:1063
std::string image_ellipse() const
Get the unit's ellipse image.
Definition: unit.hpp:1573
std::string image_mods() const
Gets an IPF string containing all IPF image mods.
Definition: unit.cpp:2730
std::string default_anim_image() const
The default image to use for animation frames with no defined image.
Definition: unit.cpp:2554
std::string image_halo() const
Get the unit's halo image.
Definition: unit.hpp:1556
const std::vector< std::string > & overlays() const
Get the unit's overlay images.
Definition: unit.hpp:1607
std::string absolute_image() const
The name of the file to game_display (used in menus).
Definition: unit.cpp:2549
void set_image_ellipse(const std::string &ellipse)
Set the unit's ellipse image.
Definition: unit.hpp:1579
void set_image_halo(const std::string &halo)
Set the unit's halo image.
Definition: unit.cpp:2782
void apply_builtin_effect(std::string type, const config &effect)
Apply a builtin effect to the unit.
Definition: unit.cpp:2052
void add_modification(const std::string &type, const config &modification, bool no_add=false)
Add a new modification to the unit.
Definition: unit.cpp:2433
static const std::set< std::string > builtin_effects
Definition: unit.hpp:1517
const config & get_modifications() const
Set the raw modifications.
Definition: unit.hpp:1485
std::string describe_builtin_effect(std::string type, const config &effect)
Construct a string describing a built-in effect.
Definition: unit.cpp:1987
config & get_modifications()
Get the raw modifications.
Definition: unit.hpp:1479
void apply_modifications()
Re-apply all saved modifications.
Definition: unit.cpp:2559
void expire_modifications(const std::string &duration)
Clears those modifications whose duration has expired.
Definition: unit.cpp:1226
std::size_t modification_count(const std::string &type, const std::string &id) const
Count modifications of a particular type.
Definition: unit.cpp:1961
bool emits_zoc() const
Tests whether the unit has a zone-of-control, considering incapacitated.
Definition: unit.hpp:1338
bool get_emit_zoc() const
Gets the raw zone-of-control flag, disregarding incapacitated.
Definition: unit.hpp:1344
int jamming() const
Gets the unit's jamming points.
Definition: unit.hpp:1406
bool has_goto() const
Gets whether this unit has a multi-turn destination set.
Definition: unit.hpp:1382
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1357
bool has_moved() const
Checks if this unit has moved.
Definition: unit.hpp:1312
void set_facing(map_location::DIRECTION dir) const
The this unit's facing.
Definition: unit.cpp:1725
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
Definition: unit.hpp:1440
const movetype & movement_type() const
Get the unit's movement type.
Definition: unit.hpp:1430
map_location::DIRECTION facing() const
The current direction this unit is facing within its hex.
Definition: unit.hpp:1373
void set_movement(int moves, bool unit_action=false)
Set this unit's remaining movement to moves.
Definition: unit.cpp:1200
const map_location & get_interrupted_move() const
Get the target location of the unit's interrupted move.
Definition: unit.hpp:1418
int vision_cost(const t_translation::terrain_code &terrain) const
Get the unit's vision cost on a particular terrain.
Definition: unit.hpp:1450
void set_resting(bool rest)
Sets this unit's resting status.
Definition: unit.hpp:1332
void set_total_movement(int value)
Definition: unit.hpp:1271
void set_emit_zoc(bool val)
Sets the raw zone-of-control flag.
Definition: unit.hpp:1350
void set_goto(const map_location &new_goto)
Sets this unit's long term destination.
Definition: unit.hpp:1394
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition: unit.hpp:1282
int movement_left(bool base_value) const
Gets how far a unit can move.
Definition: unit.hpp:1294
int total_movement() const
The maximum moves this unit has.
Definition: unit.hpp:1266
int jamming_cost(const t_translation::terrain_code &terrain) const
Get the unit's jamming cost on a particular terrain.
Definition: unit.hpp:1460
void set_location(const map_location &loc)
Sets this unit's map location.
Definition: unit.hpp:1367
void remove_movement_ai()
Sets the unit to have no moves left for this turn.
Definition: unit.cpp:2760
bool move_interrupted() const
Check whether the unit's move has been interrupted.
Definition: unit.hpp:1412
int vision() const
Gets the unit's vision points.
Definition: unit.hpp:1400
const map_location & get_goto() const
The map location to which this unit is moving over multiple turns, if any.
Definition: unit.hpp:1388
bool resting() const
Checks whether this unit is 'resting'.
Definition: unit.hpp:1326
void set_interrupted_move(const map_location &interrupted_move)
Set the target location of the unit's interrupted move.
Definition: unit.hpp:1424
bool is_flying() const
Check if the unit is a flying unit.
Definition: unit.hpp:1466
int upkeep() const
Gets the amount of gold this unit costs a side per turn.
Definition: unit.cpp:1734
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:2536
bool is_healthy() const
Gets whether this unit is healthy - ie, always rest heals.
Definition: unit.hpp:1253
bool is_fearless() const
Gets whether this unit is fearless - ie, unaffected by time of day.
Definition: unit.hpp:1247
std::vector< std::string > get_traits_list() const
Gets a list of the traits this unit currently has.
Definition: unit.cpp:889
utils::variant< upkeep_full, upkeep_loyal, int > upkeep_t
Definition: unit.hpp:1137
const std::vector< t_string > & trait_descriptions() const
Gets the descriptions of the currently registered traits.
Definition: unit.hpp:1093
const std::vector< t_string > & trait_names() const
Gets the names of the currently registered traits.
Definition: unit.hpp:1083
void generate_traits(bool must_have_only=false)
Applies mandatory traits (e.g.
Definition: unit.cpp:756
upkeep_t upkeep_raw() const
Gets the raw variant controlling the upkeep value.
Definition: unit.hpp:1232
bool loyal() const
Gets whether this unit is loyal - ie, it costs no upkeep.
Definition: unit.cpp:1744
void set_upkeep(upkeep_t v)
Sets the upkeep value to a specific value value.
Definition: unit.hpp:1238
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:1174
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:2028
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:2822
MacOS doesn't support std::visit when targing MacOS < 10.14 (currently we target 10....
#define b