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