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