ManaPlus
questdb.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2013-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "resources/db/questdb.h"
23 
24 #include "configuration.h"
25 #include "logger.h"
26 
27 #include "utils/dtor.h"
28 #include "utils/gettext.h"
29 
31 
32 #include "resources/beingcommon.h"
33 #include "resources/questeffect.h"
34 #include "resources/questitem.h"
35 
36 #include "debug.h"
37 
38 namespace
39 {
40  // quest variables: var, (val1, val2, val3, time)
42  // quests: var, quests
43  std::map<int, STD_VECTOR<QuestItem*> > mQuests;
44  STD_VECTOR<QuestEffect*> mAllEffects;
45 } // namespace
46 
48 {
49  unload();
50  logger->log1("Initializing quest database...");
52  loadXmlFile(paths.getStringValue("questsPatchFile"), SkipError_true);
53  loadXmlDir("questsPatchDir", loadXmlFile)
54 }
55 
56 static void loadQuest(const int var,
57  XmlNodeConstPtr node)
58 {
59  if (node == nullptr)
60  return;
61  QuestItem *const quest = new QuestItem;
62  // TRANSLATORS: quests window quest name
63  quest->name = XML::langProperty(node, "name", _("unknown"));
64  quest->group = XML::getProperty(node, "group", "");
65  std::string incompleteStr = XML::getProperty(node, "incomplete", "");
66  std::string completeStr = XML::getProperty(node, "complete", "");
67  if (incompleteStr.empty() && completeStr.empty())
68  {
69  logger->log("complete flags incorrect");
70  delete quest;
71  return;
72  }
73  splitToIntSet(quest->incomplete, incompleteStr, ',');
74  splitToIntSet(quest->complete, completeStr, ',');
75  if (quest->incomplete.empty() && quest->complete.empty())
76  {
77  logger->log("complete flags incorrect");
78  delete quest;
79  return;
80  }
81  if (quest->incomplete.empty() || quest->complete.empty())
82  quest->broken = true;
83 
84  for_each_xml_child_node(dataNode, node)
85  {
86  if (!xmlTypeEqual(dataNode, XML_ELEMENT_NODE))
87  continue;
88  XmlChar *const data = reinterpret_cast<XmlChar*>(
89  XmlNodeGetContent(dataNode));
90  if (data == nullptr)
91  continue;
92  std::string str = translator->getStr(data);
93  XmlFree(data);
94 
95  for (int f = 1; f < 100; f ++)
96  {
97  const std::string key = strprintf("text%d", f);
98  const std::string val = XML::getProperty(dataNode,
99  key.c_str(),
100  "");
101  if (val.empty())
102  break;
103  const std::string param = strprintf("{@@%d}", f);
104  replaceAll(str, param, val);
105  }
106  replaceItemLinks(str);
107  if (xmlNameEqual(dataNode, "text"))
108  {
109  quest->texts.push_back(QuestItemText(str,
111  std::string(),
112  std::string()));
113  }
114  else if (xmlNameEqual(dataNode, "name"))
115  {
116  quest->texts.push_back(QuestItemText(str,
118  std::string(),
119  std::string()));
120  }
121  else if (xmlNameEqual(dataNode, "reward"))
122  {
123  quest->texts.push_back(QuestItemText(str,
125  std::string(),
126  std::string()));
127  }
128  else if (xmlNameEqual(dataNode, "questgiver") ||
129  xmlNameEqual(dataNode, "giver"))
130  {
131  quest->texts.push_back(QuestItemText(str,
133  std::string(),
134  std::string()));
135  }
136  else if (xmlNameEqual(dataNode, "coordinates"))
137  {
138  const std::string str1 = toString(XML::getIntProperty(
139  dataNode, "x", 0, 1, 1000));
140  const std::string str2 = toString(XML::getIntProperty(
141  dataNode, "y", 0, 1, 1000));
142  quest->texts.push_back(QuestItemText(str,
144  str1,
145  str2));
146  }
147  else if (xmlNameEqual(dataNode, "npc"))
148  {
149  quest->texts.push_back(QuestItemText(str,
151  std::string(),
152  std::string()));
153  }
154  }
155  quest->var = var;
156  mQuests[var].push_back(quest);
157 }
158 
159 static void loadEffect(const int var,
160  XmlNodeConstPtr node)
161 {
162  QuestEffect *const effect = new QuestEffect;
163  effect->map = XML::getProperty(node, "map", "");
164  effect->id = fromInt(XML::getProperty(node, "npc", -1), BeingTypeId);
165  effect->effectId = XML::getProperty(node, "effect", -1);
166  const std::string values = XML::getProperty(node, "value", "");
167  splitToIntSet(effect->values, values, ',');
168 
169  if (effect->map.empty() || effect->id == BeingTypeId_negOne
170  || effect->effectId == -1 || values.empty())
171  {
172  delete effect;
173  return;
174  }
175  effect->var = var;
176  mAllEffects.push_back(effect);
177 }
178 
179 void QuestDb::loadXmlFile(const std::string &fileName,
180  const SkipError skipError)
181 {
184  skipError);
185  XmlNodeConstPtrConst root = doc.rootNode();
186  if (root == nullptr)
187  return;
188 
189  for_each_xml_child_node(varNode, root)
190  {
191  if (xmlNameEqual(varNode, "include"))
192  {
193  const std::string name = XML::getProperty(varNode, "name", "");
194  if (!name.empty())
195  loadXmlFile(name, skipError);
196  continue;
197  }
198  else if (xmlNameEqual(varNode, "var"))
199  {
200  const int id = XML::getProperty(varNode, "id", 0);
201  if (id < 0)
202  continue;
203  mVars[id] = QuestVar();
204  for_each_xml_child_node(questNode, varNode)
205  {
206  if (xmlNameEqual(questNode, "quest"))
207  loadQuest(id, questNode);
208  else if (xmlNameEqual(questNode, "effect"))
209  loadEffect(id, questNode);
210  }
211  }
212  }
213 }
214 
215 
217 {
218  logger->log1("Unloading quest database...");
219  for (std::map<int, STD_VECTOR<QuestItem*> >::iterator it
220  = mQuests.begin(), it_end = mQuests.end(); it != it_end; ++ it)
221  {
222  STD_VECTOR<QuestItem*> &quests = (*it).second;
223  for (STD_VECTOR<QuestItem*>::iterator it2 = quests.begin(),
224  it2_end = quests.end(); it2 != it2_end; ++ it2)
225  {
226  delete *it2;
227  }
228  }
230  mAllEffects.clear();
231  mQuests.clear();
232 }
233 
235 {
236  return &mVars;
237 }
238 
239 std::map<int, STD_VECTOR<QuestItem*> > *QuestDb::getQuests()
240 {
241  return &mQuests;
242 }
243 
244 STD_VECTOR<QuestEffect*> *QuestDb::getAllEffects()
245 {
246  return &mAllEffects;
247 }
248 
249 std::string QuestDb::getName(const int id)
250 {
251  std::map<int, STD_VECTOR<QuestItem*> >::const_iterator it =
252  mQuests.find(id);
253  if (it == mQuests.end())
254  {
255  // TRANSLATORS: quests window quest name
256  return _("unknown");
257  }
258  const STD_VECTOR<QuestItem*> &items = (*it).second;
259  if (items.empty())
260  {
261  // TRANSLATORS: quests window quest name
262  return _("unknown");
263  }
264  return items[0]->name;
265 }
static void loadXmlFile(const std::string &file, const std::string &name, BadgesInfos &arr, const SkipError skipError)
Definition: badgesdb.cpp:43
#define loadXmlDir(name, function)
Definition: beingcommon.h:39
int BeingTypeId
Definition: beingtypeid.h:30
const BeingTypeId BeingTypeId_negOne
Definition: beingtypeid.h:31
std::string getStringValue(const std::string &key) const
void log(const char *const log_text,...)
Definition: logger.cpp:269
void log1(const char *const log_text)
Definition: logger.cpp:238
const std::string getStr(const std::string &str)
Definition: podict.cpp:45
xmlNodePtr rootNode()
Definition: libxml.cpp:169
Configuration paths
void delete_all(Container &c)
Definition: dtor.h:56
#define _(s)
Definition: gettext.h:35
#define fromInt(val, name)
Definition: intdefines.h:46
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:161
Logger * logger
Definition: logger.cpp:89
uint32_t data
CompositeGenerator< T > values(T val1, T val2)
Definition: catch.hpp:2472
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
void unload()
Definition: net.cpp:180
NpcQuestVarMap * getVars()
Definition: questdb.cpp:234
std::string getName(const int id)
Definition: questdb.cpp:249
void unload()
Definition: questdb.cpp:216
void loadXmlFile(const std::string &fileName, const SkipError skipError)
Definition: questdb.cpp:179
void load()
Definition: questdb.cpp:47
std::map< int, std::vector< QuestItem * > > * getQuests()
Definition: questdb.cpp:239
std::vector< QuestEffect * > * getAllEffects()
Definition: questdb.cpp:244
@ COORDINATES
Definition: questtype.h:33
std::string langProperty(const xmlNodePtr node, const char *const name, const std::string &def)
Definition: libxml.cpp:258
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:174
int getIntProperty(const xmlNodePtr node, const char *const name, int def, const int min, const int max)
Definition: libxml.cpp:190
std::map< int, std::vector< QuestItem * > > mQuests
Definition: questdb.cpp:43
std::vector< QuestEffect * > mAllEffects
Definition: questdb.cpp:44
PoDict * translator
Definition: podict.cpp:28
static void loadQuest(const int var, const xmlNodePtr node)
Definition: questdb.cpp:56
static void loadEffect(const int var, const xmlNodePtr node)
Definition: questdb.cpp:159
std::map< int, QuestVar > NpcQuestVarMap
Definition: questvar.h:58
const bool SkipError_false
Definition: skiperror.h:30
const bool SkipError_true
Definition: skiperror.h:30
bool SkipError
Definition: skiperror.h:30
std::string & replaceAll(std::string &context, const std::string &from, const std::string &to)
std::string strprintf(const char *const format,...)
void splitToIntSet(std::set< int > &tokens, const std::string &text, const char separator)
void replaceItemLinks(std::string &msg)
std::string map
Definition: questeffect.h:45
BeingTypeId id
Definition: questeffect.h:47
std::set< int > values
Definition: questeffect.h:49
std::vector< QuestItemText > texts
Definition: questitem.h:54
std::string group
Definition: questitem.h:51
int var
Definition: questitem.h:49
bool broken
Definition: questitem.h:56
std::set< int > complete
Definition: questitem.h:53
std::string name
Definition: questitem.h:50
std::set< int > incomplete
Definition: questitem.h:52
std::string fileName
Definition: testmain.cpp:39
const bool UseVirtFs_true
Definition: usevirtfs.h:30