From 928fcf801f53d44d8b31b4285052a067340ab4ff Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Thu, 30 Aug 2007 16:46:21 +0000 Subject: Merged equipment database with items database and got rid of the unused item art attribute. Removed the now unnecessary multiplication of weapon IDs with 10000. Added a fallback item icon and used it for unknown items or when an item image fails to load. --- src/CMakeLists.txt | 4 - src/Makefile.am | 4 - src/being.cpp | 2 +- src/being.h | 21 +-- src/localplayer.cpp | 2 - src/main.cpp | 5 - src/net/beinghandler.cpp | 14 +- src/net/charserverhandler.cpp | 4 +- src/net/network.cpp | 2 +- src/player.cpp | 15 +- src/resources/equipmentdb.cpp | 180 ------------------- src/resources/equipmentdb.h | 52 ------ src/resources/equipmentinfo.cpp | 82 --------- src/resources/equipmentinfo.h | 77 --------- src/resources/itemdb.cpp | 372 ++++++++++++++++++++++++---------------- src/resources/iteminfo.cpp | 86 +++++++++- src/resources/iteminfo.h | 118 ++++++++----- src/resources/mapreader.cpp | 2 +- src/resources/spritedef.h | 4 +- 19 files changed, 403 insertions(+), 643 deletions(-) delete mode 100644 src/resources/equipmentdb.cpp delete mode 100644 src/resources/equipmentdb.h delete mode 100644 src/resources/equipmentinfo.cpp delete mode 100644 src/resources/equipmentinfo.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 90d2b37f..c744ba78 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -224,10 +224,6 @@ SET(SRCS resources/ambientoverlay.h resources/animation.cpp resources/animation.h - resources/equipmentdb.cpp - resources/equipmentdb.h - resources/equipmentinfo.cpp - resources/equipmentinfo.h resources/image.cpp resources/image.h resources/imagewriter.cpp diff --git a/src/Makefile.am b/src/Makefile.am index a7f16a26..86ea5e95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -173,10 +173,6 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \ resources/ambientoverlay.h \ resources/animation.cpp \ resources/animation.h \ - resources/equipmentdb.cpp \ - resources/equipmentdb.h \ - resources/equipmentinfo.cpp \ - resources/equipmentinfo.h \ resources/image.cpp \ resources/image.h \ resources/imagewriter.cpp \ diff --git a/src/being.cpp b/src/being.cpp index 402136c5..b0fde6d1 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -32,9 +32,9 @@ #include "map.h" #include "particle.h" -#include "resources/equipmentdb.h" #include "resources/resourcemanager.h" #include "resources/imageset.h" +#include "resources/iteminfo.h" #include "gui/gui.h" diff --git a/src/being.h b/src/being.h index 7ba1ec88..5914014b 100644 --- a/src/being.h +++ b/src/being.h @@ -38,7 +38,7 @@ class AnimatedSprite; class Equipment; -class EquipmentInfo; +class ItemInfo; class Item; class Map; class Graphics; @@ -349,26 +349,23 @@ class Being : public Sprite getHeight() const; /** - * Returns the required size of a target cursor for this being + * Returns the required size of a target cursor for this being. */ - virtual Being::TargetCursorSize - getTargetCursorSize() const + virtual Being::TargetCursorSize getTargetCursorSize() const { return TC_MEDIUM; } std::auto_ptr mEquipment; /** - * Take control of a particle + * Take control of a particle. */ - void - controlParticle(Particle *particle); + void controlParticle(Particle *particle); protected: /** * Sets the new path for this being. */ - void - setPath(const Path &path); + void setPath(const Path &path); /** * Calculates the offset in the given directions. @@ -379,8 +376,7 @@ class Being : public Sprite /** * Returns the sprite direction of this being. */ - SpriteDirection - getSpriteDirection() const; + SpriteDirection getSpriteDirection() const; Uint32 mId; /**< Unique sprite id */ Uint16 mWalkSpeed; /**< Walking speed */ @@ -389,7 +385,8 @@ class Being : public Sprite std::string mName; /**< Name of character */ SpriteIterator mSpriteIterator; - EquipmentInfo* mEquippedWeapon; /**< Engine-related infos about weapon */ + /** Engine-related infos about weapon. */ + const ItemInfo* mEquippedWeapon; Path mPath; std::string mSpeech; diff --git a/src/localplayer.cpp b/src/localplayer.cpp index ddef8b3b..47ad5309 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -37,8 +37,6 @@ #include "net/messageout.h" #include "net/protocol.h" -#include "resources/equipmentinfo.h" - #include "utils/tostring.h" LocalPlayer *player_node = NULL; diff --git a/src/main.cpp b/src/main.cpp index 061f8461..c6544017 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,6 @@ #include "net/messageout.h" #include "net/network.h" -#include "resources/equipmentdb.h" #include "resources/image.h" #include "resources/itemdb.h" #include "resources/monsterdb.h" @@ -348,7 +347,6 @@ void exit_engine() sound.close(); // Unload XML databases - EquipmentDB::unload(); ItemDB::unload(); MonsterDB::unload(); @@ -732,7 +730,6 @@ int main(int argc, char *argv[]) false); // Load XML databases - EquipmentDB::load(); ItemDB::load(); MonsterDB::load(); state = LOGIN_STATE; @@ -825,7 +822,6 @@ int main(int argc, char *argv[]) break; case CHAR_CONNECT_STATE: - logger->log("Char: %i\n", loginData.sex); progressBar->setVisible(true); progressLabel->setCaption( "Connecting to character server..."); @@ -834,7 +830,6 @@ int main(int argc, char *argv[]) break; case ACCOUNT_STATE: - logger->log("Account: %i", loginData.sex); progressBar->setVisible(true); progressLabel->setCaption( "Connecting to account server..."); diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index c6e03c86..2c643a16 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -82,7 +82,7 @@ void BeingHandler::handleMessage(MessageIn *msg) dstBeing = beingManager->findBeing(id); - if (dstBeing == NULL) + if (!dstBeing) { // Being with id >= 110000000 and job 0 are better // known as ghosts, so don't create those. @@ -108,7 +108,7 @@ void BeingHandler::handleMessage(MessageIn *msg) dstBeing->mJob = job; dstBeing->setHairStyle(msg->readInt16()); dstBeing->setVisibleEquipment( - Being::WEAPON_SPRITE, msg->readInt16() * 10000); + Being::WEAPON_SPRITE, msg->readInt16()); dstBeing->setVisibleEquipment( Being::BOTTOMCLOTHES_SPRITE, msg->readInt16()); @@ -261,8 +261,7 @@ void BeingHandler::handleMessage(MessageIn *msg) dstBeing->setHairStyle(id); break; case 2: - dstBeing->setVisibleEquipment( - Being::WEAPON_SPRITE, id * 10000); + dstBeing->setVisibleEquipment(Being::WEAPON_SPRITE, id); break; case 3: // Change lower headgear for eAthena, pants for us dstBeing->setVisibleEquipment( @@ -280,7 +279,8 @@ void BeingHandler::handleMessage(MessageIn *msg) dstBeing->setHairColor(id); break; default: - logger->log("c3: %i\n", id); // unsupported + logger->log("SMSG_BEING_CHANGE_LOOKS: unsupported type: " + "%d, id: %d", type, id); break; } } @@ -306,7 +306,7 @@ void BeingHandler::handleMessage(MessageIn *msg) dstBeing = beingManager->findBeing(id); - if (dstBeing == NULL) + if (!dstBeing) { dstBeing = beingManager->createBeing(id, job); } @@ -378,7 +378,7 @@ void BeingHandler::handleMessage(MessageIn *msg) case 0x0119: // Change in players look - logger->log("0x0119 %i %i %i %x %i\n", msg->readInt32(), + logger->log("0x0119 %i %i %i %x %i", msg->readInt32(), msg->readInt16(), msg->readInt16(), msg->readInt16(), msg->readInt8()); break; diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp index 9018b0af..a3f696c6 100644 --- a/src/net/charserverhandler.cpp +++ b/src/net/charserverhandler.cpp @@ -204,9 +204,7 @@ LocalPlayer* CharServerHandler::readPlayerData(MessageIn &msg, int &slot) msg.readInt16(); // class tempPlayer->setHairStyle(msg.readInt16()); Uint16 weapon = msg.readInt16(); - if (weapon == 11) - weapon = 2; - tempPlayer->setVisibleEquipment(Being::WEAPON_SPRITE, weapon * 10000); + tempPlayer->setVisibleEquipment(Being::WEAPON_SPRITE, weapon); tempPlayer->mLevel = msg.readInt16(); msg.readInt16(); // skill point tempPlayer->setVisibleEquipment(Being::BOTTOMCLOTHES_SPRITE, msg.readInt16()); // head bottom diff --git a/src/net/network.cpp b/src/net/network.cpp index c90e0201..fa5964d6 100644 --- a/src/net/network.cpp +++ b/src/net/network.cpp @@ -296,7 +296,7 @@ MessageIn Network::getNextMessage() len = readWord(2); #ifdef DEBUG - logger->log("Received packet 0x%x of length %d\n", msgId, length); + logger->log("Received packet 0x%x of length %d", msgId, length); #endif MessageIn msg(mInBuffer, len); diff --git a/src/player.cpp b/src/player.cpp index de3bc760..fbac7fa9 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -27,7 +27,8 @@ #include "game.h" #include "graphics.h" -#include "resources/equipmentdb.h" +#include "resources/itemdb.h" +#include "resources/iteminfo.h" #include "utils/tostring.h" @@ -104,13 +105,13 @@ Player::setSex(Uint8 sex) mSprites[BASE_SPRITE] = newBaseSprite; // Reload equipment - for (int i=1; igetSprite(sex)); + "graphics/sprites/" + ItemDB::get( + mEquipmentSpriteIDs.at(i)).getSprite(sex)); delete mSprites[i]; mSprites[i] = newEqSprite; } @@ -174,11 +175,11 @@ Player::setVisibleEquipment(Uint8 slot, int id) if (mSex == 0) { equipmentSprite = new AnimatedSprite( - "graphics/sprites/" + EquipmentDB::get(id)->getSprite(0)); + "graphics/sprites/" + ItemDB::get(id).getSprite(0)); } else { equipmentSprite = new AnimatedSprite( - "graphics/sprites/" + EquipmentDB::get(id)->getSprite(1)); + "graphics/sprites/" + ItemDB::get(id).getSprite(1)); } equipmentSprite->setDirection(getSpriteDirection()); @@ -188,7 +189,7 @@ Player::setVisibleEquipment(Uint8 slot, int id) if (slot == WEAPON_SPRITE) { - mEquippedWeapon = EquipmentDB::get(id); + mEquippedWeapon = &ItemDB::get(id); } setAction(mAction); diff --git a/src/resources/equipmentdb.cpp b/src/resources/equipmentdb.cpp deleted file mode 100644 index 55107050..00000000 --- a/src/resources/equipmentdb.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * The Mana World - * Copyright 2006 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 World 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 World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include - -#include "equipmentdb.h" - -#include "resourcemanager.h" - -#include "../log.h" - -#include "../utils/dtor.h" -#include "../utils/xml.h" - -namespace -{ - EquipmentDB::EquipmentInfos mEquipmentInfos; - EquipmentInfo mUnknown; - bool mLoaded = false; -} - -void -EquipmentDB::load() -{ - if (mLoaded) - return; - - logger->log("Initializing equipment database..."); - mUnknown.setSprite("error.xml", 0); - mUnknown.setSprite("error.xml", 1); - - ResourceManager *resman = ResourceManager::getInstance(); - int size; - char *data = (char*)resman->loadFile("equipment.xml", size); - - if (!data) - { - logger->error("Equipment Database: Could not find equipment.xml!"); - } - - xmlDocPtr doc = xmlParseMemory(data, size); - free(data); - - if (!doc) - { - logger->error("Equipment Database: Error while parsing equipment database (equipment.xml)!"); - } - - xmlNodePtr rootNode = xmlDocGetRootElement(doc); - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "equipments")) - { - logger->error("Equipment Database: equipment.xml is not a valid database file!"); - } - - //iterate s - for_each_xml_child_node(equipmentNode, rootNode) - { - if (!xmlStrEqual(equipmentNode->name, BAD_CAST "equipment")) - { - continue; - } - - EquipmentInfo *currentInfo = new EquipmentInfo(); - - currentInfo->setSlot (XML::getProperty(equipmentNode, "slot", 0)); - currentInfo->setAttackType (XML::getProperty(equipmentNode, "attacktype", "")); - - //iterate s and s - for_each_xml_child_node(spriteNode, equipmentNode) - { - if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite")) - { - std::string gender = XML::getProperty(spriteNode, "gender", "unisex"); - std::string filename = (const char*) spriteNode->xmlChildrenNode->content; - - if (gender == "male" || gender == "unisex") - { - currentInfo->setSprite(filename, 0); - } - - if (gender == "female" || gender == "unisex") - { - currentInfo->setSprite(filename, 1); - } - } - - if (xmlStrEqual(spriteNode->name, BAD_CAST "sound")) - { - std::string event = XML::getProperty(spriteNode, "event", ""); - const char *filename; - filename = (const char*) spriteNode->xmlChildrenNode->content; - - if (event == "hit") - { - currentInfo->addSound(EQUIP_EVENT_HIT, filename); - } - else if (event == "strike") - { - currentInfo->addSound(EQUIP_EVENT_STRIKE, filename); - } - else - { - logger->log("EquipmentDB: Warning, sound effect %s for unknown event %s", - filename, event.c_str()); - } - } - } - - setEquipment( XML::getProperty(equipmentNode, "id", 0), - currentInfo); - } - - mLoaded = true; -} - -void -EquipmentDB::unload() -{ - // kill EquipmentInfos - for_each(mEquipmentInfos.begin(), mEquipmentInfos.end(), - make_dtor(mEquipmentInfos)); - mEquipmentInfos.clear(); - - mLoaded = false; -} - -EquipmentInfo* -EquipmentDB::get(int id) -{ - if (!mLoaded) { - logger->error("Error: Equipment database used before initialization!"); - } - - EquipmentInfoIterator i = mEquipmentInfos.find(id); - - assert(i != mEquipmentInfos.end()); - - if (i == mEquipmentInfos.end()) - { - logger->log("EquipmentDB: Error, unknown equipment ID# %d", id); - return &mUnknown; - } - else - { - return i->second; - } -} - -void -EquipmentDB::setEquipment(int id, EquipmentInfo* equipmentInfo) -{ - if (mEquipmentInfos.find(id) != mEquipmentInfos.end()) { - logger->log("Warning: Equipment Piece with ID %d defined multiple times", - id); - delete equipmentInfo; - } - else { - mEquipmentInfos[id] = equipmentInfo; - }; -} diff --git a/src/resources/equipmentdb.h b/src/resources/equipmentdb.h deleted file mode 100644 index 76866961..00000000 --- a/src/resources/equipmentdb.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * The Mana World - * Copyright 2006 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 World 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 World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_EQUIPMENT_DB_H -#define _TMW_EQUIPMENT_DB_H - -#include - -#include "equipmentinfo.h" - -namespace EquipmentDB -{ - /** - * Loads the equipment info from Items.xml - */ - void load(); - - /** - * Frees equipment data - */ - void unload(); - - void setEquipment(int id, EquipmentInfo* equipmentInfo); - - EquipmentInfo* get(int id); - - // Equipment database types - typedef std::map EquipmentInfos; - typedef EquipmentInfos::iterator EquipmentInfoIterator; -} - -#endif diff --git a/src/resources/equipmentinfo.cpp b/src/resources/equipmentinfo.cpp deleted file mode 100644 index 9e1a03b9..00000000 --- a/src/resources/equipmentinfo.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The Mana World - * Copyright 2006 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 World 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 World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "equipmentinfo.h" - -void -EquipmentInfo::setAttackType(std::string attackType) -{ - if (attackType == "swing") - { - mAttackType = ACTION_ATTACK_SWING; - } - else if (attackType == "stab") - { - mAttackType = ACTION_ATTACK_STAB; - } - else if (attackType == "bow") - { - mAttackType = ACTION_ATTACK_BOW; - } - else if (attackType == "throw") - { - mAttackType = ACTION_ATTACK_THROW; - } - else if (attackType == "none") - { - mAttackType = ACTION_DEFAULT; - } - else - { - mAttackType = ACTION_ATTACK; - } -} - -void -EquipmentInfo::addSound (EquipmentSoundEvent event, std::string filename) -{ - if (mSounds.find(event) == mSounds.end()) - { - mSounds[event] = new std::vector; - } - - mSounds[event]->push_back("sfx/" + filename); -} - - -std::string -EquipmentInfo::getSound (EquipmentSoundEvent event) const -{ - std::map* >::const_iterator i; - - i = mSounds.find(event); - - if (i == mSounds.end()) - { - return ""; - } - else - { - return i->second->at(rand()%i->second->size()); - } -} diff --git a/src/resources/equipmentinfo.h b/src/resources/equipmentinfo.h deleted file mode 100644 index d9439c50..00000000 --- a/src/resources/equipmentinfo.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * The Mana World - * Copyright 2006 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 World 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 World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_EQUIPMENTINFO_H_ -#define _TMW_EQUIPMENTINFO_H_ - -#include -#include -#include - -#include "spritedef.h" - -enum EquipmentSoundEvent -{ - EQUIP_EVENT_STRIKE, - EQUIP_EVENT_HIT -}; - -class EquipmentInfo -{ - public: - EquipmentInfo(): - mSlot (0), - mAttackType(ACTION_DEFAULT) - { - } - - void - setSlot (int slot) { mSlot = slot; } - - const std::string& - getSprite(int gender) { return animationFiles[gender]; } - - void - setSprite(const std::string &animationFile, int gender) - { animationFiles[gender] = animationFile; } - - void - setAttackType(std::string attackType); - - const SpriteAction - getAttackType() { return mAttackType; } - - void - addSound(EquipmentSoundEvent event, std::string filename); - - std::string - getSound(EquipmentSoundEvent event) const; - - private: - int mSlot; //not used at the moment but maybe useful on our own server - SpriteAction mAttackType; - std::map animationFiles; - std::map* > mSounds; -}; - -#endif diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index 7f30ebe6..cfc485cb 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -1,149 +1,223 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 World 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 World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "itemdb.h" - -#include - -#include "iteminfo.h" -#include "resourcemanager.h" - -#include "../log.h" - -#include "../utils/dtor.h" -#include "../utils/xml.h" - -namespace -{ - ItemDB::ItemInfos mItemInfos; - ItemInfo mUnknown; - bool mLoaded = false; -} - - -void ItemDB::load() -{ - if (mLoaded) - return; - - logger->log("Initializing item database..."); - mUnknown.setName("Unknown item"); - - ResourceManager *resman = ResourceManager::getInstance(); - int size; - char *data = (char*)resman->loadFile("items.xml", size); - - if (!data) { - logger->error("ItemDB: Could not find items.xml!"); - } - - xmlDocPtr doc = xmlParseMemory(data, size); - free(data); - - if (!doc) - { - logger->error("ItemDB: Error while parsing item database (items.xml)!"); - } - - xmlNodePtr rootNode = xmlDocGetRootElement(doc); - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items")) - { - logger->error("ItemDB: items.xml is not a valid database file!"); - } - - for_each_xml_child_node(node, rootNode) - { - if (!xmlStrEqual(node->name, BAD_CAST "item")) { - continue; - } - - int id = XML::getProperty(node, "id", 0); - int art = XML::getProperty(node, "art", 0); - int type = XML::getProperty(node, "type", 0); - int weight = XML::getProperty(node, "weight", 0); - int slot = XML::getProperty(node, "slot", 0); - - std::string name = XML::getProperty(node, "name", ""); - std::string image = XML::getProperty(node, "image", ""); - std::string description = XML::getProperty(node, "description", ""); - std::string effect = XML::getProperty(node, "effect", ""); - - if (id && name != "") - { - ItemInfo *itemInfo = new ItemInfo(); - itemInfo->setImage(image); - itemInfo->setArt(art); - itemInfo->setName(name); - itemInfo->setDescription(description); - itemInfo->setEffect(effect); - itemInfo->setType(type); - itemInfo->setWeight(weight); - itemInfo->setSlot(slot); - mItemInfos[id] = itemInfo; - } - - if (id == 0) - { - logger->log("ItemDB: An item has no ID in items.xml!"); - } - -#define CHECK_PARAM(param, error_value) \ - if (param == error_value) \ - logger->log("ItemDB: Missing" #param " parameter for item %i! %s", \ - id, name.c_str()) - - CHECK_PARAM(name, ""); - CHECK_PARAM(image, ""); - // CHECK_PARAM(art, 0); - // CHECK_PARAM(description, ""); - // CHECK_PARAM(effect, ""); - // CHECK_PARAM(type, 0); - CHECK_PARAM(weight, 0); - // CHECK_PARAM(slot, 0); - -#undef CHECK_PARAM - } - - xmlFreeDoc(doc); - - mLoaded = true; -} - -void ItemDB::unload() -{ - for (ItemInfoIterator i = mItemInfos.begin(); i != mItemInfos.end(); i++) - { - delete i->second; - } - mItemInfos.clear(); - - mLoaded = false; -} - -const ItemInfo& -ItemDB::get(int id) -{ - ItemInfoIterator i = mItemInfos.find(id); - - return (i != mItemInfos.end()) ? *(i->second) : mUnknown; -} +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 World 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 World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include + +#include "itemdb.h" + +#include + +#include "iteminfo.h" +#include "resourcemanager.h" + +#include "../log.h" + +#include "../utils/dtor.h" +#include "../utils/xml.h" + +namespace +{ + ItemDB::ItemInfos mItemInfos; + ItemInfo *mUnknown; + bool mLoaded = false; +} + +// Forward declarations +static void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node); +static void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node); + +void ItemDB::load() +{ + if (mLoaded) + return; + + logger->log("Initializing item database..."); + + mUnknown = new ItemInfo(); + mUnknown->setName("Unknown item"); + mUnknown->setImage(""); + mUnknown->setSprite("error.xml", 0); + mUnknown->setSprite("error.xml", 1); + + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *data = (char*) resman->loadFile("items.xml", size); + + if (!data) { + logger->error("ItemDB: Could not find items.xml!"); + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + logger->error("ItemDB: Error while parsing item database (items.xml)!"); + } + + xmlNodePtr rootNode = xmlDocGetRootElement(doc); + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items")) + { + logger->error("ItemDB: items.xml is not a valid database file!"); + } + + for_each_xml_child_node(node, rootNode) + { + if (!xmlStrEqual(node->name, BAD_CAST "item")) + continue; + + int id = XML::getProperty(node, "id", 0); + + if (id == 0) + { + logger->log("ItemDB: Invalid or missing item ID in items.xml!"); + continue; + } + else if (mItemInfos.find(id) != mItemInfos.end()) + { + logger->log("ItemDB: Redefinition of item ID %d", id); + } + + int type = XML::getProperty(node, "type", 0); + int weight = XML::getProperty(node, "weight", 0); + int view = XML::getProperty(node, "view", 0); + int slot = XML::getProperty(node, "slot", 0); + + std::string name = XML::getProperty(node, "name", ""); + std::string image = XML::getProperty(node, "image", ""); + std::string description = XML::getProperty(node, "description", ""); + std::string effect = XML::getProperty(node, "effect", ""); + std::string attackType = XML::getProperty(node, "attacktype", ""); + + if (id && name != "") + { + ItemInfo *itemInfo = new ItemInfo(); + itemInfo->setImage(image); + itemInfo->setName(name); + itemInfo->setDescription(description); + itemInfo->setEffect(effect); + itemInfo->setType(type); + itemInfo->setView(view); + itemInfo->setWeight(weight); + itemInfo->setSlot(slot); + itemInfo->setAttackType(attackType); + + for_each_xml_child_node(itemChild, node) + { + if (xmlStrEqual(itemChild->name, BAD_CAST "sprite")) + { + loadSpriteRef(itemInfo, itemChild); + } + else if (xmlStrEqual(itemChild->name, BAD_CAST "sound")) + { + loadSoundRef(itemInfo, itemChild); + } + } + + mItemInfos[id] = itemInfo; + } + +#define CHECK_PARAM(param, error_value) \ + if (param == error_value) \ + logger->log("ItemDB: Missing " #param " attribute for item %i!",id) + + CHECK_PARAM(name, ""); + CHECK_PARAM(image, ""); + // CHECK_PARAM(description, ""); + // CHECK_PARAM(effect, ""); + // CHECK_PARAM(type, 0); + CHECK_PARAM(weight, 0); + // CHECK_PARAM(slot, 0); + +#undef CHECK_PARAM + } + + xmlFreeDoc(doc); + + mLoaded = true; +} + +void ItemDB::unload() +{ + logger->log("Unloading item database..."); + + delete mUnknown; + mUnknown = NULL; + + for_each(mItemInfos.begin(), mItemInfos.end(), make_dtor(mItemInfos)); + mItemInfos.clear(); + mLoaded = false; +} + +const ItemInfo& ItemDB::get(int id) +{ + assert(mLoaded); + + ItemInfoIterator i = mItemInfos.find(id); + + if (i == mItemInfos.end()) + { + logger->log("ItemDB: Error, unknown item ID# %d", id); + return *mUnknown; + } + else + { + return *(i->second); + } +} + +void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node) +{ + std::string gender = XML::getProperty(node, "gender", "unisex"); + std::string filename = (const char*) node->xmlChildrenNode->content; + + if (gender == "male" || gender == "unisex") + { + itemInfo->setSprite(filename, 0); + } + + if (gender == "female" || gender == "unisex") + { + itemInfo->setSprite(filename, 1); + } +} + +void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node) +{ + std::string event = XML::getProperty(node, "event", ""); + std::string filename = (const char*) node->xmlChildrenNode->content; + + if (event == "hit") + { + itemInfo->addSound(EQUIP_EVENT_HIT, filename); + } + else if (event == "strike") + { + itemInfo->addSound(EQUIP_EVENT_STRIKE, filename); + } + else + { + logger->log("ItemDB: Ignoring unknown sound event '%s'", + event.c_str()); + } +} diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index b09d1cc0..c2be5396 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -24,11 +24,11 @@ #include "resourcemanager.h" #include "image.h" - +#include "itemdb.h" ItemInfo::~ItemInfo() { - if (mImage != NULL) + if (mImage) { mImage->decRef(); } @@ -37,19 +37,87 @@ ItemInfo::~ItemInfo() void ItemInfo::setImage(const std::string &image) { + if (mImage) + { + mImage->decRef(); + } + + ResourceManager *resman = ResourceManager::getInstance(); mImageName = "graphics/items/" + image; + mImage = ResourceManager::getInstance()->getImage(mImageName); - if (mImageName != "") + if (!mImage) { - if (mImage != NULL) - { - mImage->decRef(); - } + mImage = resman->getImage("graphics/gui/unknown-item.png"); + } +} - mImage = ResourceManager::getInstance()->getImage(mImageName); +const std::string& +ItemInfo::getSprite(int gender) const +{ + if (mView) + { + // Forward the request to the item defining how to view this item + return ItemDB::get(mView).getSprite(gender); } else { - mImage = NULL; + static const std::string empty = ""; + std::map::const_iterator i = + mAnimationFiles.find(gender); + + return (i != mAnimationFiles.end()) ? i->second : empty; + } +} + +void +ItemInfo::setAttackType(const std::string &attackType) +{ + if (attackType == "swing") + { + mAttackType = ACTION_ATTACK_SWING; + } + else if (attackType == "stab") + { + mAttackType = ACTION_ATTACK_STAB; + } + else if (attackType == "bow") + { + mAttackType = ACTION_ATTACK_BOW; } + else if (attackType == "throw") + { + mAttackType = ACTION_ATTACK_THROW; + } + else if (attackType == "none") + { + mAttackType = ACTION_DEFAULT; + } + else + { + mAttackType = ACTION_ATTACK; + } +} + +void +ItemInfo::addSound(EquipmentSoundEvent event, const std::string &filename) +{ + if (mSounds.find(event) == mSounds.end()) + { + mSounds[event] = new std::vector; + } + + mSounds[event]->push_back("sfx/" + filename); +} + + +const std::string& +ItemInfo::getSound(EquipmentSoundEvent event) const +{ + static const std::string empty = ""; + std::map*>::const_iterator i; + i = mSounds.find(event); + + return (i == mSounds.end()) ? empty : + i->second->at(rand() % i->second->size()); } diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index e4f851bb..4fd1638e 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -24,12 +24,23 @@ #ifndef _TMW_ITEMINFO_H_ #define _TMW_ITEMINFO_H_ +#include #include +#include + +#include "spritedef.h" class Image; +enum EquipmentSoundEvent +{ + EQUIP_EVENT_STRIKE, + EQUIP_EVENT_HIT +}; + /** - * Defines a class for storing item infos. + * Defines a class for storing item infos. This includes information used when + * the item is equipped. */ class ItemInfo { @@ -40,10 +51,11 @@ class ItemInfo ItemInfo(): mImageName(""), mImage(NULL), - mArt(0), mType(0), mWeight(0), - mSlot(0) + mView(0), + mSlot(0), + mAttackType(ACTION_DEFAULT) { } @@ -52,73 +64,89 @@ class ItemInfo */ ~ItemInfo(); - void - setArt(short art) { mArt = art; } + void setName(const std::string &name) + { mName = name; } - short - getArt() const { return mArt; } + const std::string& getName() const + { return mName; } - void - setName(const std::string &name) { mName = name; } + void setImage(const std::string &image); - const std::string& - getName() const { return mName; } + Image* getImage() const + { return mImage; } - void - setImage(const std::string &image); + void setDescription(const std::string &description) + { mDescription = description; } - Image* - getImage() const { return mImage; } + const std::string& getDescription() const + { return mDescription; } - void - setDescription(const std::string &description) - { - mDescription = description; - } + void setEffect(const std::string &effect) + { mEffect = effect; } const std::string& - getDescription() const { return mDescription; } + getEffect() const { return mEffect; } - void - setEffect(const std::string &effect) { mEffect = effect; } + void setType(short type) + { mType = type; } - const std::string& - getEffect() const { return mEffect; } + short getType() const + { return mType; } + + void setWeight(short weight) + { mWeight = weight; } + + short getWeight() const + { return mWeight; } + + void setView(int view) + { mView = view; } + + void setSlot(char slot) + { mSlot = slot; } - void - setType(short type) { mType = type; } + char getSlot() const + { return mSlot; } - short - getType() const { return mType; } + void setSprite(const std::string &animationFile, int gender) + { mAnimationFiles[gender] = animationFile; } - void - setWeight(short weight) { mWeight = weight; } + const std::string& getSprite(int gender) const; - short - getWeight() const { return mWeight; } + void setAttackType(const std::string &attackType); - void - setSlot(char slot) { mSlot = slot; } + const SpriteAction getAttackType() const + { return mAttackType; } - char - getSlot() const { return mSlot; } + void addSound(EquipmentSoundEvent event, const std::string &filename); + + const std::string& getSound(EquipmentSoundEvent event) const; protected: - std::string mImageName; + std::string mImageName; /**< The filename of the icon image. */ /* TODO (BL): I do not think the item info should keep a reference to * the item icon. It would probably be better if this was kept in the * Item class, so that the images can be lazily instantiated and also * unloaded when no longer used. */ - Image *mImage; - short mArt; + Image *mImage; /**< The loaded icon image. */ std::string mName; - std::string mDescription; - std::string mEffect; - short mType; - short mWeight; - char mSlot; + std::string mDescription; /**< Short description. */ + std::string mEffect; /**< Description of effects. */ + short mType; /**< Item type (never used). */ + short mWeight; /**< Weight in grams. */ + int mView; /**< Item ID of how this item looks. */ + + // Equipment related members + char mSlot; /**< Equipment slot. */ + SpriteAction mAttackType; /**< Attack type, in case of weapon. */ + + /** Maps gender to sprite filenames. */ + std::map mAnimationFiles; + + /** Stores the names of sounds to be played at certain event. */ + std::map* > mSounds; }; #endif diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 260d5aa9..940ded36 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -156,7 +156,7 @@ MapReader::readMap(const std::string &filename) if (buffer == NULL) { - logger->log("Map file not found (%s)\n", filename.c_str()); + logger->log("Map file not found (%s)", filename.c_str()); return NULL; } diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h index 6d335b02..55d7f459 100644 --- a/src/resources/spritedef.h +++ b/src/resources/spritedef.h @@ -24,11 +24,11 @@ #ifndef _TMW_SPRITEDEF_H #define _TMW_SPRITEDEF_H -#include "resource.h" - #include #include +#include "resource.h" + #include class Action; -- cgit v1.2.3-70-g09d2