GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/db/statdb.cpp Lines: 14 93 15.1 %
Date: 2017-11-29 Branches: 2 218 0.9 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2016-2017  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/statdb.h"
22
23
#include "configuration.h"
24
25
#include "enums/being/attributesstrings.h"
26
27
#include "utils/checkutils.h"
28
29
#include "resources/beingcommon.h"
30
31
#include "utils/gettext.h"
32
33
#include "debug.h"
34
35
namespace
36
{
37
    bool mLoaded = false;
38
2
    STD_VECTOR<BasicStat> mBasicStats;
39
2
    std::map<std::string, STD_VECTOR<BasicStat> > mStats;
40
2
    STD_VECTOR<std::string> mPages;
41
}  // namespace
42
43
void StatDb::addDefaultStats()
44
{
45
    mBasicStats.push_back(BasicStat(Attributes::PLAYER_STR,
46
        "str",
47
        // TRANSLATORS: player stat
48
        _("Strength")));
49
    mBasicStats.push_back(BasicStat(Attributes::PLAYER_AGI,
50
        "agi",
51
        // TRANSLATORS: player stat
52
        _("Agility")));
53
    mBasicStats.push_back(BasicStat(Attributes::PLAYER_VIT,
54
        "vit",
55
        // TRANSLATORS: player stat
56
        _("Vitality")));
57
    mBasicStats.push_back(BasicStat(Attributes::PLAYER_INT,
58
        "int",
59
        // TRANSLATORS: player stat
60
        _("Intelligence")));
61
    mBasicStats.push_back(BasicStat(Attributes::PLAYER_DEX,
62
        "dex",
63
        // TRANSLATORS: player stat
64
        _("Dexterity")));
65
    mBasicStats.push_back(BasicStat(Attributes::PLAYER_LUK,
66
        "luk",
67
        // TRANSLATORS: player stat
68
        _("Luck")));
69
}
70
71
2
const STD_VECTOR<BasicStat> &StatDb::getBasicStats()
72
{
73
2
    return mBasicStats;
74
}
75
76
const STD_VECTOR<BasicStat> &StatDb::getStats(const std::string &page)
77
{
78
    return mStats[page];
79
}
80
81
2
const STD_VECTOR<std::string> &StatDb::getPages()
82
{
83
2
    return mPages;
84
}
85
86
void StatDb::load()
87
{
88
    if (mLoaded)
89
        unload();
90
91
    logger->log1("Initializing stat database...");
92
93
    loadXmlFile(paths.getStringValue("statFile"), SkipError_false);
94
    loadXmlFile(paths.getStringValue("statPatchFile"), SkipError_true);
95
    loadXmlDir("statPatchDir", loadXmlFile);
96
    mLoaded = true;
97
}
98
99
static void loadBasicStats(XmlNodeConstPtr rootNode)
100
{
101
    const int maxAttr = static_cast<int>(Attributes::MAX_ATTRIBUTE);
102
    for_each_xml_child_node(node, rootNode)
103
    {
104
        if (xmlNameEqual(node, "stat"))
105
        {
106
            const std::string name = XML::getProperty(node, "name", "");
107
            const std::string attr = XML::getProperty(node, "attr", "");
108
            if (attr.empty() || AttributesEnum::find(attr) == false)
109
            {
110
                const int id = XML::getProperty(node, "id", 0);
111
                if (id <= 0 || id >= maxAttr)
112
                {
113
                    reportAlways("Wrong attr or id for basic "
114
                        "stat with name %s",
115
                        name.c_str());
116
                    continue;
117
                }
118
                const std::string tag = XML::getProperty(node, "tag", "");
119
                mBasicStats.push_back(BasicStat(static_cast<AttributesT>(id),
120
                    tag,
121
                    name));
122
            }
123
            else
124
            {
125
                const std::string tag = XML::getProperty(node, "tag", "");
126
                mBasicStats.push_back(BasicStat(AttributesEnum::get(attr),
127
                    tag,
128
                    name));
129
            }
130
        }
131
    }
132
}
133
134
static void loadStats(XmlNodeConstPtr rootNode,
135
                      const std::string &page)
136
{
137
    const int maxAttr = static_cast<int>(Attributes::MAX_ATTRIBUTE);
138
    STD_VECTOR<BasicStat> &stats = mStats[page];
139
    mPages.push_back(page);
140
    for_each_xml_child_node(node, rootNode)
141
    {
142
        if (xmlNameEqual(node, "stat"))
143
        {
144
            const std::string name = XML::getProperty(node, "name", "");
145
            const std::string attr = XML::getProperty(node, "attr", "");
146
            if (attr.empty() || AttributesEnum::find(attr) == false)
147
            {
148
                const int id = XML::getProperty(node, "id", 0);
149
                if (id <= 0 || id >= maxAttr)
150
                {
151
                    reportAlways("Wrong attr or id for extended "
152
                        "stat with name %s",
153
                        name.c_str());
154
                    continue;
155
                }
156
                stats.push_back(BasicStat(static_cast<AttributesT>(id),
157
                    std::string(),
158
                    name));
159
            }
160
            else
161
            {
162
                stats.push_back(BasicStat(AttributesEnum::get(attr),
163
                    std::string(),
164
                    name));
165
            }
166
        }
167
    }
168
}
169
170
void StatDb::loadXmlFile(const std::string &fileName,
171
                         const SkipError skipError)
172
{
173
    XML::Document doc(fileName,
174
        UseVirtFs_true,
175
        skipError);
176
    XmlNodeConstPtrConst rootNode = doc.rootNode();
177
178
    if ((rootNode == nullptr) || !xmlNameEqual(rootNode, "stats"))
179
    {
180
        logger->log("StatDb: Error while loading %s!",
181
            fileName.c_str());
182
        if (skipError == SkipError_false)
183
            addDefaultStats();
184
        return;
185
    }
186
187
    for_each_xml_child_node(node, rootNode)
188
    {
189
        if (xmlNameEqual(node, "include"))
190
        {
191
            const std::string name = XML::getProperty(node, "name", "");
192
            if (!name.empty())
193
                loadXmlFile(name, skipError);
194
            continue;
195
        }
196
        else if (xmlNameEqual(node, "basic"))
197
        {
198
            loadBasicStats(node);
199
        }
200
        else if (xmlNameEqual(node, "extended"))
201
        {
202
            // TRANSLATORS: stats page name
203
            loadStats(node, _("Extended"));
204
        }
205
        else if (xmlNameEqual(node, "page"))
206
        {
207
            std::string page = XML::langProperty(node, "name", "");
208
            if (page.empty())
209
            {
210
                reportAlways("Page without name in stats.xml");
211
                page = "Unknown";
212
            }
213
            loadStats(node, page);
214
        }
215
    }
216
    if (skipError == SkipError_false)
217
    {
218
        if (mBasicStats.empty() &&
219
            mStats.empty())
220
        {
221
            reportAlways("StatDb: no stats found");
222
            addDefaultStats();
223
        }
224
    }
225
}
226
227
384
void StatDb::unload()
228
{
229
384
    logger->log1("Unloading stat database...");
230
231
384
    mBasicStats.clear();
232
384
    mStats.clear();
233
384
    mPages.clear();
234
384
    mLoaded = false;
235

390
}