1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name deity.cpp - The deity source file. */
12 //
13 // (c) Copyright 2018-2019 by Andrettin
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 /*----------------------------------------------------------------------------
31 -- Includes
32 ----------------------------------------------------------------------------*/
33
34 #include "stratagus.h"
35
36 #include "religion/deity.h"
37
38 #include "civilization.h"
39 #include "config.h"
40 #include "plane.h"
41 #include "player.h"
42 #include "province.h"
43 #include "religion/deity_domain.h"
44 #include "religion/pantheon.h"
45 #include "religion/religion.h"
46 #include "upgrade/upgrade.h"
47
48 #include <algorithm>
49
50 /*----------------------------------------------------------------------------
51 -- Variables
52 ----------------------------------------------------------------------------*/
53
54 std::vector<CDeity *> CDeity::Deities;
55 std::map<std::string, CDeity *> CDeity::DeitiesByIdent;
56 std::map<const CUpgrade *, CDeity *> CDeity::DeitiesByUpgrade;
57
58 /*----------------------------------------------------------------------------
59 -- Functions
60 ----------------------------------------------------------------------------*/
61
62 /**
63 ** @brief Get a deity
64 **
65 ** @param ident The deity's string identifier
66 ** @param should_find Whether it is an error if the deity could not be found; this is true by default
67 **
68 ** @return The deity if found, or null otherwise
69 */
GetDeity(const std::string & ident,const bool should_find)70 CDeity *CDeity::GetDeity(const std::string &ident, const bool should_find)
71 {
72 std::map<std::string, CDeity *>::const_iterator find_iterator = DeitiesByIdent.find(ident);
73
74 if (find_iterator != DeitiesByIdent.end()) {
75 return find_iterator->second;
76 }
77
78 if (should_find) {
79 fprintf(stderr, "Invalid deity: \"%s\".\n", ident.c_str());
80 }
81
82 return nullptr;
83 }
84
85 /**
86 ** @brief Get or add a deity
87 **
88 ** @param ident The deity's string identifier
89 **
90 ** @return The deity if found, or a newly-created one otherwise
91 */
GetOrAddDeity(const std::string & ident)92 CDeity *CDeity::GetOrAddDeity(const std::string &ident)
93 {
94 CDeity *deity = GetDeity(ident, false);
95
96 if (!deity) {
97 deity = new CDeity;
98 deity->Ident = ident;
99 Deities.push_back(deity);
100 DeitiesByIdent[ident] = deity;
101 }
102
103 return deity;
104 }
105
106 /**
107 ** @brief Get a deity by its respective upgrade
108 **
109 ** @param upgrade The deity's upgrade
110 ** @param should_find Whether it is an error if the deity could not be found; this is true by default
111 **
112 ** @return The upgrade's deity, if any
113 */
GetDeityByUpgrade(const CUpgrade * upgrade,const bool should_find)114 CDeity *CDeity::GetDeityByUpgrade(const CUpgrade *upgrade, const bool should_find)
115 {
116 if (DeitiesByUpgrade.find(upgrade) != DeitiesByUpgrade.end()) {
117 return DeitiesByUpgrade.find(upgrade)->second;
118 }
119
120 if (should_find) {
121 fprintf(stderr, "No deity found for upgrade: \"%s\".\n", upgrade->Ident.c_str());
122 }
123
124 return nullptr;
125 }
126
127 /**
128 ** @brief Remove the existing deities
129 */
ClearDeities()130 void CDeity::ClearDeities()
131 {
132 for (size_t i = 0; i < Deities.size(); ++i) {
133 delete Deities[i];
134 }
135 Deities.clear();
136 }
137
138 /**
139 ** @brief Process data provided by a configuration file
140 **
141 ** @param config_data The configuration data
142 */
ProcessConfigData(const CConfigData * config_data)143 void CDeity::ProcessConfigData(const CConfigData *config_data)
144 {
145 for (size_t i = 0; i < config_data->Properties.size(); ++i) {
146 std::string key = config_data->Properties[i].first;
147 std::string value = config_data->Properties[i].second;
148
149 if (key == "name") {
150 this->Name = value;
151 } else if (key == "pantheon") {
152 value = FindAndReplaceString(value, "_", "-");
153 this->Pantheon = CPantheon::GetPantheon(value);
154 } else if (key == "gender") {
155 this->Gender = GetGenderIdByName(value);
156 } else if (key == "major") {
157 this->Major = StringToBool(value);
158 } else if (key == "civilization") {
159 value = FindAndReplaceString(value, "_", "-");
160 CCivilization *civilization = CCivilization::GetCivilization(value);
161 if (civilization != nullptr) {
162 this->Civilizations.push_back(civilization);
163 civilization->Deities.push_back(this);
164 }
165 } else if (key == "religion") {
166 value = FindAndReplaceString(value, "_", "-");
167 CReligion *religion = CReligion::GetReligion(value.c_str());
168 if (religion) {
169 this->Religions.push_back(religion);
170 }
171 } else if (key == "domain") {
172 value = FindAndReplaceString(value, "_", "-");
173 CDeityDomain *deity_domain = CDeityDomain::GetDeityDomain(value.c_str());
174 if (deity_domain) {
175 this->Domains.push_back(deity_domain);
176 }
177 } else if (key == "description") {
178 this->Description = value;
179 } else if (key == "background") {
180 this->Background = value;
181 } else if (key == "quote") {
182 this->Quote = value;
183 } else if (key == "icon") {
184 value = FindAndReplaceString(value, "_", "-");
185 this->Icon.Name = value;
186 this->Icon.Icon = nullptr;
187 this->Icon.Load();
188 this->Icon.Icon->Load();
189 } else if (key == "home_plane") {
190 value = FindAndReplaceString(value, "_", "-");
191 CPlane *plane = CPlane::GetPlane(value);
192 if (plane) {
193 this->HomePlane = plane;
194 }
195 } else if (key == "deity_upgrade") {
196 value = FindAndReplaceString(value, "_", "-");
197 CUpgrade *upgrade = CUpgrade::Get(value);
198 if (upgrade) {
199 this->DeityUpgrade = upgrade;
200 CDeity::DeitiesByUpgrade[upgrade] = this;
201 } else {
202 fprintf(stderr, "Invalid upgrade: \"%s\".\n", value.c_str());
203 }
204 } else if (key == "character_upgrade") {
205 value = FindAndReplaceString(value, "_", "-");
206 CUpgrade *upgrade = CUpgrade::Get(value);
207 if (upgrade) {
208 this->CharacterUpgrade = upgrade;
209 } else {
210 fprintf(stderr, "Invalid upgrade: \"%s\".\n", value.c_str());
211 }
212 } else if (key == "holy_order") {
213 value = FindAndReplaceString(value, "_", "-");
214 CFaction *holy_order = PlayerRaces.GetFaction(value);
215 if (holy_order) {
216 this->HolyOrders.push_back(holy_order);
217 holy_order->HolyOrderDeity = this;
218 } else {
219 fprintf(stderr, "Invalid faction: \"%s\".\n", value.c_str());
220 }
221 } else {
222 fprintf(stderr, "Invalid deity property: \"%s\".\n", key.c_str());
223 }
224 }
225
226 for (const CConfigData *child_config_data : config_data->Children) {
227 if (child_config_data->Tag == "cultural_names") {
228 for (size_t j = 0; j < child_config_data->Properties.size(); ++j) {
229 std::string key = child_config_data->Properties[j].first;
230 std::string value = child_config_data->Properties[j].second;
231
232 key = FindAndReplaceString(key, "_", "-");
233
234 const CCivilization *civilization = CCivilization::GetCivilization(key);
235
236 if (civilization) {
237 this->CulturalNames[civilization] = value;
238 }
239 }
240 } else {
241 fprintf(stderr, "Invalid deity property: \"%s\".\n", child_config_data->Tag.c_str());
242 }
243 }
244
245 if (this->Major && this->Domains.size() > MAJOR_DEITY_DOMAIN_MAX) { // major deities can only have up to three domains
246 this->Domains.resize(MAJOR_DEITY_DOMAIN_MAX);
247 } else if (!this->Major && this->Domains.size() > MINOR_DEITY_DOMAIN_MAX) { // minor deities can only have one domain
248 this->Domains.resize(MINOR_DEITY_DOMAIN_MAX);
249 }
250
251 for (CDeityDomain *domain : this->Domains) {
252 for (CUpgrade *ability : domain->Abilities) {
253 if (std::find(this->Abilities.begin(), this->Abilities.end(), ability) == this->Abilities.end()) {
254 this->Abilities.push_back(ability);
255 }
256 }
257 }
258 }
259
260 /**
261 ** @brief Get the cultural name for a given civilization
262 **
263 ** @param civilization The civilization
264 **
265 ** @return The name if present, or an empty string otherwise
266 */
GetCulturalName(const CCivilization * civilization) const267 std::string CDeity::GetCulturalName(const CCivilization *civilization) const
268 {
269 std::map<const CCivilization *, std::string>::const_iterator find_iterator = this->CulturalNames.find(civilization);
270
271 if (find_iterator != this->CulturalNames.end()) {
272 return find_iterator->second;
273 }
274
275 return std::string();
276 }