summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client.cpp14
-rw-r--r--src/equipment.h16
-rw-r--r--src/gui/equipmentwindow.cpp103
-rw-r--r--src/gui/equipmentwindow.h2
-rw-r--r--src/gui/itempopup.cpp80
-rw-r--r--src/gui/itempopup.h2
-rw-r--r--src/localplayer.cpp14
-rw-r--r--src/net/manaserv/attributes.cpp6
-rw-r--r--src/net/tmwa/generalhandler.cpp18
-rw-r--r--src/net/tmwa/inventoryhandler.cpp32
-rw-r--r--src/resources/itemdb.cpp568
-rw-r--r--src/resources/itemdb.h152
-rw-r--r--src/resources/iteminfo.h142
13 files changed, 729 insertions, 420 deletions
diff --git a/src/client.cpp b/src/client.cpp
index 7ca90444..71e0c5d3 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -789,7 +789,19 @@ int Client::exec()
// Load XML databases
ColorDB::load();
- itemDb = new ItemDB;
+ switch (Net::getNetworkType())
+ {
+ case ServerInfo::TMWATHENA:
+ itemDb = new TmwAthena::TaItemDB;
+ break;
+ case ServerInfo::MANASERV:
+ itemDb = new ManaServ::ManaServItemDB;
+ break;
+ default:
+ // Nothing
+ itemDb = 0;
+ break;
+ }
if (!itemDb || !itemDb->isLoaded())
{
// Warn and return to login screen
diff --git a/src/equipment.h b/src/equipment.h
index 6c099324..0aa10fb0 100644
--- a/src/equipment.h
+++ b/src/equipment.h
@@ -39,22 +39,6 @@ class Equipment
*/
~Equipment() { mBackend = 0; }
- enum Slot
- {
- EQUIP_TORSO_SLOT = 0,
- EQUIP_GLOVES_SLOT = 1,
- EQUIP_HEAD_SLOT = 2,
- EQUIP_LEGS_SLOT = 3,
- EQUIP_FEET_SLOT = 4,
- EQUIP_RING1_SLOT = 5,
- EQUIP_RING2_SLOT = 6,
- EQUIP_NECK_SLOT = 7,
- EQUIP_FIGHT1_SLOT = 8,
- EQUIP_FIGHT2_SLOT = 9,
- EQUIP_PROJECTILE_SLOT = 10,
- EQUIP_VECTOREND
- };
-
class Backend {
public:
virtual Item *getEquipment(int index) const = 0;
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index aeeaf223..d6c029c3 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -68,6 +68,7 @@ static const int boxPosition[][2] = {
EquipmentWindow::EquipmentWindow(Equipment *equipment):
Window(_("Equipment")),
mEquipment(equipment),
+ mEquipBox(0),
mSelected(-1)
{
mItemPopup = new ItemPopup;
@@ -93,15 +94,24 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment):
add(playerBox);
add(mUnequip);
- for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++)
+ // Load equipment boxes.
+ if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
- mEquipBox[i].posX = boxPosition[i][0] + getPadding();
- mEquipBox[i].posY = boxPosition[i][1] + getTitleBarHeight();
+ mEquipBox = new EquipBox[TmwAthena::EQUIP_VECTOR_END];
+
+ for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++)
+ {
+ mEquipBox[i].posX = boxPosition[i][0] + getPadding();
+ mEquipBox[i].posY = boxPosition[i][1] + getTitleBarHeight();
+ }
}
}
EquipmentWindow::~EquipmentWindow()
{
+ if (Net::getNetworkType() == ServerInfo::TMWATHENA)
+ delete[] mEquipBox;
+
delete mItemPopup;
}
@@ -114,40 +124,43 @@ void EquipmentWindow::draw(gcn::Graphics *graphics)
Window::drawChildren(graphics);
- for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++)
+ if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
- if (i == mSelected)
+ for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++)
{
- const gcn::Color color = Theme::getThemeColor(Theme::HIGHLIGHT);
+ if (i == mSelected)
+ {
+ const gcn::Color color = Theme::getThemeColor(Theme::HIGHLIGHT);
- // Set color to the highlight color
- g->setColor(gcn::Color(color.r, color.g, color.b, getGuiAlpha()));
- g->fillRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY,
- BOX_WIDTH, BOX_HEIGHT));
- }
+ // Set color to the highlight color
+ g->setColor(gcn::Color(color.r, color.g, color.b, getGuiAlpha()));
+ g->fillRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT));
+ }
- // Set color black
- g->setColor(gcn::Color(0, 0, 0));
- // Draw box border
- g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY,
- BOX_WIDTH, BOX_HEIGHT));
+ // Set color black
+ g->setColor(gcn::Color(0, 0, 0));
+ // Draw box border
+ g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT));
- Item *item = mEquipment->getEquipment(i);
- if (item)
- {
- // Draw Item.
- Image *image = item->getImage();
- image->setAlpha(1.0f); // Ensure the image is drawn with maximum opacity
- g->drawImage(image,
- mEquipBox[i].posX + 2,
- mEquipBox[i].posY + 2);
- if (i == EQUIP_PROJECTILE_SLOT)
+ Item *item = mEquipment->getEquipment(i);
+ if (item)
{
- g->setColor(Theme::getThemeColor(Theme::TEXT));
- graphics->drawText(toString(item->getQuantity()),
- mEquipBox[i].posX + (BOX_WIDTH / 2),
- mEquipBox[i].posY - getFont()->getHeight(),
- gcn::Graphics::CENTER);
+ // Draw Item.
+ Image *image = item->getImage();
+ image->setAlpha(1.0f); // Ensure the image is drawn with maximum opacity
+ g->drawImage(image,
+ mEquipBox[i].posX + 2,
+ mEquipBox[i].posY + 2);
+ if (i == TmwAthena::EQUIP_PROJECTILE_SLOT)
+ {
+ g->setColor(Theme::getThemeColor(Theme::TEXT));
+ graphics->drawText(toString(item->getQuantity()),
+ mEquipBox[i].posX + (BOX_WIDTH / 2),
+ mEquipBox[i].posY - getFont()->getHeight(),
+ gcn::Graphics::CENTER);
+ }
}
}
}
@@ -165,14 +178,15 @@ void EquipmentWindow::action(const gcn::ActionEvent &event)
Item *EquipmentWindow::getItem(int x, int y) const
{
- for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++)
+ if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
- gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
- BOX_WIDTH, BOX_HEIGHT);
-
- if (tRect.isPointInRect(x, y))
+ for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++)
{
- return mEquipment->getEquipment(i);
+ gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT);
+
+ if (tRect.isPointInRect(x, y))
+ return mEquipment->getEquipment(i);
}
}
return NULL;
@@ -188,14 +202,17 @@ void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent)
if (mouseEvent.getButton() == gcn::MouseEvent::LEFT)
{
// Checks if any of the presses were in the equip boxes.
- for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++)
+ if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
- Item *item = mEquipment->getEquipment(i);
- gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
- BOX_WIDTH, BOX_HEIGHT);
+ for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++)
+ {
+ Item *item = mEquipment->getEquipment(i);
+ gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT);
- if (tRect.isPointInRect(x, y) && item)
- setSelected(i);
+ if (tRect.isPointInRect(x, y) && item)
+ setSelected(i);
+ }
}
}
else if (mouseEvent.getButton() == gcn::MouseEvent::RIGHT)
diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h
index dcb3523d..a76fa689 100644
--- a/src/gui/equipmentwindow.h
+++ b/src/gui/equipmentwindow.h
@@ -78,7 +78,7 @@ class EquipmentWindow : public Window, public gcn::ActionListener
int posY;
};
- EquipBox mEquipBox[Equipment::EQUIP_VECTOREND]; /**< Equipment Boxes. */
+ EquipBox *mEquipBox; /**< Equipment Boxes. */
ItemPopup *mItemPopup;
gcn::Button *mUnequip;
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index 9b2df34d..60943756 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -34,6 +34,8 @@
#include "utils/gettext.h"
#include "utils/stringutils.h"
+#include "net/net.h"
+
#include "resources/image.h"
#include "resources/resourcemanager.h"
#include "resources/theme.h"
@@ -42,6 +44,43 @@
#include <guichan/widgets/label.hpp>
+#define ITEMPOPUP_WRAP_WIDTH 196
+
+static gcn::Color getColorFromItemType(ItemType type)
+{
+ switch (type)
+ {
+ case ITEM_UNUSABLE:
+ return Theme::getThemeColor(Theme::GENERIC);
+ case ITEM_USABLE:
+ return Theme::getThemeColor(Theme::USABLE);
+ case ITEM_EQUIPMENT_ONE_HAND_WEAPON:
+ return Theme::getThemeColor(Theme::ONEHAND);
+ case ITEM_EQUIPMENT_TWO_HANDS_WEAPON:
+ return Theme::getThemeColor(Theme::TWOHAND);
+ case ITEM_EQUIPMENT_TORSO:
+ return Theme::getThemeColor(Theme::TORSO);
+ case ITEM_EQUIPMENT_ARMS:
+ return Theme::getThemeColor(Theme::ARMS);
+ case ITEM_EQUIPMENT_HEAD:
+ return Theme::getThemeColor(Theme::HEAD);
+ case ITEM_EQUIPMENT_LEGS:
+ return Theme::getThemeColor(Theme::LEGS);
+ case ITEM_EQUIPMENT_SHIELD:
+ return Theme::getThemeColor(Theme::SHIELD);
+ case ITEM_EQUIPMENT_RING:
+ return Theme::getThemeColor(Theme::RING);
+ case ITEM_EQUIPMENT_NECKLACE:
+ return Theme::getThemeColor(Theme::NECKLACE);
+ case ITEM_EQUIPMENT_FEET:
+ return Theme::getThemeColor(Theme::FEET);
+ case ITEM_EQUIPMENT_AMMO:
+ return Theme::getThemeColor(Theme::AMMO);
+ default:
+ return Theme::getThemeColor(Theme::UNKNOWN_ITEM);
+ }
+}
+
ItemPopup::ItemPopup():
Popup("ItemPopup"),
mIcon(0)
@@ -116,15 +155,13 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage)
mIcon->setImage(0);
}
- //mItemType = item.getType();
+ mItemType = item.getItemType();
mItemName->setCaption(item.getName());
mItemName->adjustSize();
- mItemName->setForegroundColor(Theme::UNKNOWN_ITEM); // TODO
+ mItemName->setForegroundColor(getColorFromItemType(mItemType));
mItemName->setPosition(getPadding() + space, getPadding());
-#define ITEMPOPUP_WRAP_WIDTH 196
-
mItemDesc->setTextWrapped(item.getDescription(), ITEMPOPUP_WRAP_WIDTH);
{
const std::vector<std::string> &effect = item.getEffect();
@@ -183,41 +220,6 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage)
(numRowsDesc + 1) * fontHeight);
}
-gcn::Color ItemPopup::getColor(ItemType type)
-{
- switch (type)
- {
- case ITEM_UNUSABLE:
- return Theme::getThemeColor(Theme::GENERIC);
- case ITEM_USABLE:
- return Theme::getThemeColor(Theme::USABLE);
- case ITEM_EQUIPMENT_ONE_HAND_WEAPON:
- return Theme::getThemeColor(Theme::ONEHAND);
- case ITEM_EQUIPMENT_TWO_HANDS_WEAPON:
- return Theme::getThemeColor(Theme::TWOHAND);
- case ITEM_EQUIPMENT_TORSO:
- return Theme::getThemeColor(Theme::TORSO);
- case ITEM_EQUIPMENT_ARMS:
- return Theme::getThemeColor(Theme::ARMS);
- case ITEM_EQUIPMENT_HEAD:
- return Theme::getThemeColor(Theme::HEAD);
- case ITEM_EQUIPMENT_LEGS:
- return Theme::getThemeColor(Theme::LEGS);
- case ITEM_EQUIPMENT_SHIELD:
- return Theme::getThemeColor(Theme::SHIELD);
- case ITEM_EQUIPMENT_RING:
- return Theme::getThemeColor(Theme::RING);
- case ITEM_EQUIPMENT_NECKLACE:
- return Theme::getThemeColor(Theme::NECKLACE);
- case ITEM_EQUIPMENT_FEET:
- return Theme::getThemeColor(Theme::FEET);
- case ITEM_EQUIPMENT_AMMO:
- return Theme::getThemeColor(Theme::AMMO);
- default:
- return Theme::getThemeColor(Theme::UNKNOWN_ITEM);
- }
-}
-
void ItemPopup::mouseMoved(gcn::MouseEvent &event)
{
Popup::mouseMoved(event);
diff --git a/src/gui/itempopup.h b/src/gui/itempopup.h
index a3976a11..f054ddf5 100644
--- a/src/gui/itempopup.h
+++ b/src/gui/itempopup.h
@@ -62,8 +62,6 @@ class ItemPopup : public Popup
TextBox *mItemWeight;
ItemType mItemType;
Icon *mIcon;
-
- static gcn::Color getColor(ItemType type);
};
#endif // ITEMPOPUP_H
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 7d427b82..81fb1cee 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -1020,12 +1020,16 @@ int LocalPlayer::getAttackRange()
}
else
{
- // TODO: Fix this to be more generic
- Item *weapon = PlayerInfo::getEquipment(EQUIP_FIGHT1_SLOT);
- if (weapon)
+ if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
- const ItemInfo info = weapon->getInfo();
- return info.getAttackRange();
+ // TODO: Fix this to be more generic
+ Item *weapon = PlayerInfo::getEquipment(
+ TmwAthena::EQUIP_FIGHT1_SLOT);
+ if (weapon)
+ {
+ const ItemInfo info = weapon->getInfo();
+ return info.getAttackRange();
+ }
}
return 48; // unarmed range
}
diff --git a/src/net/manaserv/attributes.cpp b/src/net/manaserv/attributes.cpp
index a65dc01f..e57c6278 100644
--- a/src/net/manaserv/attributes.cpp
+++ b/src/net/manaserv/attributes.cpp
@@ -377,14 +377,14 @@ namespace Attributes {
void informItemDB()
{
- std::list<ItemDB::Stat> dbStats;
+ std::list<ItemStat> dbStats;
TagMap::const_iterator it, it_end;
for (it = tags.begin(), it_end = tags.end(); it != it_end; ++it)
- dbStats.push_back(ItemDB::Stat(it->first,
+ dbStats.push_back(ItemStat(it->first,
it->second));
- itemDb->setStatsList(dbStats);
+ setStatsList(dbStats);
}
void informStatusWindow()
diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp
index b4327d47..1935ad72 100644
--- a/src/net/tmwa/generalhandler.cpp
+++ b/src/net/tmwa/generalhandler.cpp
@@ -98,15 +98,15 @@ GeneralHandler::GeneralHandler():
handledMessages = _messages;
generalHandler = this;
- std::list<ItemDB::Stat> stats;
- stats.push_back(ItemDB::Stat("str", _("Strength %+d")));
- stats.push_back(ItemDB::Stat("agi", _("Agility %+d")));
- stats.push_back(ItemDB::Stat("vit", _("Vitality %+d")));
- stats.push_back(ItemDB::Stat("int", _("Intelligence %+d")));
- stats.push_back(ItemDB::Stat("dex", _("Dexterity %+d")));
- stats.push_back(ItemDB::Stat("luck", _("Luck %+d")));
-
- itemDb->setStatsList(stats);
+ std::list<ItemStat> stats;
+ stats.push_back(ItemStat("str", _("Strength %+d")));
+ stats.push_back(ItemStat("agi", _("Agility %+d")));
+ stats.push_back(ItemStat("vit", _("Vitality %+d")));
+ stats.push_back(ItemStat("int", _("Intelligence %+d")));
+ stats.push_back(ItemStat("dex", _("Dexterity %+d")));
+ stats.push_back(ItemStat("luck", _("Luck %+d")));
+
+ setStatsList(stats);
listen(CHANNEL_GAME);
}
diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp
index 3a0a93e3..4aedd9f2 100644
--- a/src/net/tmwa/inventoryhandler.cpp
+++ b/src/net/tmwa/inventoryhandler.cpp
@@ -46,30 +46,30 @@
extern Net::InventoryHandler *inventoryHandler;
-const Equipment::Slot EQUIP_POINTS[Equipment::EQUIP_VECTOREND] = {
- Equipment::EQUIP_LEGS_SLOT,
- Equipment::EQUIP_FIGHT1_SLOT,
- Equipment::EQUIP_GLOVES_SLOT,
- Equipment::EQUIP_RING2_SLOT,
- Equipment::EQUIP_RING1_SLOT,
- Equipment::EQUIP_FIGHT2_SLOT,
- Equipment::EQUIP_FEET_SLOT,
- Equipment::EQUIP_NECK_SLOT,
- Equipment::EQUIP_HEAD_SLOT,
- Equipment::EQUIP_TORSO_SLOT,
- Equipment::EQUIP_PROJECTILE_SLOT};
-
namespace TmwAthena {
+const EquipmentSlot EQUIP_POINTS[EQUIP_VECTOR_END] = {
+ EQUIP_LEGS_SLOT,
+ EQUIP_FIGHT1_SLOT,
+ EQUIP_ARMS_SLOT,
+ EQUIP_RING2_SLOT,
+ EQUIP_RING1_SLOT,
+ EQUIP_FIGHT2_SLOT,
+ EQUIP_FEET_SLOT,
+ EQUIP_NECKLACE_SLOT,
+ EQUIP_HEAD_SLOT,
+ EQUIP_TORSO_SLOT,
+ EQUIP_PROJECTILE_SLOT};
+
int getSlot(int eAthenaSlot)
{
if (eAthenaSlot == 0)
{
- return Equipment::EQUIP_VECTOREND;
+ return EQUIP_VECTOR_END;
}
if (eAthenaSlot & 0x8000)
- return Equipment::EQUIP_PROJECTILE_SLOT;
+ return EQUIP_PROJECTILE_SLOT;
int mask = 1;
int position = 0;
@@ -425,7 +425,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
index -= INVENTORY_OFFSET;
logger->log("Arrows equipped: %i", index);
- mEquips.setEquipment(Equipment::EQUIP_PROJECTILE_SLOT, index);
+ mEquips.setEquipment(EQUIP_PROJECTILE_SLOT, index);
break;
}
}
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 435cdf96..2271abef 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -38,18 +38,7 @@
#include <cassert>
-// Forward declarations
-static char const *const fields[][2] =
-{
- { "attack", N_("Attack %+d") },
- { "defense", N_("Defense %+d") },
- { "hp", N_("HP %+d") },
- { "mp", N_("MP %+d") }
-};
-
-static std::list<ItemDB::Stat> extraStats;
-
-void ItemDB::setStatsList(const std::list<Stat> &stats)
+void setStatsList(const std::list<ItemStat> &stats)
{
extraStats = stats;
}
@@ -75,47 +64,136 @@ static ItemType itemTypeFromString(const std::string &name, int id = 0)
else return ITEM_UNUSABLE;
}
-void ItemDB::load()
+/*
+ * Common itemDB functions
+ */
+
+bool ItemDB::exists(int id)
{
- if (mLoaded)
- unload();
+ assert(mLoaded);
- logger->log("Initializing item database...");
+ ItemInfos::const_iterator i = mItemInfos.find(id);
- mUnknown = new ItemInfo;
- mUnknown->mName = _("Unknown item");
- mUnknown->mDisplay = SpriteDisplay();
- std::string errFile = paths.getStringValue("spriteErrorFile");
- mUnknown->setSprite(errFile, GENDER_MALE);
- mUnknown->setSprite(errFile, GENDER_FEMALE);
+ return i != mItemInfos.end();
+}
- XML::Document doc(ITEMS_DB_FILE);
- xmlNodePtr rootNode = doc.rootNode();
+const ItemInfo &ItemDB::get(int id)
+{
+ assert(mLoaded);
- if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items"))
+ ItemInfos::const_iterator i = mItemInfos.find(id);
+
+ if (i == mItemInfos.end())
{
- logger->log("ItemDB: Error while loading " ITEMS_DB_FILE "!");
- return;
+ logger->log("ItemDB: Warning, unknown item ID# %d", id);
+ return *mUnknown;
}
- for_each_xml_child_node(node, rootNode)
+ return *(i->second);
+}
+
+const ItemInfo &ItemDB::get(const std::string &name)
+{
+ assert(mLoaded);
+
+ NamedItemInfos::const_iterator i = mNamedItemInfos.find(normalize(name));
+
+ if (i == mNamedItemInfos.end())
+ {
+ if (!name.empty())
+ {
+ logger->log("ItemDB: Warning, unknown item name \"%s\"",
+ name.c_str());
+ }
+ return *mUnknown;
+ }
+
+ return *(i->second);
+}
+
+void ItemDB::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, GENDER_MALE);
+ }
+ if (gender == "female" || gender == "unisex")
+ {
+ itemInfo->setSprite(filename, GENDER_FEMALE);
+ }
+}
+
+void ItemDB::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());
+ }
+}
+
+void ItemDB::loadFloorSprite(SpriteDisplay *display, xmlNodePtr floorNode)
+{
+ for_each_xml_child_node(spriteNode, floorNode)
+ {
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
+ {
+ SpriteReference *currentSprite = new SpriteReference;
+ currentSprite->sprite = (const char*)spriteNode->xmlChildrenNode->content;
+ currentSprite->variant = XML::getProperty(spriteNode, "variant", 0);
+ display->sprites.push_back(currentSprite);
+ }
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
+ {
+ std::string particlefx = (const char*)spriteNode->xmlChildrenNode->content;
+ display->particles.push_back(particlefx);
+ }
+ }
+}
+
+void ItemDB::unload()
+{
+ logger->log("Unloading item database...");
+
+ delete mUnknown;
+ mUnknown = NULL;
+
+ delete_all(mItemInfos);
+ mItemInfos.clear();
+ mNamedItemInfos.clear();
+ mLoaded = false;
+}
+
+void ItemDB::loadCommonRef(ItemInfo *itemInfo, xmlNodePtr node)
+{
if (!xmlStrEqual(node->name, BAD_CAST "item"))
- continue;
+ return;
int id = XML::getProperty(node, "id", 0);
if (!id)
{
- logger->log("ItemDB: Invalid or missing item ID in "
+ logger->log("ItemDB: Invalid or missing item Id in "
ITEMS_DB_FILE "!");
- continue;
+ return;
}
else if (mItemInfos.find(id) != mItemInfos.end())
- logger->log("ItemDB: Redefinition of item ID %d", id);
+ logger->log("ItemDB: Redefinition of item Id %d", id);
- std::string typeStr = XML::getProperty(node, "type", "other");
- int weight = XML::getProperty(node, "weight", 0);
int view = XML::getProperty(node, "view", 0);
std::string name = XML::getProperty(node, "name", "");
@@ -125,42 +203,26 @@ void ItemDB::load()
int attackRange = XML::getProperty(node, "attack-range", 0);
std::string missileParticle = XML::getProperty(node, "missile-particle", "");
+ // Load Ta Item Type
+ std::string typeStr = XML::getProperty(node, "type", "other");
+ itemInfo->mType = itemTypeFromString(typeStr);
+
+ int weight = XML::getProperty(node, "weight", 0);
+ itemInfo->mWeight = weight > 0 ? weight : 0;
+
SpriteDisplay display;
display.image = image;
- ItemInfo *itemInfo = new ItemInfo;
itemInfo->mId = id;
- itemInfo->mName = name.empty() ? _("unnamed") : name;
+ itemInfo->mName = name;
itemInfo->mDescription = description;
- itemInfo->mType = itemTypeFromString(typeStr);
- itemInfo->mActivatable = itemInfo->mType == ITEM_USABLE;
- // Everything not unusable or usable is equippable by the old type system.
- itemInfo->mEquippable = itemInfo->mType != ITEM_UNUSABLE
- && itemInfo->mType != ITEM_USABLE;
itemInfo->mView = view;
itemInfo->mWeight = weight;
itemInfo->setAttackAction(attackAction);
itemInfo->mAttackRange = attackRange;
itemInfo->setMissileParticle(missileParticle);
- std::vector<std::string> effect;
- for (int i = 0; i < int(sizeof(fields) / sizeof(fields[0])); ++i)
- {
- int value = XML::getProperty(node, fields[i][0], 0);
- if (!value) continue;
- effect.push_back(strprintf(gettext(fields[i][1]), value));
- }
- for (std::list<Stat>::iterator it = extraStats.begin();
- it != extraStats.end(); it++)
- {
- int value = XML::getProperty(node, it->tag.c_str(), 0);
- if (!value) continue;
- effect.push_back(strprintf(it->format.c_str(), value));
- }
- std::string temp = XML::getProperty(node, "effect", "");
- if (!temp.empty())
- effect.push_back(temp);
-
+ // Load <sprite>, <sound>, and <floor>
for_each_xml_child_node(itemChild, node)
{
if (xmlStrEqual(itemChild->name, BAD_CAST "sprite"))
@@ -179,13 +241,209 @@ void ItemDB::load()
{
loadFloorSprite(&display, itemChild);
}
- /*
- * Begin new item definition code. Previous code is left in to
- * maintain backwards compatibility.
- * Exit here if tmwAthena.
- */
- else if (Net::getNetworkType() == ServerInfo::TMWATHENA);
- else if (xmlStrEqual(itemChild->name, BAD_CAST "equip"))
+
+ }
+
+ // If the item has got a floor image, we bind the good reference.
+ itemInfo->mDisplay = display;
+}
+
+void ItemDB::addItem(ItemInfo *itemInfo)
+{
+ std::string itemName = itemInfo->mName;
+ itemInfo->mName = itemName.empty() ? _("unnamed") : itemName;
+ mItemInfos[itemInfo->mId] = itemInfo;
+ if (!itemName.empty())
+ {
+ std::string temp = normalize(itemName);
+
+ NamedItemInfos::const_iterator itr = mNamedItemInfos.find(temp);
+ if (itr == mNamedItemInfos.end())
+ mNamedItemInfos[temp] = itemInfo;
+ else
+ logger->log("ItemDB: Duplicate name (%s) for item id %d found.",
+ temp.c_str(), itemInfo->mId);
+
+ }
+}
+
+template <class T>
+static void checkParameter(int id, const T param, const T errorValue)
+{
+ if (param == errorValue)
+ {
+ std::stringstream errMsg;
+ errMsg << "ItemDB: Missing " << param << " attribute for item id "
+ << id << "!";
+ logger->log(errMsg.str().c_str());
+ }
+}
+
+void ItemDB::checkItemInfo(ItemInfo* itemInfo)
+{
+ int id = itemInfo->mId;
+ if (!itemInfo->getAttackAction().empty())
+ if (itemInfo->mAttackRange == 0)
+ logger->log("ItemDB: Missing attack range from weapon %i!", id);
+
+ if (id >= 0)
+ {
+ checkParameter(id, itemInfo->mName, std::string(""));
+ checkParameter(id, itemInfo->mDescription, std::string(""));
+ checkParameter(id, itemInfo->mDisplay.image, std::string(""));
+ checkParameter(id, itemInfo->mWeight, 0);
+ }
+}
+
+namespace TmwAthena {
+
+// Description fields used by TaItemDB *itemInfo->mEffect.
+
+static char const *const fields[][2] =
+{
+ { "attack", N_("Attack %+d") },
+ { "defense", N_("Defense %+d") },
+ { "hp", N_("HP %+d") },
+ { "mp", N_("MP %+d") }
+};
+
+void TaItemDB::load()
+{
+ if (mLoaded)
+ unload();
+
+ logger->log("Initializing TmwAthena item database...");
+
+ mUnknown = new TaItemInfo;
+ mUnknown->mName = _("Unknown item");
+ mUnknown->mDisplay = SpriteDisplay();
+ std::string errFile = paths.getStringValue("spriteErrorFile");
+ mUnknown->setSprite(errFile, GENDER_MALE);
+ mUnknown->setSprite(errFile, GENDER_FEMALE);
+
+ XML::Document doc(ITEMS_DB_FILE);
+ xmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items"))
+ {
+ logger->error("ItemDB: Error while loading " ITEMS_DB_FILE "!");
+ return;
+ }
+
+ for_each_xml_child_node(node, rootNode)
+ {
+ TaItemInfo *itemInfo = new TaItemInfo;
+
+ loadCommonRef(itemInfo, node);
+
+ // Everything not unusable or usable is equippable by the Ta type system.
+ itemInfo->mEquippable = itemInfo->mType != ITEM_UNUSABLE
+ && itemInfo->mType != ITEM_USABLE;
+
+ // Load nano description
+ std::vector<std::string> effect;
+ for (int i = 0; i < int(sizeof(fields) / sizeof(fields[0])); ++i)
+ {
+ int value = XML::getProperty(node, fields[i][0], 0);
+ if (!value)
+ continue;
+ effect.push_back(strprintf(gettext(fields[i][1]), value));
+ }
+ for (std::list<ItemStat>::iterator it = extraStats.begin();
+ it != extraStats.end(); it++)
+ {
+ int value = XML::getProperty(node, it->mTag.c_str(), 0);
+ if (!value)
+ continue;
+ effect.push_back(strprintf(it->mFormat.c_str(), value));
+ }
+ std::string temp = XML::getProperty(node, "effect", "");
+ if (!temp.empty())
+ effect.push_back(temp);
+
+ itemInfo->mEffect = effect;
+
+ checkItemInfo(itemInfo);
+
+ addItem(itemInfo);
+ }
+
+ checkHairWeaponsRacesSpecialIds();
+
+ mLoaded = true;
+}
+
+void TaItemDB::checkItemInfo(ItemInfo* itemInfo)
+{
+ ItemDB::checkItemInfo(itemInfo);
+
+ // Check for unusable items?
+ //checkParameter(id, itemInfo->mType, 0);
+}
+
+}; // namespace TmwAthena
+
+namespace ManaServ {
+
+static std::map<std::string, const char* > triggerTable;
+
+static void initTriggerTable()
+{
+ if (triggerTable.empty())
+ {
+ // FIXME: This should ideally be softcoded via XML or similar.
+ logger->log("Initializing ManaServ trigger table...");
+ triggerTable["existence"] = " when it is in the inventory";
+ triggerTable["activation"] = " upon activation";
+ triggerTable["equip"] = " upon successful equip";
+ triggerTable["leave-inventory"] = " when it leaves the inventory";
+ triggerTable["unequip"] = " when it is unequipped";
+ triggerTable["equip-change"] = " when it changes the way it is equipped";
+ }
+}
+
+void ManaServItemDB::load()
+{
+ if (mLoaded)
+ unload();
+
+ // Initialize the trigger table for effect descriptions
+ initTriggerTable();
+
+ logger->log("Initializing ManaServ item database...");
+
+ mUnknown = new ManaServItemInfo;
+ mUnknown->mName = _("Unknown item");
+ mUnknown->mDisplay = SpriteDisplay();
+ std::string errFile = paths.getStringValue("spriteErrorFile");
+ mUnknown->setSprite(errFile, GENDER_MALE);
+ mUnknown->setSprite(errFile, GENDER_FEMALE);
+
+ XML::Document doc(ITEMS_DB_FILE);
+ xmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items"))
+ {
+ logger->log("ItemDB: Error while loading " ITEMS_DB_FILE "!");
+ return;
+ }
+
+ for_each_xml_child_node(node, rootNode)
+ {
+ ManaServItemInfo *itemInfo = new ManaServItemInfo;
+
+ loadCommonRef(itemInfo, node);
+
+ // We default eqippable and activatable to false as their actual value will be set
+ // within the <equip> and <effect> sub-nodes..
+ itemInfo->mActivatable = false;
+ itemInfo->mEquippable = false;
+
+ // Load <equip>, and <effect> sub nodes.
+ std::vector<std::string> effect;
+ for_each_xml_child_node(itemChild, node)
+ {
+ if (xmlStrEqual(itemChild->name, BAD_CAST "equip"))
{
// The fact that there is a way to equip is enough.
// Discard any details, but mark the item as equippable.
@@ -195,7 +453,8 @@ void ItemDB::load()
{
std::string trigger = XML::getProperty(
itemChild, "trigger", "");
- if (trigger.empty()) {
+ if (trigger.empty())
+ {
logger->log("Found empty trigger effect label, skipping.");
continue;
}
@@ -203,22 +462,12 @@ void ItemDB::load()
if (trigger == "activation")
itemInfo->mActivatable = true;
- static std::map<std::string, const char* > triggerTable;
- if (triggerTable.empty())
- {
- // FIXME: This should ideally be softcoded via XML or similar.
- triggerTable["existence"] = " when it is in the inventory";
- triggerTable["activation"] = " upon activation";
- triggerTable["equip"] = " upon successful equip";
- triggerTable["leave-inventory"] = " when it leaves the inventory";
- triggerTable["unequip"] = " when it is unequipped";
- triggerTable["equip-change"] = " when it changes the way it is equipped";
- }
std::map<std::string, const char* >::const_iterator triggerLabel =
triggerTable.find(trigger);
if (triggerLabel == triggerTable.end())
{
- logger->log("Warning: unknown trigger %s in item %d!", trigger.c_str(), id);
+ logger->log("Warning: unknown trigger %s in item %d!",
+ trigger.c_str(), itemInfo->mId);
continue;
}
@@ -237,7 +486,7 @@ void ItemDB::load()
logger->log("Warning: incomplete modifier definition, skipping.");
continue;
}
- std::list<Stat>::const_iterator
+ std::list<ItemStat>::const_iterator
it = extraStats.begin(),
it_end = extraStats.end();
while (it != it_end && !(*it == attribute))
@@ -251,7 +500,7 @@ void ItemDB::load()
strprintf(strprintf(
duration ?
strprintf("%%s%%s. This effect lasts %d ticks.", duration).c_str()
- : "%s%s.", it->format.c_str(), triggerLabel->second).c_str(), value));
+ : "%s%s.", it->mFormat.c_str(), triggerLabel->second).c_str(), value));
}
else if (xmlStrEqual(effectChild->name, BAD_CAST "modifier"))
effect.push_back(strprintf("Provides an autoattack%s.",
@@ -264,159 +513,30 @@ void ItemDB::load()
(const char*)effectChild->xmlChildrenNode->content);
}
}
- }
+ // Set Item Type based on subnodes info
+ // TODO: Improve it once the itemTypes are loaded through xml
+ itemInfo->mType = ITEM_UNUSABLE;
+ if (itemInfo->mActivatable)
+ itemInfo->mType = ITEM_USABLE;
+ else if (itemInfo->mEquippable)
+ itemInfo->mType = ITEM_EQUIPMENT_TORSO;
+ } // end for_each_xml_child_node(itemChild, node)
itemInfo->mEffect = effect;
- itemInfo->mDisplay = display;
-
- mItemInfos[id] = itemInfo;
- if (!name.empty())
- {
- std::string temp = normalize(name);
-
- NamedItemInfos::const_iterator itr = mNamedItemInfos.find(temp);
- if (itr == mNamedItemInfos.end())
- {
- mNamedItemInfos[temp] = itemInfo;
- }
- else
- {
- logger->log("ItemDB: Duplicate name of item found item %d", id);
- }
- }
-
- if (!attackAction.empty())
- if (attackRange == 0)
- logger->log("ItemDB: Missing attack range from weapon %i!", id);
-
-#define CHECK_PARAM(param, error_value) \
- if (param == error_value) \
- logger->log("ItemDB: Missing " #param " attribute for item %i!",id)
-
- if (id >= 0)
- {
- CHECK_PARAM(name, "");
- CHECK_PARAM(description, "");
- CHECK_PARAM(image, "");
- }
- // CHECK_PARAM(effect, "");
- // CHECK_PARAM(type, 0);
- // CHECK_PARAM(weight, 0);
- // CHECK_PARAM(slot, 0);
+ checkItemInfo(itemInfo);
-#undef CHECK_PARAM
+ addItem(itemInfo);
}
mLoaded = true;
}
-void ItemDB::unload()
-{
- logger->log("Unloading item database...");
-
- delete mUnknown;
- mUnknown = NULL;
-
- delete_all(mItemInfos);
- mItemInfos.clear();
- mNamedItemInfos.clear();
- mLoaded = false;
-}
-
-bool ItemDB::exists(int id)
-{
- assert(mLoaded);
-
- ItemInfos::const_iterator i = mItemInfos.find(id);
-
- return i != mItemInfos.end();
-}
-
-const ItemInfo &ItemDB::get(int id)
-{
- assert(mLoaded);
-
- ItemInfos::const_iterator i = mItemInfos.find(id);
-
- if (i == mItemInfos.end())
- {
- logger->log("ItemDB: Warning, unknown item ID# %d", id);
- return *mUnknown;
- }
-
- return *(i->second);
-}
-
-const ItemInfo &ItemDB::get(const std::string &name)
+void ManaServItemDB::checkItemInfo(ItemInfo* itemInfo)
{
- assert(mLoaded);
-
- NamedItemInfos::const_iterator i = mNamedItemInfos.find(normalize(name));
+ ItemDB::checkItemInfo(itemInfo);
- if (i == mNamedItemInfos.end())
- {
- if (!name.empty())
- {
- logger->log("ItemDB: Warning, unknown item name \"%s\"",
- name.c_str());
- }
- return *mUnknown;
- }
-
- return *(i->second);
+ // Add specific Manaserv checks here
}
-void ItemDB::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, GENDER_MALE);
- }
- if (gender == "female" || gender == "unisex")
- {
- itemInfo->setSprite(filename, GENDER_FEMALE);
- }
-}
-
-void ItemDB::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());
- }
-}
-
-void ItemDB::loadFloorSprite(SpriteDisplay *display, xmlNodePtr floorNode)
-{
- for_each_xml_child_node(spriteNode, floorNode)
- {
- if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
- {
- SpriteReference *currentSprite = new SpriteReference;
- currentSprite->sprite = (const char*)spriteNode->xmlChildrenNode->content;
- currentSprite->variant = XML::getProperty(spriteNode, "variant", 0);
- display->sprites.push_back(currentSprite);
- }
- else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
- {
- std::string particlefx = (const char*)spriteNode->xmlChildrenNode->content;
- display->particles.push_back(particlefx);
- }
- }
-}
+}; // namespace ManaServ
diff --git a/src/resources/itemdb.h b/src/resources/itemdb.h
index 9109898b..e80f2cd0 100644
--- a/src/resources/itemdb.h
+++ b/src/resources/itemdb.h
@@ -33,24 +33,59 @@
class ItemInfo;
class SpriteDisplay;
+// Used to make the compiler uderstand the iteminfo friendship.
+namespace TmwAthena { class TaItemDB; };
+namespace ManaServ { class ManaServItemDB; };
+
+/**
+ * Nano-description functions
+ */
+class ItemStat
+{
+ friend class ItemDB;
+ friend class TmwAthena::TaItemDB;
+ friend class ManaServ::ManaServItemDB;
+
+ public:
+ ItemStat(const std::string &tag,
+ const std::string &format):
+ mTag(tag), mFormat(format) {}
+
+ bool operator ==(std::string &name) const
+ { return mTag == name; }
+
+ private:
+ std::string mTag;
+ std::string mFormat;
+};
+
+// Used to set nano-description
+static std::list<ItemStat> extraStats;
+void setStatsList(const std::list<ItemStat> &stats);
+
/**
- * Item information database.
+ * Item information database generic definition.
*/
class ItemDB
{
public:
- ItemDB() : mLoaded(false) { load(); }
+ ItemDB() :
+ mUnknown(0),
+ mLoaded(false)
+ {}
+
+ ~ItemDB()
+ {}
- ~ItemDB() { unload(); }
/**
* Loads the item data from <code>items.xml</code>.
*/
- void load();
+ virtual void load() = 0;
/**
* Frees item data.
*/
- void unload();
+ virtual void unload();
/**
* Tells whether the item database is loaded.
@@ -63,26 +98,42 @@ class ItemDB
const ItemInfo &get(int id);
const ItemInfo &get(const std::string &name);
- class Stat
- {
- public:
- Stat(const std::string &tag,
- const std::string &format):
- tag(tag), format(format) {}
+ protected:
+ /**
+ * Permits to load item definitions which are common
+ * for each protocols to avoid code duplication.
+ */
+ void loadCommonRef(ItemInfo *itemInfo, xmlNodePtr node);
- bool operator ==(std::string &name) const { return tag == name; }
+ /**
+ * Checks the items parameters consistency.
+ */
+ virtual void checkItemInfo(ItemInfo* itemInfo);
- private:
- std::string tag;
- std::string format;
- friend class ItemDB;
- };
+ /**
+ * Register the item to mItemInfos and mNamedItemsInfos
+ */
+ void addItem(ItemInfo *itemInfo);
- void setStatsList(const std::list<Stat> &stats);
+ // Default unknown reference
+ ItemInfo *mUnknown;
+
+ bool mLoaded;
private:
+ /**
+ * Loads the sprite references contained in a <sprite> tag.
+ */
void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node);
- void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node);
+
+ /**
+ * Loads the sound references contained in a <sound> tag.
+ */
+ void loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node);
+
+ /**
+ * Loads the floor item references contained in a <floor> tag.
+ */
void loadFloorSprite(SpriteDisplay *display, xmlNodePtr node);
// Items database
@@ -91,10 +142,69 @@ class ItemDB
ItemInfos mItemInfos;
NamedItemInfos mNamedItemInfos;
- ItemInfo *mUnknown;
- bool mLoaded;
};
+namespace TmwAthena {
+
+class TaItemInfo;
+
+/**
+ * Item information database TmwAthena specific class.
+ */
+class TaItemDB: public ItemDB
+{
+ public:
+ TaItemDB() : ItemDB()
+ { load(); }
+
+ ~TaItemDB()
+ { unload(); }
+
+ /**
+ * Loads the item data from <code>items.xml</code>.
+ */
+ void load();
+
+ private:
+ /**
+ * Check items id specific hard limits and log errors found.
+ * TODO: Do it.
+ */
+ void checkHairWeaponsRacesSpecialIds()
+ {}
+
+ void checkItemInfo(ItemInfo* itemInfo);
+};
+
+}; // namespace TmwAthena
+
+namespace ManaServ {
+
+class ManaServItemInfo;
+
+/**
+ * Item information database TmwAthena specific class.
+ */
+class ManaServItemDB: public ItemDB
+{
+ public:
+ ManaServItemDB() : ItemDB()
+ { load(); }
+
+ ~ManaServItemDB()
+ { unload(); }
+
+ /**
+ * Loads the item data from <code>items.xml</code>.
+ */
+ void load();
+
+ private:
+ void checkItemInfo(ItemInfo* itemInfo);
+};
+
+}; // namespace ManaServ
+
extern ItemDB *itemDb;
#endif
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index 2ed27847..50633f71 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -36,38 +36,9 @@ enum EquipmentSoundEvent
EQUIP_EVENT_HIT
};
-enum EquipmentSlot
-{
- // Equipment rules:
- // 1 Brest equipment
- EQUIP_TORSO_SLOT = 0,
- // 1 arms equipment
- EQUIP_ARMS_SLOT = 1,
- // 1 head equipment
- EQUIP_HEAD_SLOT = 2,
- // 1 legs equipment
- EQUIP_LEGS_SLOT = 3,
- // 1 feet equipment
- EQUIP_FEET_SLOT = 4,
- // 2 rings
- EQUIP_RING1_SLOT = 5,
- EQUIP_RING2_SLOT = 6,
- // 1 necklace
- EQUIP_NECKLACE_SLOT = 7,
- // Fight:
- // 2 one-handed weapons
- // or 1 two-handed weapon
- // or 1 one-handed weapon + 1 shield.
- EQUIP_FIGHT1_SLOT = 8,
- EQUIP_FIGHT2_SLOT = 9,
- // Projectile:
- // this item does not amount to one, it only indicates the chosen projectile.
- EQUIP_PROJECTILE_SLOT = 10
-};
-
-
/**
* Enumeration of available Item types.
+ * TODO: Dynamise this using an xml.
*/
enum ItemType
{
@@ -89,12 +60,21 @@ enum ItemType
ITEM_SPRITE_HAIR // 15
};
+// Used to make the compiler uderstand the iteminfo friendship.
+namespace TmwAthena { class TaItemDB; };
+namespace ManaServ { class ManaServItemDB; };
+
/**
- * Defines a class for storing item infos. This includes information used when
- * the item is equipped.
+ * Defines a class for storing generic item infos.
+ * Specialized version for one or another protocol are defined below.
*/
class ItemInfo
{
+ friend class ItemDB;
+ friend void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node);
+ friend class TmwAthena::TaItemDB;
+ friend class ManaServ::ManaServItemDB;
+
public:
/**
* Constructor.
@@ -114,7 +94,8 @@ class ItemInfo
const std::string &getName() const
{ return mName; }
- std::string getParticleEffect() const { return mParticle; }
+ std::string getParticleEffect() const
+ { return mParticle; }
const SpriteDisplay &getDisplay() const
{ return mDisplay; }
@@ -122,7 +103,8 @@ class ItemInfo
const std::string &getDescription() const
{ return mDescription; }
- const std::vector<std::string> &getEffect() const { return mEffect; }
+ const std::vector<std::string> &getEffect() const
+ { return mEffect; }
int getWeight() const
{ return mWeight; }
@@ -132,9 +114,11 @@ class ItemInfo
void setAttackAction(std::string attackAction);
// Handlers for seting and getting the string used for particles when attacking
- void setMissileParticle(std::string s) { mMissileParticle = s; }
+ void setMissileParticle(std::string s)
+ { mMissileParticle = s; }
- std::string getMissileParticle() const { return mMissileParticle; }
+ std::string getMissileParticle() const
+ { return mMissileParticle; }
std::string getAttackAction() const
{ return mAttackAction; }
@@ -144,9 +128,14 @@ class ItemInfo
const std::string &getSound(EquipmentSoundEvent event) const;
- bool getEquippable() const { return mEquippable; }
+ bool getEquippable() const
+ { return mEquippable; }
- bool getActivatable() const { return mActivatable; }
+ bool getActivatable() const
+ { return mActivatable; }
+
+ ItemType getItemType() const
+ { return mType; }
private:
@@ -184,9 +173,82 @@ class ItemInfo
/** Stores the names of sounds to be played at certain event. */
std::map< EquipmentSoundEvent, std::vector<std::string> > mSounds;
+};
- friend class ItemDB;
- friend void loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node);
+/*
+ * TmwAthena specialization of the itemInfo for TmwAthena
+ */
+namespace TmwAthena {
+
+enum EquipmentSlot
+{
+ // Equipment rules:
+ // 1 Brest equipment
+ EQUIP_TORSO_SLOT = 0,
+ // 1 arms equipment
+ EQUIP_ARMS_SLOT = 1,
+ // 1 head equipment
+ EQUIP_HEAD_SLOT = 2,
+ // 1 legs equipment
+ EQUIP_LEGS_SLOT = 3,
+ // 1 feet equipment
+ EQUIP_FEET_SLOT = 4,
+ // 2 rings
+ EQUIP_RING1_SLOT = 5,
+ EQUIP_RING2_SLOT = 6,
+ // 1 necklace
+ EQUIP_NECKLACE_SLOT = 7,
+ // Fight:
+ // 2 one-handed weapons
+ // or 1 two-handed weapon
+ // or 1 one-handed weapon + 1 shield.
+ EQUIP_FIGHT1_SLOT = 8,
+ EQUIP_FIGHT2_SLOT = 9,
+ // Projectile:
+ // this item does not amount to one, it only indicates the chosen projectile.
+ EQUIP_PROJECTILE_SLOT = 10,
+ EQUIP_VECTOR_END = 11
};
+/**
+ * Defines a class for storing TmwAthena specific item infos.
+ * Specialized version for one or another protocol are defined below.
+ */
+class TaItemInfo: public ItemInfo
+{
+ friend class TaItemDB;
+
+ public:
+ /**
+ * Constructor.
+ */
+ TaItemInfo():ItemInfo()
+ {}
+
+ // Declare TmwAthena Specific item info here
+};
+
+}; // namespace TmwAthena
+
+namespace ManaServ {
+
+/**
+ * Defines a class for storing Manaserv Specific item infos.
+ * Specialized version for one or another protocol are defined below.
+ */
+class ManaServItemInfo: public ItemInfo
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ManaServItemInfo():ItemInfo()
+ {}
+
+ // Declare Manaserv Specific item info here
+};
+
+
+}; // namespace ManaServ
+
#endif