summaryrefslogblamecommitdiff
path: root/src/game-server/specialmanager.cpp
blob: 32669bca461f61daec95a60640d73b365505c842 (plain) (tree)
















































































































































































                                                                                  
/*
 *  The Mana Server
 *  Copyright (C) 2004-2010  The Mana World Development Team
 *  Copyright (C) 2010-2012  The Mana Developers
 *
 *  This file is part of The Mana Server.
 *
 *  The Mana Server is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  The Mana Server is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with The Mana Server.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "specialmanager.h"

#include "utils/xml.h"
#include "utils/logger.h"

static SpecialManager::TargetMode getTargetByString(const std::string &str)
{
    std::string strLower = utils::toLower(str);
    if (strLower == "being")
        return SpecialManager::TARGET_BEING;
    else if (strLower == "point")
        return SpecialManager::TARGET_POINT;

    LOG_WARN("Unknown targetmode " << str << " assuming being.");
    return SpecialManager::TARGET_BEING;
}

void SpecialManager::readSpecialNode(xmlNodePtr specialNode,
                                     const std::string &setName)
{
    std::string name = utils::toLower(
                XML::getProperty(specialNode, "name", std::string()));
    int id = XML::getProperty(specialNode, "id", 0);

    if (id <= 0 || name.empty())
    {
        LOG_WARN("Invalid special (empty name or id <= 0) in set: " << setName);
        return;
    }

    SpecialsInfo::iterator it = mSpecialsInfo.find(id);
    if (it != mSpecialsInfo.end())
    {
        LOG_WARN("SpecialManager: The same id: " << id
                 << " is given for special names: " << it->first
                 << " and " << name);
        LOG_WARN("The special reference: " << id
                 << ": '" << name << "' will be ignored.");
        return;
    }

    bool rechargeable = XML::getBoolProperty(specialNode, "rechargeable", true);
    int neededMana = XML::getProperty(specialNode, "needed", 0);
    int defaultRechargeSpeed = XML::getProperty(specialNode,
                                                "rechargespeed", 0);

    if (rechargeable && neededMana <= 0)
    {
        LOG_WARN("Invalid special '" << name
                 << "' (rechargable but no needed attribute) in set: "
                 << setName);
        return;
    }


    SpecialInfo *newInfo = new SpecialManager::SpecialInfo;
    newInfo->setName = setName;
    newInfo->name = name;
    newInfo->id = id;
    newInfo->rechargeable = rechargeable;
    newInfo->neededMana = neededMana;
    newInfo->defaultRechargeSpeed = defaultRechargeSpeed;

    newInfo->target = getTargetByString(XML::getProperty(specialNode, "target",
                                                         std::string()));

    mSpecialsInfo[newInfo->id] = newInfo;

    std::string keyName = setName + "_" + newInfo->name;
    mNamedSpecialsInfo[keyName] = newInfo;
}

void SpecialManager::initialize()
{
    clear();

    XML::Document doc(mSpecialFile);
    xmlNodePtr rootNode = doc.rootNode();

    if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "specials"))
    {
        LOG_ERROR("Special Manager: " << mSpecialFile
                  << " is not a valid database file!");
        return;
    }

    LOG_INFO("Loading special reference: " << mSpecialFile);

    for_each_xml_child_node(setNode, rootNode)
    {
        // The server will prefix the core name with the set, so we need one.
        if (!xmlStrEqual(setNode->name, BAD_CAST "set"))
            continue;

        std::string setName = XML::getProperty(setNode, "name", std::string());
        if (setName.empty())
        {
            LOG_WARN("The " << mSpecialFile << " file is containing unamed <set> "
                     "tags and will be ignored.");
            continue;
        }

        setName = utils::toLower(setName);

        for_each_xml_child_node(specialNode, setNode)
        {
            if (!xmlStrEqual(specialNode->name, BAD_CAST "special"))
                continue;
            readSpecialNode(specialNode, setName);
        }
    }
}

void SpecialManager::clear()
{
    for (SpecialsInfo::iterator it = mSpecialsInfo.begin(),
         it_end = mSpecialsInfo.end(); it != it_end; ++it)
    {
        delete it->second;
    }
    mSpecialsInfo.clear();
    mNamedSpecialsInfo.clear();
}

unsigned int SpecialManager::getId(const std::string &set,
                                   const std::string &name) const
{
    std::string key = utils::toLower(set) + "_" + utils::toLower(name);
    return getId(key);
}

unsigned int SpecialManager::getId(const std::string &specialName) const
{
    if (mNamedSpecialsInfo.contains(specialName))
        return mNamedSpecialsInfo.value(specialName)->id;
    else
        return 0;
}

const std::string SpecialManager::getSpecialName(int id) const
{
    SpecialsInfo::const_iterator it = mSpecialsInfo.find(id);
    return it != mSpecialsInfo.end() ? it->second->name : "";
}

const std::string SpecialManager::getSetName(int id) const
{
    SpecialsInfo::const_iterator it = mSpecialsInfo.find(id);
    return it != mSpecialsInfo.end() ? it->second->setName : "";
}

SpecialManager::SpecialInfo *SpecialManager::getSpecialInfo(int id)
{
    SpecialsInfo::const_iterator it = mSpecialsInfo.find(id);
    return it != mSpecialsInfo.end() ? it->second : 0;
}