summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2009-07-07 11:23:14 -0600
committerJared Adams <jaxad0127@gmail.com>2009-07-07 11:23:14 -0600
commit5662b7d9ad9eb6927df7ca83713d3b6108f59ddc (patch)
tree1e962203f7bf2440b558045967d0f93ccf21bbe4 /src
parent851f67cd9975b090b051decb1deab6b0489d14c5 (diff)
downloadmana-5662b7d9ad9eb6927df7ca83713d3b6108f59ddc.tar.gz
mana-5662b7d9ad9eb6927df7ca83713d3b6108f59ddc.tar.bz2
mana-5662b7d9ad9eb6927df7ca83713d3b6108f59ddc.tar.xz
mana-5662b7d9ad9eb6927df7ca83713d3b6108f59ddc.zip
Use tmw-skills.xml instead of hardcoding
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gui/skilldialog.cpp365
-rw-r--r--src/gui/skilldialog.h30
-rw-r--r--src/gui/widgets/tabbedarea.cpp10
-rw-r--r--src/gui/widgets/tabbedarea.h5
-rw-r--r--src/gui/widgets/vertcontainer.cpp53
-rw-r--r--src/gui/widgets/vertcontainer.h47
-rw-r--r--src/localplayer.cpp66
-rw-r--r--src/localplayer.h58
-rw-r--r--src/net/tmwserv/generalhandler.cpp2
-rw-r--r--src/net/tmwserv/playerhandler.cpp27
-rw-r--r--src/net/tmwserv/protocol.h2
13 files changed, 352 insertions, 317 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 91fe8e06..a4594281 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -110,6 +110,8 @@ SET(SRCS
gui/widgets/textfield.h
gui/widgets/textpreview.cpp
gui/widgets/textpreview.h
+ gui/widgets/vertcontainer.cpp
+ gui/widgets/vertcontainer.h
gui/widgets/whispertab.cpp
gui/widgets/whispertab.h
gui/widgets/window.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 23de64bc..3637dc9f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,8 @@ tmw_SOURCES = gui/widgets/avatar.cpp \
gui/widgets/textfield.h \
gui/widgets/textpreview.cpp \
gui/widgets/textpreview.h \
+ gui/widgets/vertcontainer.cpp \
+ gui/widgets/vertcontainer.h \
gui/widgets/whispertab.cpp \
gui/widgets/whispertab.h \
gui/widgets/window.cpp \
diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp
index f0cd01ce..a0b8f569 100644
--- a/src/gui/skilldialog.cpp
+++ b/src/gui/skilldialog.cpp
@@ -25,105 +25,66 @@
#include "gui/widgets/container.h"
#include "gui/widgets/icon.h"
#include "gui/widgets/label.h"
+#include "gui/widgets/layouthelper.h"
#include "gui/widgets/listbox.h"
#include "gui/widgets/progressbar.h"
#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/tab.h"
#include "gui/widgets/tabbedarea.h"
+#include "gui/widgets/vertcontainer.h"
#include "gui/widgets/windowcontainer.h"
#include "localplayer.h"
+#include "log.h"
#include "utils/dtor.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
+#include "utils/xml.h"
#include <string>
#include <vector>
-class SkillTab : public Container, public gcn::ActionListener
+class SkillEntry;
+
+struct SkillInfo
+{
+ unsigned short id;
+ std::string name;
+ std::string icon;
+ bool modifiable;
+ SkillEntry *display;
+};
+
+class SkillEntry : public Container
{
public:
- /**
- * The type of this skill tab
- */
- const std::string type;
-
- /**
- * Constructor
- */
- SkillTab(const std::string &type);
-
- /**
- * Update this tab
- */
- void update();
+ SkillEntry(struct SkillInfo *info);
- /**
- * Called when receiving actions from widget.
- */
- void action(const gcn::ActionEvent &event) {}
+ void update();
private:
- /**
- * Update the information of a skill at
- * the given index
- */
- void updateSkill(int index);
-
- /**
- * Gets the number of skills in this particular
- * type of tab.
- */
- int getSkillNum();
-
- /**
- * Get the first enumeration of this skill tab's
- * skill type.
- */
- int getSkillBegin();
-
- /**
- * Get the icon associated with the given index
- */
- Icon *getIcon(int index);
-
- std::vector<Icon *> mSkillIcons;
- std::vector<gcn::Label *> mSkillNameLabels;
- std::vector<gcn::Label *> mSkillLevelLabels;
- std::vector<gcn::Label *> mSkillExpLabels;
- std::vector<ProgressBar *> mSkillProgress;
+ struct SkillInfo *mInfo;
+ Icon *mIcon;
+ Label *mNameLabel;
+ Label *mLevelLabel;
+ Label *mExpLabel;
+ ProgressBar *mProgress;
};
-
SkillDialog::SkillDialog():
Window(_("Skills"))
{
setWindowName("Skills");
setCloseButton(true);
+ setResizable(true);
setSaveVisible(true);
setDefaultSize(windowContainer->getWidth() - 280, 30, 275, 425);
- TabbedArea *panel = new TabbedArea;
- panel->setDimension(gcn::Rectangle(5, 5, 270, 420));
-
- SkillTab *tab;
+ mTabs = new TabbedArea();
- // Add each type of skill tab to the panel
- tab = new SkillTab("Weapon");
- panel->addTab(_("Weapons"), tab);
- mTabs.push_back(tab);
-
- tab = new SkillTab("Magic");
- panel->addTab(_("Magic"), tab);
- mTabs.push_back(tab);
-
- tab = new SkillTab("Craft");
- panel->addTab(_("Crafts"), tab);
- mTabs.push_back(tab);
-
- add(panel);
-
- update();
+ place(0, 0, mTabs, 5, 5);
+ place(0, 5, new Label("TODO"));
setLocationRelativeTo(getParent());
loadWindowState();
@@ -131,7 +92,7 @@ SkillDialog::SkillDialog():
SkillDialog::~SkillDialog()
{
- delete_all(mTabs);
+ //delete_all(mTabs);
}
void SkillDialog::action(const gcn::ActionEvent &event)
@@ -145,174 +106,182 @@ void SkillDialog::action(const gcn::ActionEvent &event)
}
}
-void SkillDialog::draw(gcn::Graphics *g)
-{
- update();
-
- Window::draw(g);
-}
-
-void SkillDialog::update()
+void SkillDialog::adjustTabSize()
{
- for(std::list<SkillTab*>::const_iterator i = mTabs.begin();
- i != mTabs.end(); ++i)
- {
- (*i)->update();
+ gcn::Widget *content = mTabs->getCurrentWidget();
+ if (content) {
+ int width = mTabs->getWidth() - 2 * content->getFrameSize();
+ int height = mTabs->getContainerHeight() - 2 * content->getFrameSize();
+ content->setSize(width, height);
+ content->setVisible(true);
+ content->logic();
}
}
-SkillTab::SkillTab(const std::string &type): type(type)
+void SkillDialog::widgetResized(const gcn::Event &event)
{
- setOpaque(false);
- setDimension(gcn::Rectangle(0, 0, 270, 420));
- int skillNum = getSkillNum();
-
- mSkillIcons.resize(skillNum);
- mSkillNameLabels.resize(skillNum);
- mSkillLevelLabels.resize(skillNum);
- mSkillExpLabels.resize(skillNum);
- mSkillProgress.resize(skillNum);
-
- // Set the initial positions of the skill information
- for (int a = 0; a < skillNum; a++)
- {
- mSkillIcons.at(a) = getIcon(a);
- mSkillIcons.at(a)->setPosition(1, a*32);
- add(mSkillIcons.at(a));
-
- mSkillNameLabels.at(a) = new Label("");
- mSkillNameLabels.at(a)->setPosition(35, a*32 );
- add(mSkillNameLabels.at(a));
+ Window::widgetResized(event);
- mSkillProgress.at(a) = new ProgressBar(0.0f, 200, 20, gcn::Color(150, 150, 150));
- mSkillProgress.at(a)->setPosition(35, a*32 + 13);
- add(mSkillProgress.at(a));
+ adjustTabSize();
+}
- mSkillExpLabels.at(a) = new Label("");
- mSkillExpLabels.at(a)->setPosition(45, a*32 + 16);
- add(mSkillExpLabels.at(a));
+void SkillDialog::logic()
+{
+ Window::logic();
- mSkillLevelLabels.at(a) = new Label("");
- mSkillLevelLabels.at(a)->setPosition(165, a*32);
- add(mSkillLevelLabels.at(a));
+ Tab *tab = dynamic_cast<Tab*>(mTabs->getSelectedTab());
+ if (tab != mCurrentTab) {
+ mCurrentTab = tab;
+ adjustTabSize();
}
-
- update();
}
-int SkillTab::getSkillNum()
+std::string SkillDialog::update(int id)
{
- int skillNum = 0;
+ SkillInfo *info = mSkills[id];
- if (type == "Weapon")
- {
- skillNum = CHAR_SKILL_WEAPON_NB;
- return skillNum;
- }
- else if (type == "Magic")
- {
- skillNum = CHAR_SKILL_MAGIC_NB;
- return skillNum;
- }
- else if (type == "Craft")
+ if (info)
{
- skillNum = CHAR_SKILL_CRAFT_NB;
- return skillNum;
+ info->display->update();
+ return info->name;
}
- else return skillNum;
+ else
+ return "";
}
-int SkillTab::getSkillBegin()
+void SkillDialog::loadSkills(const std::string &file, bool fixed)
{
- int skillBegin = 0;
+ // TODO: mTabs->clear();
+ delete_all(mSkills);
- if (type == "Weapon")
- {
- skillBegin = CHAR_SKILL_WEAPON_BEGIN - CHAR_SKILL_BEGIN;
- return skillBegin;
- }
- else if (type == "Magic")
+ XML::Document doc(file);
+ xmlNodePtr root = doc.rootNode();
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "skills"))
{
- skillBegin = CHAR_SKILL_MAGIC_BEGIN - CHAR_SKILL_BEGIN;
- return skillBegin;
+ logger->log("Error loading skills file: %s", file.c_str());
+ return;
}
- else if (type == "Craft")
+
+ int setCount = 0;
+ std::string setName;
+ ScrollArea *scroll;
+ VertContainer *container;
+ std::string fixedDef = toString(fixed);
+
+ for_each_xml_child_node(set, root)
{
- skillBegin = CHAR_SKILL_CRAFT_BEGIN - CHAR_SKILL_BEGIN;
- return skillBegin;
+ if (xmlStrEqual(set->name, BAD_CAST "set"))
+ {
+ setCount++;
+ setName = XML::getProperty(set, "name", strprintf(_("Skill Set %d"), setCount));
+
+ container = new VertContainer(32);
+ container->setOpaque(false);
+ scroll = new ScrollArea(container);
+ scroll->setOpaque(false);
+ scroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
+ scroll->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS);
+
+ mTabs->addTab(setName, scroll);
+ for_each_xml_child_node(node, set)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "skill"))
+ {
+ int id = atoi(XML::getProperty(node, "id", "-1").c_str());
+ std::string name = XML::getProperty(node, "name", strprintf(_("Skill %d"), id));
+ std::string icon = XML::getProperty(node, "icon", "");
+ bool modifiable = !atoi(XML::getProperty(node, "fixed", fixedDef).c_str());
+
+ SkillInfo *skill = new SkillInfo;
+ skill->id = id;
+ skill->name = name;
+ skill->icon = icon;
+ skill->modifiable = modifiable;
+ skill->display = new SkillEntry(skill);
+
+ container->add(skill->display);
+
+ mSkills[id] = skill;
+ }
+ }
+ }
}
- else return skillBegin;
-}
-Icon* SkillTab::getIcon(int index)
-{
- int skillBegin = getSkillBegin();
- std::string icon = LocalPlayer::getSkillInfo(index + skillBegin).icon;
- return new Icon(icon);
+ adjustTabSize();
}
-void SkillTab::updateSkill(int index)
+SkillEntry::SkillEntry(struct SkillInfo *info) : mInfo(info),
+ mIcon(NULL),
+ mNameLabel(new Label(info->name)),
+ mProgress(new ProgressBar(0.0f, 200, 20, gcn::Color(150, 150, 150))),
+ mLevelLabel(new Label("999"))
{
- int skillBegin = getSkillBegin();
+ setOpaque(false);
+
+ if (!info->icon.empty())
+ mIcon = new Icon(info->icon);
- int baseLevel = player_node->getAttributeBase(index +
- skillBegin +
- CHAR_SKILL_BEGIN);
+ /*LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
- int effLevel = player_node->getAttributeEffective(index +
- skillBegin +
- CHAR_SKILL_BEGIN);
- if(baseLevel <= 0)
+ if (mIcon)
+ place(0, 0, mIcon, 1, 2);
+ place(1, 0, mNameLabel, 3);
+ place(4, 0, mLevelLabel);
+ place(1, 1, mProgress, 4);*/
+
+ if (mIcon)
{
- mSkillProgress.at(index)->setVisible(false);
- mSkillExpLabels.at(index)->setVisible(false);
- mSkillLevelLabels.at(index)->setVisible(false);
- mSkillNameLabels.at(index)->setVisible(false);
- mSkillIcons.at(index)->setVisible(false);
+ mIcon->setPosition(1, 0);
+ add(mIcon);
}
- else
- {
- mSkillProgress.at(index)->setVisible(true);
- mSkillExpLabels.at(index)->setVisible(true);
- mSkillLevelLabels.at(index)->setVisible(true);
- mSkillNameLabels.at(index)->setVisible(true);
- mSkillIcons.at(index)->setVisible(true);
- std::string skillLevel("Lvl: " + toString(baseLevel));
- if (effLevel < baseLevel)
- {
- skillLevel.append(" - " + toString(baseLevel - effLevel));
- }
- else if (effLevel > baseLevel)
- {
- skillLevel.append(" + " + toString(effLevel - baseLevel));
- }
- mSkillLevelLabels.at(index)->setCaption(skillLevel);
- std::pair<int, int> exp = player_node->getExperience(index + skillBegin);
- std::string sExp (toString(exp.first) + " / " + toString(exp.second));
+ mNameLabel->setPosition(35, 0);
+ add(mNameLabel);
+ mLevelLabel->setPosition(165, 0);
+ add(mLevelLabel);
- mSkillNameLabels.at(index)->setCaption(LocalPlayer::getSkillInfo(index + skillBegin).name);
- mSkillNameLabels.at(index)->adjustSize();
- mSkillLevelLabels.at(index)->adjustSize();
- mSkillExpLabels.at(index)->setCaption(sExp);
- mSkillExpLabels.at(index)->adjustSize();
- mSkillExpLabels.at(index)->setAlignment(gcn::Graphics::RIGHT);
+ mProgress->setPosition(35, 13);
+ add(mProgress);
- // More intense red as exp grows
- int color = 150 - (int)(150 * ((float) exp.first / exp.second));
- mSkillProgress.at(index)->setColor(244, color, color);
- mSkillProgress.at(index)->setProgress((float) exp.first / exp.second);
- }
+ update();
}
-void SkillTab::update()
+void SkillEntry::update()
{
- int skillNum = getSkillNum();
+ int baseLevel = player_node->getAttributeBase(mInfo->id);
+
+ int effLevel = player_node->getAttributeEffective(mInfo->id);
+
+ if (baseLevel <= 0)
+ {
+ setVisible(false);
+ return;
+ }
- // Update the skill information for reach skill
- for (int a = 0; a < skillNum; a++)
+ setVisible(true);
+
+ std::string skillLevel("Lvl: " + toString(baseLevel));
+ if (effLevel < baseLevel)
+ {
+ skillLevel.append(" - " + toString(baseLevel - effLevel));
+ }
+ else if (effLevel > baseLevel)
{
- updateSkill(a);
+ skillLevel.append(" + " + toString(effLevel - baseLevel));
}
+ mLevelLabel->setCaption(skillLevel);
+
+ std::pair<int, int> exp = player_node->getExperience(mInfo->id);
+ std::string sExp (toString(exp.first) + " / " + toString(exp.second));
+
+ mLevelLabel->adjustSize();
+ mProgress->setText(sExp);
+
+ // More intense red as exp grows
+ int color = 150 - (int)(150 * ((float) exp.first / exp.second));
+ mProgress->setColor(244, color, color);
+ mProgress->setProgress((float) exp.first / exp.second);
}
diff --git a/src/gui/skilldialog.h b/src/gui/skilldialog.h
index 56192273..fbd3c26d 100644
--- a/src/gui/skilldialog.h
+++ b/src/gui/skilldialog.h
@@ -29,10 +29,13 @@
#include <guichan/actionlistener.hpp>
#include <list>
+#include <map>
-class ProgressBar;
-class Icon;
-class SkillTab;
+class ScrollArea;
+class Tab;
+class TabbedArea;
+
+struct SkillInfo;
/**
* The skill dialog.
@@ -52,17 +55,26 @@ class SkillDialog : public Window, public gcn::ActionListener
void action(const gcn::ActionEvent &event);
/**
- * Update the tabs in this dialog
+ * Called when the widget changes size. Used for adapting the size of
+ * the tabbed area.
*/
- void update();
+ void widgetResized(const gcn::Event &event);
+
+ void logic();
/**
- * Draw this window.
- */
- void draw(gcn::Graphics *g);
+ * Update the given skill's display
+ */
+ std::string update(int id);
+
+ void loadSkills(const std::string &file, bool fixed = true);
private:
- std::list<SkillTab*> mTabs;
+ void adjustTabSize();
+
+ Tab *mCurrentTab;
+ TabbedArea *mTabs;
+ std::map<int, SkillInfo*> mSkills;
};
extern SkillDialog *skillDialog;
diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp
index 07f46a94..bb5ae9a4 100644
--- a/src/gui/widgets/tabbedarea.cpp
+++ b/src/gui/widgets/tabbedarea.cpp
@@ -69,6 +69,16 @@ gcn::Widget *TabbedArea::getWidget(const std::string &name) const
return NULL;
}
+gcn::Widget *TabbedArea::getCurrentWidget()
+{
+ gcn::Tab *tab = getSelectedTab();
+
+ if (tab)
+ return getWidget(tab->getCaption());
+ else
+ return NULL;
+}
+
void TabbedArea::addTab(const std::string &caption, gcn::Widget *widget)
{
Tab *tab = new Tab;
diff --git a/src/gui/widgets/tabbedarea.h b/src/gui/widgets/tabbedarea.h
index 6aaafe16..29ba2f76 100644
--- a/src/gui/widgets/tabbedarea.h
+++ b/src/gui/widgets/tabbedarea.h
@@ -63,6 +63,11 @@ class TabbedArea : public gcn::TabbedArea
*/
gcn::Widget *getWidget(const std::string &name) const;
+ /**
+ * Returns the widget for the current tab
+ */
+ gcn::Widget *getCurrentWidget();
+
using gcn::TabbedArea::addTab;
/**
diff --git a/src/gui/widgets/vertcontainer.cpp b/src/gui/widgets/vertcontainer.cpp
new file mode 100644
index 00000000..9dd02cdc
--- /dev/null
+++ b/src/gui/widgets/vertcontainer.cpp
@@ -0,0 +1,53 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/vertcontainer.h"
+
+VertContainer::VertContainer(int spacing):
+ mSpacing(spacing),
+ mCount(0)
+{
+ addWidgetListener(this);
+}
+
+void VertContainer::add(gcn::Widget *widget)
+{
+ Container::add(widget);
+ widget->setPosition(0, mCount * mSpacing);
+ widget->setSize(getWidth(), mSpacing);
+ mCount++;
+ setHeight(mCount * mSpacing);
+}
+
+void VertContainer::clear()
+{
+ Container::clear();
+
+ mCount = 0;
+}
+
+void VertContainer::widgetResized(const gcn::Event &event)
+{
+ for (WidgetListIterator it = mWidgets.begin(); it != mWidgets.end(); it++)
+ {
+ (*it)->setWidth(getWidth());
+ }
+}
diff --git a/src/gui/widgets/vertcontainer.h b/src/gui/widgets/vertcontainer.h
new file mode 100644
index 00000000..9e15e66a
--- /dev/null
+++ b/src/gui/widgets/vertcontainer.h
@@ -0,0 +1,47 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef GUI_VERTCONTAINER_H
+#define GUI_VERTCONTAINER_H
+
+#include "gui/widgets/container.h"
+
+#include <guichan/widgetlistener.hpp>
+
+/**
+ * A widget container.
+ *
+ * This container places it's contents veritcally.
+ */
+class VertContainer : public Container, public gcn::WidgetListener
+{
+ public:
+ VertContainer(int spacing);
+ virtual void add(gcn::Widget *widget);
+ virtual void clear();
+ void widgetResized(const gcn::Event &event);
+
+ private:
+ int mSpacing;
+ int mCount;
+};
+
+#endif
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 240f0a65..1c7f7a5a 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -41,6 +41,8 @@
#include "gui/palette.h"
#ifdef EATHENA_SUPPORT
#include "gui/storagewindow.h"
+#else
+#include "gui/skilldialog.h"
#endif
#include "net/inventoryhandler.h"
@@ -103,10 +105,6 @@ LocalPlayer::LocalPlayer(int id, int job, Map *map):
#endif
mLastTarget(-1),
#ifdef TMWSERV_SUPPORT
- mAttributeBase(NB_CHARACTER_ATTRIBUTES, -1),
- mAttributeEffective(NB_CHARACTER_ATTRIBUTES, -1),
- mExpCurrent(CHAR_SKILL_NB, -1),
- mExpNext(CHAR_SKILL_NB, -1),
mCharacterPoints(-1),
mCorrectionPoints(-1),
mLevelProgress(0),
@@ -793,52 +791,50 @@ void LocalPlayer::lowerAttribute(size_t attr)
Net::GameServer::Player::lowerAttribute(attr + CHAR_ATTR_BEGIN);
}
-const struct LocalPlayer::SkillInfo& LocalPlayer::getSkillInfo(int skill)
+void LocalPlayer::setAttributeBase(int num, int value)
{
- static const SkillInfo skills[CHAR_SKILL_NB + 1] =
- {
- { _("Unarmed"), "graphics/images/unarmed.png" }, // CHAR_SKILL_WEAPON_NONE
- { _("Knife"), "graphics/images/knife.png" }, // CHAR_SKILL_WEAPON_KNIFE
- { _("Sword"), "graphics/images/sword.png" }, // CHAR_SKILL_WEAPON_SWORD
- { _("Polearm"), "graphics/images/polearm.png" }, // CHAR_SKILL_WEAPON_POLEARM
- { _("Staff"), "graphics/images/staff.png" }, // CHAR_SKILL_WEAPON_STAFF
- { _("Whip"), "graphics/images/whip.png" }, // CHAR_SKILL_WEAPON_WHIP
- { _("Bow"), "graphics/images/bow.png" }, // CHAR_SKILL_WEAPON_BOW
- { _("Shooting"), "graphics/images/shooting.png" }, // CHAR_SKILL_WEAPON_SHOOTING
- { _("Mace"), "graphics/images/mace.png" }, // CHAR_SKILL_WEAPON_MACE
- { _("Axe"), "graphics/images/axe.png" }, // CHAR_SKILL_WEAPON_AXE
- { _("Thrown"), "graphics/images/thrown.png" }, // CHAR_SKILL_WEAPON_THROWN
- { _("Magic"), "graphics/images/magic.png" }, // CHAR_SKILL_MAGIC_IAMJUSTAPLACEHOLDER
- { _("Craft"), "graphics/images/craft.png" }, // CHAR_SKILL_CRAFT_IAMJUSTAPLACEHOLDER
- { _("Unknown Skill"), "graphics/images/unknown.png" }
- };
+ int old = mAttributeBase[num];
- if ((skill < 0) || (skill > CHAR_SKILL_NB))
+ mAttributeBase[num] = value;
+ if (skillDialog)
{
- return skills[CHAR_SKILL_NB];
- }
- else
- {
- return skills[skill];
+ if (skillDialog->update(num).empty() || !(value > old))
+ return;
+
+ Particle* effect = particleEngine->addEffect("graphics/particles/skillup.particle.xml", 0, 0);
+ this->controlParticle(effect);
}
}
+void LocalPlayer::setAttributeEffective(int num, int value)
+{
+ mAttributeEffective[num] = value;
+ if (skillDialog)
+ skillDialog->update(num);
+}
+
void LocalPlayer::setExperience(int skill, int current, int next)
{
- int diff = current - mExpCurrent.at(skill);
- if (mMap && mExpCurrent.at(skill) != -1 && diff > 0)
+ std::pair<int, int> cur = getExperience(skill);
+ int diff = current - cur.first;
+
+ cur = std::pair<int, int>(current, next);
+
+ mSkillExp[skill] = cur;
+ std::string name;
+ if (skillDialog)
+ name = skillDialog->update(skill);
+
+ if (mMap && cur.first != -1 && diff > 0 && !name.empty())
{
- const std::string text = toString(diff) + " " + getSkillInfo(skill).name + " xp";
+ const std::string text = strprintf("%d %s xp", diff, name.c_str());
mExpMessages.push_back(text);
}
-
- mExpCurrent.at(skill) = current;
- mExpNext.at(skill) = next;
}
std::pair<int, int> LocalPlayer::getExperience(int skill)
{
- return std::pair<int, int> (mExpCurrent.at(skill), mExpNext.at(skill));
+ return mSkillExp[skill];
}
#endif
diff --git a/src/localplayer.h b/src/localplayer.h
index 4053e81e..50dfbc98 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -84,39 +84,7 @@ enum
CHAR_ATTR_END,
CHAR_ATTR_NB = CHAR_ATTR_END - CHAR_ATTR_BEGIN,
- CHAR_SKILL_BEGIN = CHAR_ATTR_END,
-
- CHAR_SKILL_WEAPON_BEGIN = CHAR_SKILL_BEGIN,
- CHAR_SKILL_WEAPON_NONE = CHAR_SKILL_WEAPON_BEGIN,
- CHAR_SKILL_WEAPON_KNIFE,
- CHAR_SKILL_WEAPON_SWORD,
- CHAR_SKILL_WEAPON_POLEARM,
- CHAR_SKILL_WEAPON_STAFF,
- CHAR_SKILL_WEAPON_WHIP,
- CHAR_SKILL_WEAPON_BOW,
- CHAR_SKILL_WEAPON_SHOOTING,
- CHAR_SKILL_WEAPON_MACE,
- CHAR_SKILL_WEAPON_AXE,
- CHAR_SKILL_WEAPON_THROWN,
- CHAR_SKILL_WEAPON_END,
- CHAR_SKILL_WEAPON_NB = CHAR_SKILL_WEAPON_END - CHAR_SKILL_WEAPON_BEGIN,
-
- CHAR_SKILL_MAGIC_BEGIN = CHAR_SKILL_WEAPON_END,
- CHAR_SKILL_MAGIC_IAMJUSTAPLACEHOLDER = CHAR_SKILL_MAGIC_BEGIN,
- // add magic skills here
- CHAR_SKILL_MAGIC_END,
- CHAR_SKILL_MAGIC_NB = CHAR_SKILL_MAGIC_END - CHAR_SKILL_MAGIC_BEGIN,
-
- CHAR_SKILL_CRAFT_BEGIN = CHAR_SKILL_MAGIC_END,
- CHAR_SKILL_CRAFT_IAMJUSTAPLACEHOLDER = CHAR_SKILL_CRAFT_BEGIN,
- // add crafting skills here
- CHAR_SKILL_CRAFT_END,
- CHAR_SKILL_CRAFT_NB = CHAR_SKILL_CRAFT_END - CHAR_SKILL_CRAFT_BEGIN,
-
- CHAR_SKILL_END = CHAR_SKILL_CRAFT_END,
- CHAR_SKILL_NB = CHAR_SKILL_END - CHAR_SKILL_BEGIN,
-
- NB_CHARACTER_ATTRIBUTES = CHAR_SKILL_END
+ NB_CHARACTER_ATTRIBUTES = CHAR_ATTR_END
};
#endif
@@ -371,17 +339,15 @@ class LocalPlayer : public Player
void setMaxWeight(int value)
{ mMaxWeight = value; }
- int getAttributeBase(int num) const
+ int getAttributeBase(int num)
{ return mAttributeBase[num]; }
- void setAttributeBase(int num, int value)
- { mAttributeBase[num] = value; }
+ void setAttributeBase(int num, int value);
- int getAttributeEffective(int num) const
+ int getAttributeEffective(int num)
{ return mAttributeEffective[num]; }
- void setAttributeEffective(int num, int value)
- { mAttributeEffective[num] = value; }
+ void setAttributeEffective(int num, int value);
int getCharacterPoints() const
{ return mCharacterPoints; }
@@ -397,13 +363,6 @@ class LocalPlayer : public Player
void setExperience(int skill, int current, int next);
- struct SkillInfo {
- std::string name;
- std::string icon;
- };
-
- static const SkillInfo& getSkillInfo(int skill);
-
std::pair<int, int> getExperience(int skill);
bool mUpdateName; /** Whether or not the name settings have changed */
@@ -424,10 +383,9 @@ class LocalPlayer : public Player
int mLastTarget; /** Time stamp of last targeting action, -1 if none. */
// Character status:
- std::vector<int> mAttributeBase;
- std::vector<int> mAttributeEffective;
- std::vector<int> mExpCurrent;
- std::vector<int> mExpNext;
+ std::map<int, int> mAttributeBase;
+ std::map<int, int> mAttributeEffective;
+ std::map<int, std::pair<int, int> > mSkillExp;
int mCharacterPoints;
int mCorrectionPoints;
int mLevelProgress;
diff --git a/src/net/tmwserv/generalhandler.cpp b/src/net/tmwserv/generalhandler.cpp
index 5886aafb..10b2c0f3 100644
--- a/src/net/tmwserv/generalhandler.cpp
+++ b/src/net/tmwserv/generalhandler.cpp
@@ -21,6 +21,7 @@
#include "gui/inventorywindow.h"
#include "gui/partywindow.h"
+#include "gui/skilldialog.h"
#include "net/tmwserv/generalhandler.h"
@@ -146,6 +147,7 @@ void GeneralHandler::guiWindowsLoaded()
{
inventoryWindow->setSplitAllowed(true);
partyWindow->clearPartyName();
+ skillDialog->loadSkills("tmw-skills.xml");
}
void GeneralHandler::guiWindowsUnloaded()
diff --git a/src/net/tmwserv/playerhandler.cpp b/src/net/tmwserv/playerhandler.cpp
index 69a2bdb4..bbce3ae1 100644
--- a/src/net/tmwserv/playerhandler.cpp
+++ b/src/net/tmwserv/playerhandler.cpp
@@ -133,7 +133,7 @@ void PlayerHandler::handleMessage(MessageIn &msg)
logger->log("ATTRIBUTE UPDATE:");
while (msg.getUnreadLength())
{
- int stat = msg.readInt8();
+ int stat = msg.readInt16();
int base = msg.readInt16();
int value = msg.readInt16();
logger->log("%d set to %d %d", stat, base, value);
@@ -143,24 +143,11 @@ void PlayerHandler::handleMessage(MessageIn &msg)
player_node->setMaxHp(base);
player_node->setHp(value);
}
- else if (stat < NB_CHARACTER_ATTRIBUTES)
+ else
{
- if (stat >= CHAR_SKILL_BEGIN && stat < CHAR_SKILL_END
- && player_node->getAttributeBase(stat) < base
- && player_node->getAttributeBase(stat) > -1)
- {
- Particle* effect = particleEngine->addEffect("graphics/particles/skillup.particle.xml", 0, 0);
- player_node->controlParticle(effect);
- }
-
player_node->setAttributeBase(stat, base);
player_node->setAttributeEffective(stat, value);
}
- else
- {
- logger->log("Warning: server wants to update unknown "
- "attribute %d to %d", stat, value);
- }
}
} break;
@@ -173,15 +160,7 @@ void PlayerHandler::handleMessage(MessageIn &msg)
int current = msg.readInt32();
int next = msg.readInt32();
- if (skill < CHAR_SKILL_NB)
- {
- player_node->setExperience(skill, current, next);
- }
- else
- {
- logger->log("Warning: server wants to update experience of unknown "
- "skill %d to %d / %d", skill, current, next);
- }
+ player_node->setExperience(skill, current, next);
}
} break;
diff --git a/src/net/tmwserv/protocol.h b/src/net/tmwserv/protocol.h
index e9fc5b8a..13a15256 100644
--- a/src/net/tmwserv/protocol.h
+++ b/src/net/tmwserv/protocol.h
@@ -83,7 +83,7 @@ enum {
PGMSG_MOVE_ITEM = 0x0114, // B slot1, B slot2, B amount
GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount] }*
GPMSG_INVENTORY_FULL = 0x0121, // { B slot, W item id [, B amount] }*
- GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { B attribute, W base value, W modified value }*
+ GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { W attribute, W base value, W modified value }*
GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { W skill, D exp got, D exp needed }*
GPMSG_LEVELUP = 0x0150, // W new level
GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup