/* * The Mana Server * Copyright (C) 2004-2010 The Mana World Development Team * * 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 . */ #include #include #include "game-server/itemmanager.hpp" #include "defines.h" #include "game-server/item.hpp" #include "game-server/resourcemanager.hpp" #include "game-server/skillmanager.hpp" #include "scripting/script.hpp" #include "utils/logger.h" #include "utils/xml.hpp" #include typedef std::map< int, ItemClass * > ItemClasses; static ItemClasses itemClasses; /**< Item reference */ static std::string itemReferenceFile; static unsigned int itemDatabaseVersion = 0; /**< Version of the loaded items database file.*/ void ItemManager::initialize(const std::string &file) { itemReferenceFile = file; reload(); } void ItemManager::reload() { int size; char *data = ResourceManager::loadFile(itemReferenceFile, size); if (!data) { LOG_ERROR("Item Manager: Could not find " << itemReferenceFile << "!"); free(data); return; } xmlDocPtr doc = xmlParseMemory(data, size); free(data); if (!doc) { LOG_ERROR("Item Manager: Error while parsing item database (" << itemReferenceFile << ")!"); return; } xmlNodePtr node = xmlDocGetRootElement(doc); if (!node || !xmlStrEqual(node->name, BAD_CAST "items")) { LOG_ERROR("Item Manager: " << itemReferenceFile << " is not a valid database file!"); xmlFreeDoc(doc); return; } LOG_INFO("Loading item reference..."); unsigned nbItems = 0; for (node = node->xmlChildrenNode; node != NULL; node = node->next) { // Try to load the version of the item database. The version is defined // as subversion tag embedded as XML attribute. So every modification // to the items.xml file will increase the revision automatically. if (xmlStrEqual(node->name, BAD_CAST "version")) { std::string revision = XML::getProperty(node, "revision", std::string()); itemDatabaseVersion = atoi(revision.c_str()); LOG_INFO("Loading item database version " << itemDatabaseVersion); continue; } if (!xmlStrEqual(node->name, BAD_CAST "item")) { continue; } int id = XML::getProperty(node, "id", 0); if (id == 0) { LOG_WARN("Item Manager: An (ignored) item has no ID in " << itemReferenceFile << "!"); continue; } std::string sItemType = XML::getProperty(node, "type", ""); ItemType itemType = itemTypeFromString(sItemType); if (itemType == ITEM_UNKNOWN) { LOG_WARN(itemReferenceFile<<": Unknown item type \""<second; } int weight = XML::getProperty(node, "weight", 0); int value = XML::getProperty(node, "value", 0); int maxPerSlot = XML::getProperty(node, "max-per-slot", 0); int sprite = XML::getProperty(node, "sprite_id", 0); std::string scriptFile = XML::getProperty(node, "script", ""); unsigned attackRange = XML::getProperty(node, "attack-range", 0); ItemModifiers modifiers; if (itemType == ITEM_EQUIPMENT_ONE_HAND_WEAPON || itemType == ITEM_EQUIPMENT_TWO_HANDS_WEAPON) { int weaponType = 0; std::string strWeaponType = XML::getProperty(node, "weapon-type", ""); if (strWeaponType == "") { LOG_WARN(itemReferenceFile<<": Unknown weapon type \"" <<"\" for item #"< ITEM_USABLE && itemType < ITEM_EQUIPMENT_AMMO && maxPerSlot != 1) { LOG_WARN("Item Manager: Setting max-per-slot property to 1 for " "equipment " << id << " in " << itemReferenceFile << '.'); maxPerSlot = 1; } if (weight == 0) { LOG_WARN("Item Manager: Missing weight for item " << id << " in " << itemReferenceFile << '.'); weight = 1; } // TODO: Clean this up some if (scriptFile != "") { std::stringstream filename; filename << "scripts/items/" << scriptFile; if (ResourceManager::exists(filename.str())) // file exists! { LOG_INFO("Loading item script: " << filename.str()); Script *s = Script::create("lua"); s->loadFile(filename.str()); item->setScript(s); } else { LOG_WARN("Could not find script file \"" << filename.str() << "\" for item #"<setWeight(weight); item->setCost(value); item->setMaxPerSlot(maxPerSlot); item->setModifiers(modifiers); item->setSpriteID(sprite ? sprite : id); ++nbItems; item->setAttackRange(attackRange); LOG_DEBUG("Item: ID: " << id << ", itemType: " << itemType << ", weight: " << weight << ", value: " << value << ", script: " << scriptFile << ", maxPerSlot: " << maxPerSlot << "."); } LOG_INFO("Loaded " << nbItems << " items from " << itemReferenceFile << "."); xmlFreeDoc(doc); } void ItemManager::deinitialize() { for (ItemClasses::iterator i = itemClasses.begin(), i_end = itemClasses.end(); i != i_end; ++i) { delete i->second; } itemClasses.clear(); } ItemClass *ItemManager::getItem(int itemId) { ItemClasses::const_iterator i = itemClasses.find(itemId); return i != itemClasses.end() ? i->second : NULL; } unsigned ItemManager::getDatabaseVersion() { return itemDatabaseVersion; }