GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/db/homunculusdb.cpp Lines: 2 64 3.1 %
Date: 2021-03-17 Branches: 0 112 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2019  The ManaPlus Developers
6
 *  Copyright (C) 2019-2021  Andrei Karas
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "resources/db/homunculusdb.h"
25
26
#include "resources/beingcommon.h"
27
#include "resources/beinginfo.h"
28
29
#include "utils/checkutils.h"
30
#include "utils/dtor.h"
31
#include "utils/gettext.h"
32
33
#include "configuration.h"
34
35
#include "debug.h"
36
37
namespace
38
{
39
1
    BeingInfos mHomunculusInfos;
40
    bool mLoaded = false;
41
}  // namespace
42
43
void HomunculusDB::load()
44
{
45
    if (mLoaded)
46
        unload();
47
48
    logger->log1("Initializing homunculus database...");
49
    loadXmlFile(paths.getStringValue("homunculusesFile"), SkipError_false);
50
    loadXmlFile(paths.getStringValue("homunculusesPatchFile"), SkipError_true);
51
    loadXmlDir("homunculusesPatchDir", loadXmlFile)
52
53
    mLoaded = true;
54
}
55
56
void HomunculusDB::loadXmlFile(const std::string &fileName,
57
                               const SkipError skipError)
58
{
59
    XML::Document doc(fileName, UseVirtFs_true, skipError);
60
    XmlNodeConstPtr rootNode = doc.rootNode();
61
62
    if ((rootNode == nullptr) || !xmlNameEqual(rootNode, "homunculuses"))
63
    {
64
        logger->log("Homunculus Database: Error while loading %s!",
65
            paths.getStringValue("homunculusesFile").c_str());
66
        mLoaded = true;
67
        return;
68
    }
69
70
    const int offset = XML::getProperty(rootNode, "offset", 0);
71
72
    // iterate <homunculus>s
73
    for_each_xml_child_node(homunculusNode, rootNode)
74
    {
75
        if (xmlNameEqual(homunculusNode, "include"))
76
        {
77
            const std::string name = XML::getProperty(
78
                homunculusNode, "name", "");
79
            if (!name.empty())
80
                loadXmlFile(name, skipError);
81
            continue;
82
        }
83
        if (!xmlNameEqual(homunculusNode, "homunculus"))
84
            continue;
85
86
        const int id = XML::getProperty(homunculusNode, "id", 0);
87
        BeingInfo *currentInfo = nullptr;
88
        if (mHomunculusInfos.find(fromInt(id + offset, BeingTypeId))
89
            != mHomunculusInfos.end())
90
        {
91
            logger->log("HomunculusDB: Redefinition of homunculus ID %d", id);
92
            currentInfo = mHomunculusInfos[fromInt(id + offset, BeingTypeId)];
93
        }
94
        if (currentInfo == nullptr)
95
            currentInfo = new BeingInfo;
96
97
        currentInfo->setBlockType(BlockType::NONE);
98
        currentInfo->setName(XML::langProperty(
99
            // TRANSLATORS: unknown info name
100
            homunculusNode, "name", _("unnamed")));
101
102
        BeingCommon::readBasicAttributes(currentInfo,
103
            homunculusNode, "attack");
104
        BeingCommon::readWalkingAttributes(currentInfo,
105
            homunculusNode,
106
            0);
107
        BeingCommon::readAiAttributes(currentInfo,
108
            homunculusNode);
109
110
        currentInfo->setMaxHP(XML::getProperty(homunculusNode, "maxHP", 0));
111
112
        currentInfo->setDeadSortOffsetY(XML::getProperty(
113
            homunculusNode, "deadSortOffsetY", 31));
114
115
        currentInfo->setColorsList(XML::getProperty(homunculusNode,
116
            "colors", ""));
117
118
        if (currentInfo->getMaxHP() != 0)
119
            currentInfo->setStaticMaxHP(true);
120
121
        SpriteDisplay display;
122
123
        // iterate <sprite>s and <sound>s
124
        for_each_xml_child_node(spriteNode, homunculusNode)
125
        {
126
            BeingCommon::readObjectNodes(spriteNode, display,
127
                currentInfo, "HomunculusDB");
128
        }
129
        currentInfo->setDisplay(display);
130
131
        mHomunculusInfos[fromInt(id + offset, BeingTypeId)] = currentInfo;
132
    }
133
}
134
135
void HomunculusDB::unload()
136
{
137
    logger->log1("Unloading homunculus database...");
138
    delete_all(mHomunculusInfos);
139
    mHomunculusInfos.clear();
140
141
    mLoaded = false;
142
}
143
144
BeingInfo *HomunculusDB::get(const BeingTypeId id)
145
{
146
    BeingInfoIterator i = mHomunculusInfos.find(id);
147
148
    if (i == mHomunculusInfos.end())
149
    {
150
        i = mHomunculusInfos.find(id);
151
        if (i == mHomunculusInfos.end())
152
        {
153
            reportAlways("HomunculusDB: Warning, unknown homunculus ID "
154
                "%d requested",
155
                toInt(id, int))
156
            return BeingInfo::unknown;
157
        }
158
    }
159
    return i->second;
160
2
}