The Battle for Wesnoth  1.17.0-dev
race.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2021
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 /**
17  * @file
18  * Generate race-specific unit-names.
19  */
20 
21 #include "units/race.hpp"
22 
23 #include "filesystem.hpp"
24 #include "log.hpp"
27 #include "utils/name_generator.hpp"
29 
30 static lg::log_domain log_wml("wml");
31 #define ERR_WML LOG_STREAM(err, log_wml)
32 
33 /** Dummy race used when a race is not yet known. */
35 /** Standard string id (not translatable) for FEMALE */
36 const std::string unit_race::s_female("female");
37 /** Standard string id (not translatable) for MALE */
38 const std::string unit_race::s_male("male");
39 
40 
41 static const config &empty_traits() {
42  static config cfg;
43  return cfg;
44 }
45 
46 static const config &empty_topics() {
47  static config cfg;
48  return cfg;
49 }
50 
52  cfg_(),
53  id_(),
54  name_(),
55  plural_name_(),
56  description_(),
57  ntraits_(0),
58  traits_(empty_traits().child_range("trait")),
59  topics_(empty_topics().child_range("topic")),
60  global_traits_(true),
61  undead_variation_(),
62  help_taxonomy_()
63 {
64  for(auto& generator : name_generator_) {
65  generator.reset(new name_generator());
66  }
67 }
68 
70  cfg_(cfg),
71  id_(cfg["id"]),
72  icon_(cfg["editor_icon"]),
73  plural_name_(cfg["plural_name"].t_str()),
74  description_(cfg["description"].t_str()),
75  ntraits_(cfg["num_traits"]),
76  traits_(cfg.child_range("trait")),
77  topics_(cfg.child_range("topic")),
78  global_traits_(!cfg["ignore_global_traits"].to_bool()),
79  undead_variation_(cfg["undead_variation"]),
80  help_taxonomy_(cfg["help_taxonomy"])
81 
82 {
83  if (plural_name_.empty()) {
84  lg::log_to_chat() << "[race] id='" << id_ << "' is missing a plural_name field.\n";
85  ERR_WML << "[race] id='" << id_ << "' is missing a plural_name field.\n";
86  plural_name_ = (cfg["name"]);
87  }
88 
89  // use "name" if "male_name" or "female_name" aren't available
90  name_[MALE] = cfg["male_name"];
91  if(name_[MALE].empty()) {
92  name_[MALE] = (cfg["name"]);
93  }
94  name_[FEMALE] = cfg["female_name"];
95  if(name_[FEMALE].empty()) {
96  name_[FEMALE] = (cfg["name"]);
97  }
98  if(std::any_of(name_.begin(), name_.end(), [](const auto& n) { return n.empty(); })) {
100  << "[race] id='" << id_
101  << "' is missing a singular name field (either 'name' or both 'male_name' and 'female_name').\n";
102  ERR_WML << "[race] id'" << id_
103  << "' is missing a singular name field (either 'name' or both 'male_name' and 'female_name').\n";
104  }
105 
106  name_generator_factory generator_factory = name_generator_factory(cfg, {"male", "female"});
107 
108  for(int i=MALE; i<NUM_GENDERS; i++) {
109  GENDER gender = static_cast<GENDER>(i);
110  name_generator_[i] = generator_factory.get_name_generator(gender_string(gender));
111  }
112 }
113 
115 {
116  return name_generator_[gender]->generate();
117 }
118 
120 {
121  return *name_generator_[gender];
122 }
123 
125 {
126  return global_traits_;
127 }
128 
130 {
131  return traits_;
132 }
133 
135 {
136  return topics_;
137 }
138 
139 unsigned int unit_race::num_traits() const { return ntraits_; }
140 
141 
142 const std::string& gender_string(unit_race::GENDER gender) {
143  switch(gender) {
144  case unit_race::FEMALE:
145  return unit_race::s_female;
146  default:
147  case unit_race::MALE:
148  return unit_race::s_male;
149  }
150 }
151 
152 unit_race::GENDER string_gender(const std::string& str, unit_race::GENDER def) {
153  if ( str == unit_race::s_male ) {
154  return unit_race::MALE;
155  } else if ( str == unit_race::s_female ) {
156  return unit_race::FEMALE;
157  }
158  return def;
159 }
160 
161 std::string unit_race::get_icon_path_stem() const
162 {
163  if(!icon_.empty()) {
164  return icon_;
165  }
166 
167  std::string path = "icons/unit-groups/race_" + id_;
168 
169  // FIXME: hardcoded '30' is bad...
170  if(!filesystem::file_exists(filesystem::get_binary_file_location("images", path + "_30.png"))) {
171  path = "icons/unit-groups/race_custom";
172  }
173 
174  return path;
175 }
static const config & empty_traits()
Definition: race.cpp:41
static const std::string s_male
Standard string id (not translatable) for MALE.
Definition: race.hpp:29
std::array< std::shared_ptr< name_generator >, NUM_GENDERS > name_generator_
Definition: race.hpp:83
unsigned int ntraits_
Definition: race.hpp:82
static lg::log_domain log_wml("wml")
std::string undead_variation_
Definition: race.hpp:88
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:263
const config::const_child_itors & additional_topics() const
Definition: race.cpp:134
const name_generator & generator(GENDER gender) const
Definition: race.cpp:119
std::string get_binary_file_location(const std::string &type, const std::string &filename)
Returns a complete path to the actual file of a given type or an empty string if the file isn&#39;t prese...
std::shared_ptr< name_generator > get_name_generator()
Gets the default name generator.
static const std::string s_female
Standard string id (not translatable) for FEMALE.
Definition: race.hpp:28
static const unit_race null_race
Dummy race used when a race is not yet known.
Definition: race.hpp:69
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
Definition: race.cpp:152
std::array< t_string, NUM_GENDERS > name_
Definition: race.hpp:79
std::string path
Definition: game_config.cpp:39
t_string description_
Definition: race.hpp:81
const config::const_child_itors & additional_traits() const
Definition: race.cpp:129
unsigned int num_traits() const
Definition: race.cpp:139
const std::string & gender_string(unit_race::GENDER gender)
Definition: race.cpp:142
t_string description_
boost::iterator_range< const_child_iterator > const_child_itors
Definition: config.hpp:206
config::const_child_itors topics_
Definition: race.hpp:86
std::size_t i
Definition: function.cpp:967
std::string id_
Definition: race.hpp:77
std::string icon_
Definition: race.hpp:78
static const config & empty_topics()
Definition: race.cpp:46
bool uses_global_traits() const
Definition: race.cpp:124
const config cfg_
Definition: race.hpp:75
Declarations for File-IO.
std::string id_
bool empty() const
Definition: tstring.hpp:187
t_string plural_name_
Definition: race.hpp:80
unit_race()
Only used to construct null_race.
Definition: race.cpp:51
std::string help_taxonomy_
Definition: race.hpp:89
Standard logging facilities (interface).
config::const_child_itors traits_
Definition: race.hpp:85
std::string get_icon_path_stem() const
Gets this race&#39;s icon path without state/size suffix and extension.
Definition: race.cpp:161
bool global_traits_
Definition: race.hpp:87
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
#define ERR_WML
Definition: race.cpp:31
static map_location::DIRECTION n
std::string generate_name(GENDER gender) const
Definition: race.cpp:114
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
Definition: log.cpp:289