ManaPlus
npcdialogdb.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2011-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 
23 
24 #include "configuration.h"
25 
26 #include "resources/beingcommon.h"
28 
29 #include "utils/checkutils.h"
30 #include "utils/dtor.h"
31 
32 #include "debug.h"
33 
34 namespace
35 {
36  bool mLoaded = false;
38 } // namespace
39 
41 {
42  if (mLoaded)
43  unload();
44 
45  logger->log1("Loading npc dialog database...");
46  loadXmlFile(paths.getStringValue("npcDialogsFile"), SkipError_false);
47  loadXmlFile(paths.getStringValue("npcDialogsPatchFile"), SkipError_true);
48  loadXmlDir("npcDialogsPatchDir", loadXmlFile)
49 
50  mLoaded = true;
51 }
52 
53 static void loadNpcDialogMenu(NpcDialogInfo *const dialog,
54  XmlNodeConstPtrConst node)
55 {
56  for_each_xml_child_node(childNode, node)
57  {
58  if (!xmlTypeEqual(childNode, XML_ELEMENT_NODE))
59  continue;
60 
61  if (xmlNameEqual(childNode, "button"))
62  {
63  const std::string name = XML::getProperty(childNode, "name", "");
64  const std::string value = XML::getProperty(childNode, "value", "");
65  if (value.empty())
66  continue;
67 
68  NpcButtonInfo *const button = new NpcButtonInfo;
69  button->x = XML::getIntProperty(
70  childNode, "x", 0, 0, 10000);
71  button->y = XML::getIntProperty(
72  childNode, "y", 0, 0, 10000);
73  button->name = name;
74  button->value = value;
75  button->image = XML::getProperty(childNode, "image", "");
76  if (button->name.empty() && button->image.empty())
77  {
78  reportAlways("Error: npc button without name or image")
79  delete button;
80  continue;
81  }
83  childNode, "imageWidth", 16, 1, 1000);
85  childNode, "imageHeight", 16, 1, 1000);
86  dialog->menu.buttons.push_back(button);
87  }
88  else if (xmlNameEqual(childNode, "image"))
89  {
90  const std::string image = XML::getProperty(childNode, "image", "");
91  if (image.empty())
92  {
93  reportAlways("Error: no image attribute found in image tag.")
94  continue;
95  }
96  NpcImageInfo *const imageInfo = new NpcImageInfo;
97  imageInfo->name = image;
98  imageInfo->x = XML::getIntProperty(
99  childNode, "x", 0, 0, 10000);
100  imageInfo->y = XML::getIntProperty(
101  childNode, "y", 0, 0, 10000);
102  dialog->menu.images.push_back(imageInfo);
103  }
104  else if (xmlNameEqual(childNode, "text"))
105  {
106  const std::string text = XML::getProperty(childNode, "text", "");
107  if (text.empty())
108  {
109  reportAlways("Error: no text attribute found in text tag.")
110  continue;
111  }
112  NpcTextInfo *const textInfo = new NpcTextInfo;
113  textInfo->text = text;
114  textInfo->x = XML::getIntProperty(
115  childNode, "x", 0, 0, 10000);
116  textInfo->y = XML::getIntProperty(
117  childNode, "y", 0, 0, 10000);
118  textInfo->width = XML::getIntProperty(
119  childNode, "width", 20, 10, 10000);
120  textInfo->height = XML::getIntProperty(
121  childNode, "height", 20, 10, 10000);
122  dialog->menu.texts.push_back(textInfo);
123  }
124  }
125 }
126 
127 static void loadNpcDialogInventory(NpcDialogInfo *const dialog,
128  XmlNodePtrConst node)
129 {
130  dialog->inventory.cell = XML::getProperty(node, "cell", "");
132  node, "columns", 10000, 1, 10000);
133 }
134 
135 static void loadNpcDialog(NpcDialogInfo *const dialog,
136  XmlNodeConstPtrConst node)
137 {
138  for_each_xml_child_node(childNode, node)
139  {
140  if (xmlNameEqual(childNode, "menu"))
141  {
142  loadNpcDialogMenu(dialog, childNode);
143  }
144  else if (xmlNameEqual(childNode, "inventory"))
145  {
146  loadNpcDialogInventory(dialog, childNode);
147  }
148  }
149 }
150 
151 void NpcDialogDB::loadXmlFile(const std::string &fileName,
152  const SkipError skipError)
153 {
154  XML::Document *const doc = new XML::Document(fileName,
156  skipError);
157 
158  XmlNodeConstPtrConst root = doc->rootNode();
159  if (root == nullptr)
160  {
161  delete doc;
162  return;
163  }
164 
165  for_each_xml_child_node(node, root)
166  {
167  if (xmlNameEqual(node, "dialog"))
168  {
169  const std::string name = XML::getProperty(node, "name", "");
170  if (name.empty())
171  continue;
172 
173  deleteDialog(name);
174  NpcDialogInfo *const dialog = new NpcDialogInfo;
175  dialog->name = name;
176  dialog->hideText = XML::getBoolProperty(
177  node, "hideText", false);
178  mDialogs[name] = dialog;
179  loadNpcDialog(dialog, node);
180  }
181  else if (xmlNameEqual(node, "include"))
182  {
183  const std::string name = XML::getProperty(node, "name", "");
184  if (!name.empty())
185  loadXmlFile(name, skipError);
186  continue;
187  }
188  }
189 
190  delete doc;
191 }
192 
193 void NpcDialogDB::deleteDialog(const std::string &name)
194 {
195  const DialogsIter it = mDialogs.find(name);
196  if (it == mDialogs.end())
197  return;
198 
199  NpcDialogInfo *dialog = (*it).second;
200  delete_all(dialog->menu.buttons);
201  delete_all(dialog->menu.images);
202  delete_all(dialog->menu.texts);
203  mDialogs.erase(it);
204  delete dialog;
205 }
206 
208 {
209  logger->log1("Unloading npc dialog database...");
210 
212  {
213  NpcDialogInfo *dialog = (*it).second;
214  delete_all(dialog->menu.buttons);
215  delete_all(dialog->menu.images);
216  delete_all(dialog->menu.texts);
217  delete dialog;
218  }
219  mDialogs.clear();
220 
221  mLoaded = false;
222 }
223 
224 NpcDialogInfo *NpcDialogDB::getDialog(const std::string &name)
225 {
226  const DialogsIter it = mDialogs.find(name);
227  if (it == mDialogs.end())
228  return nullptr;
229  return (*it).second;
230 }
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
#define reportAlways(...)
Definition: checkutils.h:253
std::string getStringValue(const std::string &key) const
void log1(const char *const log_text)
Definition: logger.cpp:238
xmlNodePtr rootNode()
Definition: libxml.cpp:169
Configuration paths
void delete_all(Container &c)
Definition: dtor.h:56
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:161
Logger * logger
Definition: logger.cpp:89
void unload()
Definition: net.cpp:180
void loadXmlFile(const std::string &fileName, const SkipError skipError)
Dialogs::iterator DialogsIter
Definition: npcdialogdb.h:57
void deleteDialog(const std::string &name)
std::map< std::string, NpcDialogInfo * > Dialogs
Definition: npcdialogdb.h:56
NpcDialogInfo * getDialog(const std::string &name)
bool getBoolProperty(const xmlNodePtr node, const char *const name, const bool def)
Definition: libxml.cpp:269
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
static void loadNpcDialogMenu(NpcDialogInfo *const dialog, const xmlNode *const node)
Definition: npcdialogdb.cpp:53
static void loadNpcDialog(NpcDialogInfo *const dialog, const xmlNode *const node)
static void loadNpcDialogInventory(NpcDialogInfo *const dialog, xmlNode *const node)
const bool SkipError_false
Definition: skiperror.h:30
const bool SkipError_true
Definition: skiperror.h:30
bool SkipError
Definition: skiperror.h:30
std::string name
Definition: npcbuttoninfo.h:44
std::string value
Definition: npcbuttoninfo.h:45
std::string image
Definition: npcbuttoninfo.h:46
std::string name
Definition: npcdialoginfo.h:44
NpcDialogMenuInfo menu
Definition: npcdialoginfo.h:42
NpcInventoryInfo inventory
Definition: npcdialoginfo.h:43
std::vector< NpcImageInfo * > images
std::vector< NpcButtonInfo * > buttons
std::vector< NpcTextInfo * > texts
std::string name
Definition: npcimageinfo.h:40
std::string text
Definition: npctextinfo.h:42
std::string fileName
Definition: testmain.cpp:39
const bool UseVirtFs_true
Definition: usevirtfs.h:30