23 #include "formula/callable_objects.hpp"
35 #include <boost/range/algorithm_ext/erase.hpp>
41 #define ERR_CF LOG_STREAM(err, log_config)
42 #define WRN_CF LOG_STREAM(warn, log_config)
43 #define LOG_CONFIG LOG_STREAM(info, log_config)
44 #define DBG_CF LOG_STREAM(debug, log_config)
47 #define DBG_UT LOG_STREAM(debug, log_unit)
48 #define LOG_UT LOG_STREAM(info, log_unit)
49 #define ERR_UT LOG_STREAM(err, log_unit)
56 , debug_id_(o.debug_id_)
57 , parent_id_(o.parent_id_)
58 , base_unit_id_(o.base_unit_id_)
59 , type_name_(o.type_name_)
60 , description_(o.description_)
61 , hitpoints_(o.hitpoints_)
62 , hp_bar_scaling_(o.hp_bar_scaling_)
63 , xp_bar_scaling_(o.xp_bar_scaling_)
65 , recall_cost_(o.recall_cost_)
66 , movement_(o.movement_)
68 , jamming_(o.jamming_)
69 , max_attacks_(o.max_attacks_)
72 , undead_variation_(o.undead_variation_)
75 , small_profile_(o.small_profile_)
76 , profile_(o.profile_)
77 , flag_rgb_(o.flag_rgb_)
78 , num_traits_(o.num_traits_)
79 , variations_(o.variations_)
80 , default_variation_(o.default_variation_)
81 , variation_name_(o.variation_name_)
83 , abilities_(o.abilities_)
84 , adv_abilities_(o.adv_abilities_)
86 , hide_help_(o.hide_help_)
87 , do_not_list_(o.do_not_list_)
88 , advances_to_(o.advances_to_)
89 , advancements_(o.advancements_)
90 , experience_needed_(o.experience_needed_)
91 , alignment_(o.alignment_)
92 , movement_type_(o.movement_type_)
93 , possible_traits_(o.possible_traits_)
94 , genders_(o.genders_)
95 , animations_(o.animations_)
96 , build_status_(o.build_status_)
106 , id_(cfg.has_attribute(
"id") ? cfg[
"id"].str() : parent_id)
108 , parent_id_(!parent_id.empty() ? parent_id : id_)
113 , hp_bar_scaling_(0.0)
114 , xp_bar_scaling_(0.0)
123 , undead_variation_()
132 , default_variation_()
141 , advancements_(cfg.child_range(
"advancement"))
142 , experience_needed_(0)
148 , build_status_(NOT_BUILT)
167 built_cfg_ = std::make_unique<config>(std::move(cfg));
177 , name(cfg[
"name"].t_str())
178 , name_inactive(cfg[
"name_inactive"].t_str())
179 , female_name(cfg[
"female_name"].t_str())
180 , female_name_inactive(cfg[
"female_name_inactive"].t_str())
181 , description(cfg[
"description"].t_str())
182 , description_inactive(cfg[
"description_inactive"].t_str())
183 , affect_self(cfg[
"affect_self"].to_bool())
184 , affect_allies(cfg[
"affect_allies"].to_bool())
185 , affect_enemies(cfg[
"affect_enemies"].to_bool())
186 , cumulative(cfg[
"cumulative"].to_bool())
204 for(
int i = 0;
i < 2; ++
i) {
224 for(variations_map::value_type& variation :
variations_) {
225 variation.second.build_full(mv_types, races, traits);
252 level_ = cfg[
"level"].to_int();
255 vision_ = cfg[
"vision"].to_int(-1);
256 jamming_ = cfg[
"jamming"].to_int(0);
258 usage_ = cfg[
"usage"].str();
261 icon_ = cfg[
"image_icon"].str();
275 for(
int i = 0;
i < 2; ++
i) {
282 pair.second.build_help_index(mv_types, races, traits);
285 const race_map::const_iterator race_it = races.find(cfg[
"race"]);
286 if(race_it != races.end()) {
287 race_ = &race_it->second;
305 for(
const auto [key, cfg] : abil_cfg->all_children_view()) {
312 auto abil_cfg = effect.optional_child(
"abilities");
314 if(!abil_cfg || effect[
"apply_to"] !=
"new_ability") {
318 for(
const auto [key, cfg] : abil_cfg->all_children_view()) {
325 const std::string move_type = cfg[
"movement_type"];
327 const movement_type_map::const_iterator find_it = mv_types.find(move_type);
329 if(find_it != mv_types.end()) {
330 DBG_UT <<
"inheriting from movement_type '" << move_type <<
"'";
332 }
else if(!move_type.empty()) {
333 DBG_UT <<
"movement_type '" << move_type <<
"' not found";
339 for(
const config&
t : traits) {
348 if(cfg[
"ignore_race_traits"].to_bool()) {
352 if(
alignment_ != unit_alignments::type::neutral ||
t[
"id"] !=
"fearless")
392 pair.second.build_created();
398 const std::string& advances_to_val = cfg[
"advances_to"];
399 if(advances_to_val !=
"null" && !advances_to_val.empty()) {
407 DBG_UT <<
"unit_type '" <<
log_id() <<
"' advances to : " << advances_to_val;
410 cost_ = cfg[
"cost"].to_int(1);
413 image_ = cfg[
"image"].str();
425 DBG_UT <<
"Building unit type " <<
log_id() <<
", level " << status;
448 ERR_UT <<
"Build of unit_type to unrecognized status (" << status <<
") requested.";
468 const std::size_t
i = gender;
478 const variations_map::const_iterator
i =
variations_.find(
id);
489 return (
_(
"No description available."));
500 if(new_note.
empty())
return;
501 std::string_view note_plain = new_note.
c_str();
503 if(note_plain.empty())
return;
504 auto iter = std::find(notes.begin(), notes.end(), new_note);
505 if(iter != notes.end())
return;
506 notes.push_back(new_note);
511 std::vector<t_string> notes;
512 for(
const auto& note : direct) {
516 if(cfg.has_attribute(
"special_note")) {
520 for(
const auto& attack :
attacks) {
521 for(
const auto [key, cfg] : attack.specials().all_children_view()) {
522 if(cfg.has_attribute(
"special_note")) {
560 int experience_modifier = 100;
564 : old_value_(experience_modifier)
566 experience_modifier = modifier;
576 return experience_modifier;
581 if(with_acceleration) {
595 if(
auto abil =
get_cfg().optional_child(
"abilities")) {
596 for(
const auto [key, cfg] : abil->all_children_view()) {
597 if(cfg[
"id"] == ability) {
608 std::vector<std::string> res;
615 for(
const auto [key, cfg] : abilities->all_children_view()) {
616 std::string
id = cfg[
"id"];
619 res.push_back(std::move(
id));
640 if(tree.insert(adv).second) {
649 std::set<std::string> tree;
659 std::vector<std::string> adv_from;
660 for(
const unit_type_data::unit_type_map::value_type& ut :
unit_types.
types()) {
661 for(
const std::string& adv : ut.second.advances_to()) {
663 adv_from.push_back(ut.second.id());
677 bool current_status =
false;
684 if(mod[
"availability"] !=
"musthave") {
694 const std::string& ut = effect[
"unit_type"];
697 const std::vector<std::string>& types =
utils::split(ut);
699 if(std::find(types.begin(), types.end(),
id()) == types.end()) {
705 if(effect[
"apply_to"] !=
"status") {
709 if(effect[
"add"] == status_name) {
710 current_status =
true;
713 if(effect[
"remove"] == status_name) {
714 current_status =
false;
719 return current_status;
735 if(availability.
blank()) {
739 if(availability.
str() !=
"musthave") {
749 std::vector<std::string>
retval;
752 for(
const variations_map::value_type& val :
variations_) {
753 retval.push_back(val.first);
766 for(
const variations_map::value_type& val :
variations_) {
767 if(!val.second.hide_help()) {
780 if(
auto abilities =
get_cfg().optional_child(
"abilities")) {
782 if(!cfg[
"affect_self"].to_bool(
true)) {
794 if(!resistance_abilities.
empty()) {
797 resistance = 100 - std::min<int>(
799 resistance_abilities.
highest(
"max_value").first
807 const config& cfg,
bool attacker,
const std::string& damage_name,
int res)
const
809 if(!(cfg[
"active_on"].empty() ||
810 (attacker && cfg[
"active_on"] ==
"offense") ||
811 (!attacker && cfg[
"active_on"] ==
"defense"))
816 const std::string& apply_to = cfg[
"apply_to"];
818 if(!apply_to.empty()) {
819 if(damage_name != apply_to) {
820 if(apply_to.find(
',') != std::string::npos && apply_to.find(damage_name) != std::string::npos) {
821 const std::vector<std::string>& vals =
utils::split(apply_to);
823 if(std::find(vals.begin(), vals.end(), damage_name) == vals.end()) {
846 case unit_alignments::type::lawful:
847 return _(
"female^lawful");
848 case unit_alignments::type::neutral:
849 return _(
"female^neutral");
850 case unit_alignments::type::chaotic:
851 return _(
"female^chaotic");
852 case unit_alignments::type::liminal:
853 return _(
"female^liminal");
855 return _(
"female^lawful");
860 case unit_alignments::type::lawful:
862 case unit_alignments::type::neutral:
864 case unit_alignments::type::chaotic:
866 case unit_alignments::type::liminal:
880 , hide_help_all_(false)
898 void throw_base_unit_recursion_error(
const std::vector<std::string>& base_tree,
const std::string& base_id)
900 std::stringstream ss;
901 ss <<
"[base_unit] recursion loop in [unit_type] ";
903 for(
const std::string& step : base_tree) {
918 const std::string& type_to_patch,
919 const std::string& new_key,
920 const std::string& formula_str,
924 LOG_CONFIG <<
"Patching " << new_key <<
" into movetype." << type_to_patch;
926 mt.
write(mt_cfg,
false);
944 std::list<config> config_copies;
951 const std::array fallback_children {
"movement_costs",
"vision_costs",
"jamming_costs"};
953 for(
const auto& x : fallback_children) {
957 config_copies.emplace_back(cumulative_values);
958 auto val = std::make_shared<wfl::config_callable>(config_copies.back());
959 original.
add(x, val);
962 if(type_to_patch == x) {
968 const std::array child_names {
"defense",
"resistance"};
969 for(
const auto& x : child_names) {
972 auto val = std::make_shared<wfl::config_callable>(subtag);
973 original.
add(x, val);
976 if(type_to_patch == x) {
982 LOG_CONFIG <<
" formula=" << formula_str <<
", resolves to " << formula(original);
983 temp_cfg[new_key] = formula(original);
985 mt.
merge(temp_cfg, type_to_patch,
true);
998 if(
type.base_unit_id_.empty()) {
1003 if(std::find(base_tree.begin(), base_tree.end(),
type.base_unit_id_) != base_tree.end()) {
1004 throw_base_unit_recursion_error(base_tree,
type.base_unit_id_);
1009 if(itor !=
types_.end()) {
1014 base_tree.push_back(
type.base_unit_id_);
1018 base_tree.pop_back();
1021 type.writable_cfg().inherit_from(base_type.
get_cfg());
1024 ERR_CF <<
"[base_unit]: unit type not found: " <<
type.base_unit_id_;
1036 config var_copy = var_cfg;
1037 if(var_cfg[
"inherit"].to_bool(default_inherit)) {
1044 return std::make_unique<unit_type>(std::move(var_copy),
parent_id());
1054 if(!
get_cfg().has_child(
"variation")) {
1059 for(
const config& var_cfg :
get_cfg().child_range(
"variation")) {
1063 var->built_cfg_->remove_children(
"variation");
1064 var->variation_id_ = var_cfg[
"variation_id"].str();
1065 var->debug_id_ =
debug_id_ +
" [" + var->variation_id_ +
"]";
1069 std::tie(ut, success) =
variations_.emplace(var_cfg[
"variation_id"].str(), std::move(*var));
1071 ERR_CF <<
"Skipping duplicate unit variation ID: '" << var_cfg[
"variation_id"]
1072 <<
"' of unit_type '" <<
get_cfg()[
"id"] <<
"'";
1083 if(
auto male_cfg =
get_cfg().optional_child(
"male")) {
1088 if(
auto female_cfg =
get_cfg().optional_child(
"female")) {
1105 LOG_UT <<
"unit_type_data::set_config, nunits: " << cfg.
child_range(
"unit_type").size();
1124 DBG_CF <<
"Start of movetype patching";
1126 const std::string& dmg_type = r[
"id"];
1128 for(
const auto& [mt, value] : r.attribute_range()) {
1133 DBG_CF <<
"Patching specific movetype " << mt;
1134 patch_movetype(
movement_types_[mt],
"resistance", dmg_type, value, 100,
true);
1137 if(r.has_attribute(
"default")) {
1140 if(r.has_attribute(mt.first)) {
1144 if(mt.first ==
"none") {
1148 patch_movetype(mt.second,
"resistance", dmg_type, r[
"default"], 100,
false);
1152 DBG_CF <<
"Split between resistance and cost patching";
1156 const std::string& ter_type = terrain[
"id"];
1158 struct ter_defs_to_movetype
1166 const std::array terrain_info_tags{
1170 ter_defs_to_movetype{{
"defense"}, {
"defense"}, 100}
1173 for(
const auto& cost_type : terrain_info_tags) {
1174 const std::string* src_tag =
nullptr;
1175 if(terrain.has_child(cost_type.subtag)) {
1176 src_tag = &cost_type.subtag;
1178 else if(terrain.has_child(cost_type.alias)) {
1180 src_tag = &cost_type.alias;
1186 const config&
info = terrain.mandatory_child(*src_tag);
1188 for(
const auto& [mt, value] :
info.attribute_range()) {
1194 movement_types_[mt], cost_type.subtag, ter_type, value, cost_type.default_val,
true);
1197 if(
info.has_attribute(
"default")) {
1200 if(
info.has_attribute(mt.first)) {
1204 if(mt.first ==
"none") {
1209 mt.second, cost_type.subtag, ter_type,
info[
"default"], cost_type.default_val,
false);
1214 DBG_CF <<
"End of movetype patching";
1218 std::string
id = ut[
"id"].str();
1220 ERR_CF <<
"[unit_type] with empty id=, ignoring:\n" << ut.debug();
1225 LOG_CONFIG <<
"added " <<
id <<
" to unit_type list (unit_type_data.unit_types)";
1227 ERR_CF <<
"Multiple [unit_type]s with id=" <<
id <<
" encountered.";
1233 std::vector<std::string> base_tree(1,
type.second.id());
1241 type.second.fill_variations_and_gender();
1254 DBG_UT <<
"Finished creating unit types";
1267 if(key.empty() || key ==
"random") {
1271 DBG_CF <<
"trying to find " << key <<
" in unit_type list (unit_type_data.unit_types)";
1275 if(itor ==
types_.end()) {
1276 DBG_CF <<
"unable to find " << key <<
" in unit_type list (unit_type_data.unit_types)";
1283 return &itor->second;
1334 std::vector<std::string> trees =
utils::split(cfg[
"type_adv_tree"]);
1337 for(
const std::string& t_id : trees) {
1341 std::set<std::string> adv_tree = ut->second.advancement_tree();
1360 for(; lvl < lvl_nb; ++lvl) {
1371 race_map::const_iterator
i =
races_.find(key);
1372 return i !=
races_.end() ? &
i->second :
nullptr;
1378 if(
auto p_setxp = cfg.
get(
"set_experience")) {
1381 if(
auto attr = cfg.
get(
"set_advances_to")) {
1384 if(
auto attr = cfg.
get(
"set_cost")) {
1385 cost_ = attr->to_int(1);
1387 if(
auto attr = cfg.
get(
"add_advancement")) {
1394 if(
auto attr = cfg.
get(
"remove_advancement")) {
1405 for(
int gender = 0; gender <= 1; ++gender) {
1410 std::string gender_str = gender == 0 ?
"male" :
"female";
1419 if(
get_cfg().has_child(
"variation")) {
1424 if(v.first == cv[
"variation_id"]){
1425 v.second.apply_scenario_fix(cv);
1436 if(itor !=
types_.end()) {
1437 itor->second.apply_scenario_fix(cfg);
1447 const std::string& advances_to_val =
get_cfg()[
"advances_to"];
1448 if(advances_to_val !=
"null" && !advances_to_val.empty()) {
1455 for(
int gender = 0; gender <= 1; ++gender) {
1462 v.second.remove_scenario_fixes();
1469 for(
auto& pair :
types_) {
1470 pair.second.remove_scenario_fixes();
1476 assert(!
id.empty());
1480 throw error(
"Found unit type id with a leading whitespace \"" +
id +
"\"");
1483 bool gave_warning =
false;
1485 for(std::size_t pos = 0; pos <
id.size(); ++pos) {
1486 const char c =
id[pos];
1487 const bool valid = std::isalnum(
c, std::locale::classic()) ||
c ==
'_' ||
c ==
' ';
1491 ERR_UT <<
"Found unit type id with invalid characters: \"" <<
id <<
"\"";
1492 gave_warning =
true;
1505 std::string temp = profile;
1507 static const std::string path_adjust =
"/transparent";
1508 const std::string::size_type offset = profile.find_last_of(
'/', profile.find(
'~'));
1511 if(profile.find(path_adjust) != std::string::npos && offset != std::string::npos) {
1513 profile.replace(profile.find(path_adjust), path_adjust.length(),
"");
1520 offset != std::string::npos ? temp.insert(offset, path_adjust) : temp = path_adjust + temp;
boost::iterator_range< boost::indirect_iterator< attack_list::const_iterator > > const_attack_itors
attack_itors make_attack_itors(attack_list &atks)
Variant for storing WML attributes.
std::string str(const std::string &fallback="") const
bool blank() const
Tests for an attribute that was never set.
A config object defines a single node in a WML file, with access to child nodes.
const config & child_or_empty(config_key_type key) const
Returns the first child with the given key, or an empty config if there is none.
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
auto all_children_view() const
In-order iteration over all children.
void clear_children(T... keys)
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
bool has_attribute(config_key_type key) const
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
void inherit_from(const config &c)
Merge config 'c' into this config, preserving this config's values.
child_itors child_range(config_key_type key)
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
A class grating read only view to a vector of config objects, viewed as one config with all children ...
optional_const_config optional_child(config_key_type key) const
static game_config_view wrap(const config &cfg)
config_array_view child_range(config_key_type key) const
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
The basic "size" of the unit - flying, small land, large land, etc.
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
void write(config &cfg, bool include_notes) const
Writes the movement type data to the provided config.
void merge(const config &new_cfg, bool overwrite=true)
Merges the given config over the existing data, the config should have zero or more children named "m...
int resistance_against(const std::string &damage_type) const
Returns the vulnerability to the indicated damage type (higher means takes more damage).
const std::vector< t_string > & special_notes() const
Contents of any [special_note] tags.
const char * c_str() const
int get_composite_value() const
void emplace_back(T &&... args)
std::pair< int, map_location > highest(const std::string &key, int def=0) const
static void fill_initial_animations(std::vector< unit_animation > &animations, const config &cfg)
const std::string & id() const
bool uses_global_traits() const
static const unit_race null_race
Dummy race used when a race is not yet known.
const std::string & undead_variation() const
unsigned int num_traits() const
const config::const_child_itors & additional_traits() const
static const std::string s_female
Standard string id (not translatable) for FEMALE.
static const std::string s_male
Standard string id (not translatable) for MALE.
void set_config(const game_config_view &cfg)
Resets all data based on the provided config.
unit_type::BUILD_STATUS build_status_
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
bool hide_help(const std::string &type_id, const std::string &race_id) const
Checks if the [hide_help] tag contains these IDs.
void remove_scenario_fixes()
const race_map & races() const
bool hide_help_all_
True if [hide_help] contains a 'all=yes' at its root.
void build_all(unit_type::BUILD_STATUS status)
Makes sure the all unit_types are built to the specified level.
void apply_base_unit(unit_type &type, std::vector< std::string > &base_tree)
Modifies the provided config by merging all base units into it.
const unit_race * find_race(const std::string &) const
void check_types(const std::vector< std::string > &types) const
movement_type_map movement_types_
game_config_view units_cfg_
void build_unit_type(const unit_type &ut, unit_type::BUILD_STATUS status) const
Makes sure the provided unit_type is built to the specified level.
std::vector< std::set< std::string > > hide_help_type_
const game_config_view & units_cfg() const
const unit_type_map & types() const
void read_hide_help(const config &cfg)
Parses the [hide_help] tag.
void apply_scenario_fix(const config &cfg)
std::vector< std::set< std::string > > hide_help_race_
A single unit type that the player may recruit.
std::string default_variation_
std::vector< unit_animation > animations_
const std::vector< std::string > advances_from() const
A vector of unit_type ids that can advance to this unit_type.
unit_alignments::type alignment_
const std::string & parent_id() const
The id of the original type from which this (variation) descended.
config::const_child_itors advancements_
void fill_variations()
Processes [variation] tags of ut_cfg, handling inheritance and child clearing.
static std::string alignment_description(unit_alignments::type align, unit_race::GENDER gender=unit_race::MALE)
Implementation detail of unit_type::alignment_description.
std::vector< t_string > special_notes_
variations_map variations_
void build_full(const movement_type_map &movement_types, const race_map &races, const config_array_view &traits)
Load data into an empty unit_type (build to FULL).
const std::string & variation_id() const
The id of this variation; empty if it's a gender variation or a base unit.
const unit_race * race_
Never nullptr, but may point to the null race.
std::string parent_id_
The id of the top ancestor of this unit_type.
std::string undead_variation_
bool has_random_traits() const
std::string movement_type_id_
std::vector< ability_metadata > abilities_
void fill_variations_and_gender()
const movetype & movement_type() const
bool show_variations_in_help() const
Whether the unit type has at least one help-visible variation.
std::string debug_id_
A suffix for id_, used when logging messages.
std::array< std::unique_ptr< unit_type >, 2 > gender_types_
bool has_ability_by_id(const std::string &ability) const
std::string small_profile_
const unit_type & get_variation(const std::string &id) const
const_attack_itors attacks() const
const std::vector< std::string > & advances_to() const
A vector of unit_type ids that this unit_type can advance to.
void apply_scenario_fix(const config &cfg)
int resistance_against(const std::string &damage_name, bool attacker) const
Gets resistance while considering custom WML abilities.
bool has_variation(const std::string &variation_id) const
t_string unit_description() const
static void check_id(std::string &id)
Validate the id argument.
BUILD_STATUS
Records the status of the lazy building of unit types.
const std::vector< unit_animation > & animations() const
std::vector< std::string > variations() const
const std::string & flag_rgb() const
const config & abilities_cfg() const
std::vector< t_string > special_notes() const
Returns all notes that should be displayed in the help page for this type, including those found in a...
attack_list attacks_cache_
std::vector< std::string > advances_to_
std::string base_unit_id_
from [base_unit]
const std::string log_id() const
A variant on id() that is more descriptive, for use with message logging.
const unit_type & get_gender_unit_type(std::string gender) const
Returns a gendered variant of this unit_type.
std::vector< unit_race::GENDER > genders_
int experience_needed(bool with_acceleration=true) const
bool musthave_status(const std::string &status) const
void build(BUILD_STATUS status, const movement_type_map &movement_types, const race_map &races, const config_array_view &traits)
Performs a build of this to the indicated stage.
std::vector< std::string > get_ability_list() const
bool resistance_filter_matches(const config &cfg, bool attacker, const std::string &damage_name, int res) const
Identical to unit::resistance_filter_matches.
void remove_scenario_fixes()
std::unique_ptr< unit_type > create_sub_type(const config &var_cfg, bool default_inherit)
Handles inheritance for configs of [male], [female], and [variation].
void build_help_index(const movement_type_map &movement_types, const race_map &races, const config_array_view &traits)
Partially load data into an empty unit_type (build to HELP_INDEXED).
BUILD_STATUS build_status_
config::const_child_itors possible_traits() const
void build_created()
Load the most needed data into an empty unit_type (build to CREATE).
std::unique_ptr< config > built_cfg_
std::vector< ability_metadata > adv_abilities_
const config & get_cfg() const
unsigned int num_traits() const
std::set< std::string > advancement_tree() const
Get the advancement tree.
std::vector< std::reference_wrapper< const config > > config_array_view
static std::string _(const char *str)
std::string id
Text to match against addon_info.tags()
symbol_table string_table
Standard logging facilities (interface).
static void add_color_info(const game_config_view &v, bool build_defaults)
retval
Default window/dialog return values.
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
bool filter_base_matches(const config &cfg, int def)
void trim(std::string_view &s)
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
std::vector< std::string > split(const config_attribute_value &val)
std::string::const_iterator iterator
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
std::map< std::string, unit_race > race_map
Error used for any general game error, e.g.
static const map_location & null_location()
The base template for associating string values with enum values.
static constexpr utils::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
utils::string_map::const_iterator end() const
utils::string_map::const_iterator find(const std::string &key) const
Look up the string mappings given in [language] tags.
~unit_experience_accelerator()
unit_experience_accelerator(int modifier)
static int get_acceleration()
static lg::log_domain log_unit("unit")
unit_type_data unit_types
std::vector< t_string > combine_special_notes(const std::vector< t_string > direct, const config &abilities, const_attack_itors attacks, const movetype &mt)
Common logic for unit_type::special_notes() and unit::special_notes().
static void advancement_tree_internal(const std::string &id, std::set< std::string > &tree)
void adjust_profile(std::string &profile)
static void append_special_note(std::vector< t_string > ¬es, const t_string &new_note)
static lg::log_domain log_config("config")
std::map< std::string, movetype > movement_type_map