summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChuck Miller <shadowmil@gmail.com>2010-07-17 21:01:26 -0400
committerChuck Miller <shadowmil@gmail.com>2010-07-17 21:40:48 -0400
commit6a13899daed872debe2375c71903505e6434a731 (patch)
treefaaf483d80c6e791ec182f6331697f06281b97c7 /src
parentb738d67f76336641468e3f77cef472a52a6e5ad3 (diff)
downloadmana-6a13899daed872debe2375c71903505e6434a731.tar.gz
mana-6a13899daed872debe2375c71903505e6434a731.tar.bz2
mana-6a13899daed872debe2375c71903505e6434a731.tar.xz
mana-6a13899daed872debe2375c71903505e6434a731.zip
Modify how attributes and stats are handled
Handling moved from LocalPlayer to PlayerInfo class Event system used to update windows Reviewed-by: Jared Adams
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gui/charselectdialog.cpp6
-rw-r--r--src/gui/inventorywindow.cpp25
-rw-r--r--src/gui/inventorywindow.h17
-rw-r--r--src/gui/ministatus.cpp72
-rw-r--r--src/gui/ministatus.h6
-rw-r--r--src/gui/skilldialog.cpp10
-rw-r--r--src/gui/statuswindow.cpp228
-rw-r--r--src/gui/statuswindow.h14
-rw-r--r--src/gui/trade.cpp7
-rw-r--r--src/localplayer.cpp193
-rw-r--r--src/localplayer.h104
-rw-r--r--src/net/charhandler.h3
-rw-r--r--src/net/manaserv/buysellhandler.cpp6
-rw-r--r--src/net/manaserv/charhandler.cpp11
-rw-r--r--src/net/manaserv/generalhandler.cpp2
-rw-r--r--src/net/manaserv/inventoryhandler.cpp3
-rw-r--r--src/net/manaserv/playerhandler.cpp54
-rw-r--r--src/net/tmwa/buysellhandler.cpp7
-rw-r--r--src/net/tmwa/charserverhandler.cpp51
-rw-r--r--src/net/tmwa/charserverhandler.h2
-rw-r--r--src/net/tmwa/playerhandler.cpp203
-rw-r--r--src/net/tmwa/specialhandler.cpp8
-rw-r--r--src/playerinfo.cpp140
-rw-r--r--src/playerinfo.h105
26 files changed, 615 insertions, 666 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d4845085..de5c22c5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -487,6 +487,8 @@ SET(SRCS
particleemitterprop.h
party.cpp
party.h
+ playerinfo.cpp
+ playerinfo.h
playerrelations.cpp
playerrelations.h
position.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 8324671b..b20fcfa0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -386,6 +386,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
particleemitterprop.h \
party.cpp \
party.h \
+ playerinfo.cpp \
+ playerinfo.h \
playerrelations.cpp \
playerrelations.h \
position.cpp \
diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp
index e22c4daf..9d6050f8 100644
--- a/src/gui/charselectdialog.cpp
+++ b/src/gui/charselectdialog.cpp
@@ -388,8 +388,10 @@ void CharacterDisplay::update()
mButton->setCaption(_("Choose"));
mButton->setActionEventId("use");
mName->setCaption(strprintf("%s", character->getName().c_str()));
- mLevel->setCaption(strprintf("Level %d", character->getLevel()));
- mMoney->setCaption(Units::formatCurrency(character->getMoney()));
+ mLevel->setCaption(strprintf("Level %d",
+ mCharacter->data.mAttributes[LEVEL]));
+ mMoney->setCaption(Units::formatCurrency(
+ mCharacter->data.mAttributes[MONEY]));
mDelete->setVisible(true);
}
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 591ebd2f..91acbb00 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -21,11 +21,12 @@
#include "gui/inventorywindow.h"
+#include "event.h"
#include "inventory.h"
#include "item.h"
-#include "localplayer.h"
#include "units.h"
#include "keyboardconfig.h"
+#include "playerinfo.h"
#include "gui/itemamount.h"
#include "gui/setup.h"
@@ -60,6 +61,8 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
mInventory(inventory),
mSplit(false)
{
+ listen("Attributes");
+
setWindowName(isMainInventory() ? "Inventory" : "Storage");
setupWindow->registerWindowForReset(this);
setResizable(true);
@@ -341,10 +344,26 @@ void InventoryWindow::close()
}
}
+void InventoryWindow::event(const std::string &channel, const Mana::Event &event)
+{
+ if (event.getName() == "UpdateAttribute")
+ {
+ int id = event.getInt("id");
+ if (id == TOTAL_WEIGHT ||
+ id == MAX_WEIGHT)
+ {
+ updateWeight();
+ }
+ }
+}
+
void InventoryWindow::updateWeight()
{
- int total = player_node->getTotalWeight();
- int max = player_node->getMaxWeight();
+ int total = PlayerInfo::getAttribute(TOTAL_WEIGHT);
+ int max = PlayerInfo::getAttribute(MAX_WEIGHT);
+
+ if (max <= 0)
+ return;
// Adjust progress bar
mWeightBar->setProgress((float) total / max);
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index f611e934..3adbc1cc 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -23,6 +23,7 @@
#define INVENTORYWINDOW_H
#include "inventory.h"
+#include "listener.h"
#include "gui/widgets/window.h"
@@ -47,7 +48,8 @@ class InventoryWindow : public Window,
public gcn::ActionListener,
public gcn::KeyListener,
public gcn::SelectionListener,
- public InventoryListener
+ public InventoryListener,
+ public Mana::Listener
{
public:
/**
@@ -100,11 +102,6 @@ class InventoryWindow : public Window,
* window has been closed.
*/
void close();
-
- /**
- * Updates the weight bar.
- */
- void updateWeight();
void slotsChanged(Inventory* inventory);
@@ -115,7 +112,15 @@ class InventoryWindow : public Window,
*/
static bool isStorageActive() { return instances.size() > 1; }
+ void event(const std::string &channel, const Mana::Event &event);
+
private:
+ /**
+ * Updates the weight bar.
+ */
+ void updateWeight();
+
+
typedef std::list<InventoryWindow*> WindowList;
static WindowList instances;
diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp
index c8c942fd..84c88ec7 100644
--- a/src/gui/ministatus.cpp
+++ b/src/gui/ministatus.cpp
@@ -23,8 +23,9 @@
#include "animatedsprite.h"
#include "configuration.h"
+#include "event.h"
#include "graphics.h"
-#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/gui.h"
#include "gui/statuswindow.h"
@@ -45,22 +46,27 @@ extern volatile int tick_time;
MiniStatusWindow::MiniStatusWindow():
Popup("MiniStatus")
{
- int max = player_node->getMaxHp();
- mHpBar = new ProgressBar(max ? (float) player_node->getHp() / max : 0,
- 100, 20, Theme::PROG_HP);
+ listen("Attributes");
+
+ mHpBar = new ProgressBar(0, 100, 20, Theme::PROG_HP);
+ StatusWindow::updateHPBar(mHpBar);
+
if (Net::getGameHandler()->canUseMagicBar())
{
- max = player_node->getMaxMP();
- mMpBar = new ProgressBar(max ? (float) player_node->getMaxMP() / max : 0,
- 100, 20, Net::getPlayerHandler()->canUseMagic() ?
- Theme::PROG_MP : Theme::PROG_NO_MP);
+ mMpBar = new ProgressBar(0, 100, 20,
+ Net::getPlayerHandler()->canUseMagic()
+ ? Theme::PROG_MP : Theme::PROG_NO_MP);
+
+ StatusWindow::updateMPBar(mMpBar);
}
else
mMpBar = 0;
- max = player_node->getExpNeeded();
- mXpBar = new ProgressBar(max ? (float) player_node->getExp() / max : 0,
- 100, 20, Theme::PROG_EXP);
+ mXpBar = new ProgressBar(0, 100, 20, Theme::PROG_EXP);
+ StatusWindow::updateXPBar(mXpBar);
+
+ // Add the progressbars to the window
+
mHpBar->setPosition(0, 3);
if (mMpBar)
mMpBar->setPosition(mHpBar->getWidth() + 3, 3);
@@ -80,8 +86,6 @@ MiniStatusWindow::MiniStatusWindow():
mTextPopup = new TextPopup();
addMouseListener(this);
-
- update(StatusWindow::HP);
}
void MiniStatusWindow::setIcon(int index, AnimatedSprite *sprite)
@@ -114,19 +118,23 @@ void MiniStatusWindow::drawIcons(Graphics *graphics)
}
}
-void MiniStatusWindow::update(int id)
+void MiniStatusWindow::event(const std::string &channel, const Mana::Event &event)
{
- if (id == StatusWindow::HP)
- {
- StatusWindow::updateHPBar(mHpBar);
- }
- else if (id == StatusWindow::MP)
+ if (event.getName() == "UpdateAttribute")
{
- StatusWindow::updateMPBar(mMpBar);
- }
- else if (id == StatusWindow::EXP)
- {
- StatusWindow::updateXPBar(mXpBar);
+ int id = event.getInt("id");
+ if (id == HP || id == MAX_HP)
+ {
+ StatusWindow::updateHPBar(mHpBar);
+ }
+ else if (id == MP || id == MAX_MP)
+ {
+ StatusWindow::updateMPBar(mMpBar);
+ }
+ else if (id == EXP || id == EXP_NEEDED)
+ {
+ StatusWindow::updateXPBar(mXpBar);
+ }
}
}
@@ -162,23 +170,23 @@ void MiniStatusWindow::mouseMoved(gcn::MouseEvent &event)
if (event.getSource() == mXpBar)
{
mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", player_node->getExp(),
- player_node->getExpNeeded()),
+ strprintf("%u/%u", PlayerInfo::getAttribute(EXP),
+ PlayerInfo::getAttribute(EXP_NEEDED)),
strprintf("%s: %u", _("Need"),
- player_node->getExpNeeded()
- - player_node->getExp()));
+ PlayerInfo::getAttribute(EXP_NEEDED)
+ - PlayerInfo::getAttribute(EXP)));
}
else if (event.getSource() == mHpBar)
{
mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", player_node->getHp(),
- player_node->getMaxHp()));
+ strprintf("%u/%u", PlayerInfo::getAttribute(HP),
+ PlayerInfo::getAttribute(MAX_HP)));
}
else if (event.getSource() == mMpBar)
{
mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", player_node->getMP(),
- player_node->getMaxMP()));
+ strprintf("%u/%u", PlayerInfo::getAttribute(MP),
+ PlayerInfo::getAttribute(MAX_MP)));
}
else
{
diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h
index bb8d4094..1c772850 100644
--- a/src/gui/ministatus.h
+++ b/src/gui/ministatus.h
@@ -22,6 +22,8 @@
#ifndef MINISTATUS_H
#define MINISTATUS_H
+#include "listener.h"
+
#include "gui/widgets/popup.h"
#include <vector>
@@ -36,7 +38,7 @@ class TextPopup;
*
* \ingroup Interface
*/
-class MiniStatusWindow : public Popup
+class MiniStatusWindow : public Popup, public Mana::Listener
{
public:
MiniStatusWindow();
@@ -50,7 +52,7 @@ class MiniStatusWindow : public Popup
void drawIcons(Graphics *graphics);
- void update(int id); // Same types as status window
+ void event(const std::string &channel, const Mana::Event &event);
void logic(); // Updates icons
diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp
index 683a6d43..ccf4b418 100644
--- a/src/gui/skilldialog.cpp
+++ b/src/gui/skilldialog.cpp
@@ -21,8 +21,8 @@
#include "gui/skilldialog.h"
-#include "localplayer.h"
#include "log.h"
+#include "playerinfo.h"
#include "gui/setup.h"
#include "gui/theme.h"
@@ -259,7 +259,7 @@ std::string SkillDialog::update(int id)
void SkillDialog::update()
{
mPointsLabel->setCaption(strprintf(_("Skill points available: %d"),
- player_node->getSkillPoints()));
+ PlayerInfo::getAttribute(SKILL_POINTS)));
mPointsLabel->adjustSize();
for (SkillMap::iterator it = mSkills.begin(); it != mSkills.end(); it++)
@@ -410,10 +410,10 @@ void SkillModel::updateVisibilities()
void SkillInfo::update()
{
- int baseLevel = player_node->getAttributeBase(id);
- int effLevel = player_node->getAttributeEffective(id);
+ int baseLevel = PlayerInfo::getStatBase(id);
+ int effLevel = PlayerInfo::getStatEffective(id);
- std::pair<int, int> exp = player_node->getExperience(id);
+ std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
if (!modifiable && baseLevel == 0 && effLevel == 0 && exp.second == 0)
{
diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp
index c8ebdc98..5ba7fdea 100644
--- a/src/gui/statuswindow.cpp
+++ b/src/gui/statuswindow.cpp
@@ -21,10 +21,11 @@
#include "gui/statuswindow.h"
+#include "event.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "units.h"
-#include "gui/ministatus.h"
#include "gui/setup.h"
#include "gui/theme.h"
@@ -95,6 +96,8 @@ class ChangeDisplay : public AttrDisplay, gcn::ActionListener
StatusWindow::StatusWindow():
Window(player_node->getName())
{
+ listen("Attributes");
+
setWindowName("Status");
setupWindow->registerWindowForReset(this);
setResizable(true);
@@ -110,22 +113,22 @@ StatusWindow::StatusWindow():
mLvlLabel = new Label(strprintf(_("Level: %d"), 0));
mMoneyLabel = new Label(strprintf(_("Money: %s"), ""));
- int max = player_node->getMaxHp();
+ int max = PlayerInfo::getAttribute(MAX_HP);
mHpLabel = new Label(_("HP:"));
- mHpBar = new ProgressBar(max ? (float) player_node->getHp() / max: 0,
+ mHpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(HP) / max: 0,
80, 15, Theme::PROG_HP);
- max = player_node->getExpNeeded();
+ max = PlayerInfo::getAttribute(EXP_NEEDED);
mXpLabel = new Label(_("Exp:"));
- mXpBar = new ProgressBar(max ? (float) player_node->getExp() / max : 0,
+ mXpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(EXP) / max : 0,
80, 15, Theme::PROG_EXP);
bool magicBar = Net::getGameHandler()->canUseMagicBar();
if (magicBar)
{
- max = player_node->getMaxMP();
+ max = PlayerInfo::getAttribute(MAX_MP);
mMpLabel = new Label(_("MP:"));
- mMpBar = new ProgressBar(max ? (float) player_node->getMaxMP() / max : 0,
+ mMpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(MAX_MP) / max : 0,
80, 15, Net::getPlayerHandler()->canUseMagic() ?
Theme::PROG_MP : Theme::PROG_NO_MP);
}
@@ -186,97 +189,95 @@ StatusWindow::StatusWindow():
loadWindowState();
- update(HP);
+ // Update bars
+ updateHPBar(mHpBar, true);
if (magicBar)
- update(MP);
- update(EXP);
- update(MONEY);
- update(CHAR_POINTS); // This also updates all attributes (none atm)
- update(LEVEL);
- int job = Net::getPlayerHandler()->getJobLocation();
- if (job > 0)
- update(job);
-}
-
-std::string StatusWindow::update(int id)
-{
- if (miniStatusWindow)
- miniStatusWindow->update(id);
-
- if (id == HP)
- {
- updateHPBar(mHpBar, true);
-
- return _("HP");
- }
- else if (id == MP)
- {
updateMPBar(mMpBar, true);
+ updateXPBar(mXpBar, false);
- return _("MP");
- }
- else if (id == EXP)
- {
- updateXPBar(mXpBar, false);
- return _("Exp");
- }
- else if (id == MONEY)
- {
- int money = player_node->getMoney();
- mMoneyLabel->setCaption(strprintf(_("Money: %s"),
- Units::formatCurrency(money).c_str()));
- mMoneyLabel->adjustSize();
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"),
+ Units::formatCurrency(PlayerInfo::getAttribute(MONEY)).c_str()));
+ mMoneyLabel->adjustSize();
+ mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"),
+ PlayerInfo::getAttribute(CHAR_POINTS)));
+ mCharacterPointsLabel->adjustSize();
- return _("Money");
- }
- else if (id == Net::getPlayerHandler()->getJobLocation())
- {
- mJobLvlLabel->setCaption(strprintf(_("Job: %d"),
- player_node->getAttributeBase(id)));
- mJobLvlLabel->adjustSize();
-
- updateProgressBar(mJobBar, id, false);
+ mLvlLabel->setCaption(strprintf(_("Level: %d"),
+ PlayerInfo::getAttribute(LEVEL)));
+ mLvlLabel->adjustSize();
+}
- return _("Job");
- }
- else if (id == CHAR_POINTS)
+void StatusWindow::event(const std::string &channel, const Mana::Event &event)
+{
+ if (event.getName() == "UpdateAttribute")
{
- mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"),
- player_node->getCharacterPoints()));
- mCharacterPointsLabel->adjustSize();
-
- if (Net::getPlayerHandler()->canCorrectAttributes())
- {
- mCorrectionPointsLabel->setCaption(strprintf(_("Correction points: %d"),
- player_node->getCorrectionPoints()));
- mCorrectionPointsLabel->adjustSize();
- }
-
- for (Attrs::iterator it = mAttrs.begin(); it != mAttrs.end(); it++)
+ switch(event.getInt("id"))
{
- it->second->update();
+ case HP: case MAX_HP:
+ updateHPBar(mHpBar, true);
+ break;
+
+ case MP: case MAX_MP:
+ updateMPBar(mMpBar, true);
+ break;
+
+ case EXP: case EXP_NEEDED:
+ updateXPBar(mXpBar, false);
+ break;
+
+ case MONEY:
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"),
+ Units::formatCurrency(event.getInt("value")).c_str()));
+ mMoneyLabel->adjustSize();
+ break;
+
+ case CHAR_POINTS:
+ mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"),
+ event.getInt("value")));
+ mCharacterPointsLabel->adjustSize();
+ // Update all attributes
+ for (Attrs::iterator it = mAttrs.begin(); it != mAttrs.end(); it++)
+ it->second->update();
+ break;
+
+ case CORR_POINTS:
+ mCorrectionPointsLabel->setCaption(strprintf(_("Correction points: %d"),
+ event.getInt("value")));
+ mCorrectionPointsLabel->adjustSize();
+ // Update all attributes
+ for (Attrs::iterator it = mAttrs.begin(); it != mAttrs.end(); it++)
+ it->second->update();
+ break;
+
+ case LEVEL:
+ mLvlLabel->setCaption(strprintf(_("Level: %d"),
+ event.getInt("value")));
+ mLvlLabel->adjustSize();
+ break;
}
}
- else if (id == LEVEL)
+ else if (event.getName() == "UpdateStat")
{
- mLvlLabel->setCaption(strprintf(_("Level: %d"),
- player_node->getLevel()));
- mLvlLabel->adjustSize();
+ int id = event.getInt("id");
+ if (id == Net::getPlayerHandler()->getJobLocation())
+ {
- return _("Level");
- }
- else
- {
- Attrs::iterator it = mAttrs.find(id);
+ mJobLvlLabel->setCaption(strprintf(_("Job: %d"),
+ PlayerInfo::getStatBase(id)));
+ mJobLvlLabel->adjustSize();
- if (it != mAttrs.end())
+ updateProgressBar(mJobBar, id, false);
+ }
+ else
{
- return it->second->update();
+ Attrs::iterator it = mAttrs.find(id);
+ if (it != mAttrs.end())
+ {
+ it->second->update();
+ }
}
}
-
- return "";
}
void StatusWindow::setPointsNeeded(int id, int needed)
@@ -317,15 +318,15 @@ void StatusWindow::updateHPBar(ProgressBar *bar, bool showMax)
return;
if (showMax)
- bar->setText(toString(player_node->getHp()) +
- "/" + toString(player_node->getMaxHp()));
+ bar->setText(toString(PlayerInfo::getAttribute(HP)) +
+ "/" + toString(PlayerInfo::getAttribute(MAX_HP)));
else
- bar->setText(toString(player_node->getHp()));
+ bar->setText(toString(PlayerInfo::getAttribute(HP)));
float prog = 1.0;
- if (player_node->getMaxHp() > 0)
- prog = (float) player_node->getHp() / player_node->getMaxHp();
+ if (PlayerInfo::getAttribute(MAX_HP) > 0)
+ prog = (float) PlayerInfo::getAttribute(HP) / PlayerInfo::getAttribute(MAX_HP);
bar->setProgress(prog);
}
@@ -335,15 +336,15 @@ void StatusWindow::updateMPBar(ProgressBar *bar, bool showMax)
return;
if (showMax)
- bar->setText(toString(player_node->getMP()) +
- "/" + toString(player_node->getMaxMP()));
+ bar->setText(toString(PlayerInfo::getAttribute(MP)) +
+ "/" + toString(PlayerInfo::getAttribute(MAX_MP)));
else
- bar->setText(toString(player_node->getMP()));
+ bar->setText(toString(PlayerInfo::getAttribute(MP)));
float prog = 1.0f;
- if (player_node->getMaxMP() > 0)
- prog = (float) player_node->getMP() / player_node->getMaxMP();
+ if (PlayerInfo::getAttribute(MAX_MP) > 0)
+ prog = (float) PlayerInfo::getAttribute(MP) / PlayerInfo::getAttribute(MAX_MP);
if (Net::getPlayerHandler()->canUseMagic())
bar->setProgressPalette(Theme::PROG_MP);
@@ -382,13 +383,13 @@ void StatusWindow::updateXPBar(ProgressBar *bar, bool percent)
if (!bar)
return;
- updateProgressBar(bar, player_node->getExp(),
- player_node->getExpNeeded(), percent);
+ updateProgressBar(bar, PlayerInfo::getAttribute(EXP),
+ PlayerInfo::getAttribute(EXP_NEEDED), percent);
}
void StatusWindow::updateProgressBar(ProgressBar *bar, int id, bool percent)
{
- std::pair<int, int> exp = player_node->getExperience(id);
+ std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
updateProgressBar(bar, exp.first, exp.second, percent);
}
@@ -413,8 +414,8 @@ AttrDisplay::~AttrDisplay()
std::string AttrDisplay::update()
{
- int base = player_node->getAttributeBase(mId);
- int bonus = player_node->getAttributeEffective(mId) - base;
+ int base = PlayerInfo::getStatBase(mId);
+ int bonus = PlayerInfo::getStatMod(mId);
std::string value = toString(base);
if (bonus)
value += strprintf(" (%+d)", bonus);
@@ -478,9 +479,9 @@ std::string ChangeDisplay::update()
if (mDec)
{
- mDec->setEnabled(player_node->getCorrectionPoints());
+ mDec->setEnabled(PlayerInfo::getAttribute(CORR_POINTS));
}
- mInc->setEnabled(player_node->getCharacterPoints() >= mNeeded &&
+ mInc->setEnabled(PlayerInfo::getAttribute(CHAR_POINTS) >= mNeeded &&
mNeeded > 0);
return AttrDisplay::update();
@@ -498,24 +499,25 @@ void ChangeDisplay::action(const gcn::ActionEvent &event)
if (Net::getPlayerHandler()->canCorrectAttributes() &&
event.getSource() == mDec)
{
- int newcorpoints = player_node->getCorrectionPoints() - 1;
- player_node->setCorrectionPoints(newcorpoints);
- int newpoints = player_node->getCharacterPoints() + 1;
- player_node->setCharacterPoints(newpoints);
- int newbase = player_node->getAttributeBase(mId) - 1;
- player_node->setAttributeBase(mId, newbase);
- int newmod = player_node->getAttributeEffective(mId) - 1;
- player_node->setAttributeEffective(mId, newmod);
+ int newcorpoints = PlayerInfo::getAttribute(CORR_POINTS) - 1;
+ PlayerInfo::setAttribute(CORR_POINTS, newcorpoints);
+
+ int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) + 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, newpoints);
+
+ int newbase = PlayerInfo::getStatBase(mId) - 1;
+ PlayerInfo::setStatBase(mId, newbase);
+
Net::getPlayerHandler()->decreaseAttribute(mId);
}
else if (event.getSource() == mInc)
{
- int newpoints = player_node->getCharacterPoints() - 1;
- player_node->setCharacterPoints(newpoints);
- int newbase = player_node->getAttributeBase(mId) + 1;
- player_node->setAttributeBase(mId, newbase);
- int newmod = player_node->getAttributeEffective(mId) + 1;
- player_node->setAttributeEffective(mId, newmod);
+ int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, newpoints);
+
+ int newbase = PlayerInfo::getStatBase(mId) + 1;
+ PlayerInfo::setStatBase(mId, newbase);
+
Net::getPlayerHandler()->increaseAttribute(mId);
}
}
diff --git a/src/gui/statuswindow.h b/src/gui/statuswindow.h
index a1fc4b4b..5be09b6a 100644
--- a/src/gui/statuswindow.h
+++ b/src/gui/statuswindow.h
@@ -23,6 +23,7 @@
#define STATUS_H
#include "guichanfwd.h"
+#include "listener.h"
#include "gui/widgets/window.h"
@@ -40,24 +41,15 @@ class VertContainer;
*
* \ingroup Interface
*/
-class StatusWindow : public Window
+class StatusWindow : public Window, public Mana::Listener
{
public:
- enum { // Some update constants
- HP = -1,
- MP = -2,
- EXP = -3,
- MONEY = -4,
- CHAR_POINTS = -5,
- LEVEL = -6
- };
-
/**
* Constructor.
*/
StatusWindow();
- std::string update(int id);
+ void event(const std::string &channel, const Mana::Event &event);
void setPointsNeeded(int id, int needed);
diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp
index dcb38e8e..d500999e 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -24,6 +24,7 @@
#include "inventory.h"
#include "item.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "units.h"
#include "gui/inventorywindow.h"
@@ -59,7 +60,7 @@ TradeWindow::TradeWindow():
mMyInventory(new Inventory(Inventory::TRADE)),
mPartnerInventory(new Inventory(Inventory::TRADE)),
mStatus(PROPOSING)
-{
+{
setWindowName("Trade");
setResizable(true);
setCloseButton(true);
@@ -96,7 +97,7 @@ TradeWindow::TradeWindow():
mMoneyLabel = new Label(strprintf(_("You get %s"), ""));
gcn::Label *mMoneyLabel2 = new Label(_("You give:"));
-
+
mMoneyField = new TextField;
mMoneyField->setWidth(40);
mMoneyChangeButton = new Button(_("Change"), "money", this);
@@ -310,7 +311,7 @@ void TradeWindow::action(const gcn::ActionEvent &event)
return;
int v = atoi(mMoneyField->getText().c_str());
- int curMoney = player_node->getMoney();
+ int curMoney = PlayerInfo::getAttribute(MONEY);
if (v > curMoney)
{
localChatTab->chatLog(_("You don't have enough money."),
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 15047f5a..511b5ed6 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -43,7 +43,6 @@
#include "gui/ministatus.h"
#include "gui/okdialog.h"
#include "gui/skilldialog.h"
-#include "gui/statuswindow.h"
#include "gui/theme.h"
#include "gui/userpalette.h"
@@ -84,16 +83,7 @@ LocalPlayer::LocalPlayer(int id, int subtype):
mAttackRange(0),
mTargetTime(-1),
mLastTarget(-1),
- mCharacterPoints(0),
- mCorrectionPoints(0),
mSpecialRechargeUpdateNeeded(0),
- mLevel(1),
- mExp(0), mExpNeeded(0),
- mMp(0), mMaxMp(0),
- mMoney(0),
- mTotalWeight(1), mMaxWeight(1),
- mHp(1), mMaxHp(1),
- mSkillPoints(0),
mTarget(NULL),
mPlayerFollowed(""),
mPickUpTarget(NULL),
@@ -1054,189 +1044,6 @@ void LocalPlayer::stopAttack()
mLastTarget = -1;
}
-void LocalPlayer::raiseAttribute(int attr)
-{
- // we assume that the server allows the change.
- // When not we will undo it later.
- mCharacterPoints--;
- IntMap::iterator it = mAttributeBase.find(attr);
- if (it != mAttributeBase.end())
- (*it).second++;
- Net::getPlayerHandler()->increaseAttribute(attr);
-}
-
-void LocalPlayer::lowerAttribute(int attr)
-{
- // we assume that the server allows the change.
- // When not we will undo it later.
- mCorrectionPoints--;
- mCharacterPoints++;
- IntMap::iterator it = mAttributeBase.find(attr);
- if (it != mAttributeBase.end())
- (*it).second--;
- Net::getPlayerHandler()->decreaseAttribute(attr);
-}
-
-void LocalPlayer::setTotalWeight(int value)
-{
- mTotalWeight = value;
-
- inventoryWindow->updateWeight();
-}
-
-void LocalPlayer::setMaxWeight(int value)
-{
- mMaxWeight = value;
-
- inventoryWindow->updateWeight();
-}
-
-void LocalPlayer::setAttributeBase(int num, int value, bool notify)
-{
- int old = mAttributeBase[num];
-
- mAttributeBase[num] = value;
- if (skillDialog)
- {
- if (skillDialog->update(num).empty() || !(value > old))
- return;
-
- if (old != 0 && notify)
- effectManager->trigger(1, this);
- }
-
- if (statusWindow)
- statusWindow->update(num);
-}
-
-void LocalPlayer::setAttributeEffective(int num, int value)
-{
- mAttributeEffective[num] = value;
- if (skillDialog)
- skillDialog->update(num);
-
- if (statusWindow)
- statusWindow->update(num);
-}
-
-void LocalPlayer::setCharacterPoints(int n)
-{
- mCharacterPoints = n;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::CHAR_POINTS);
-}
-
-void LocalPlayer::setCorrectionPoints(int n)
-{
- mCorrectionPoints = n;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::CHAR_POINTS);
-}
-
-void LocalPlayer::setSkillPoints(int points)
-{
- mSkillPoints = points;
- if (skillDialog)
- skillDialog->update();
-}
-
-void LocalPlayer::setExperience(int skill, int current, int next, bool notify)
-{
- 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 && notify && cur.first != -1 && diff > 0 && !name.empty())
- {
- addMessageToQueue(strprintf("%d %s xp", diff, name.c_str()));
- }
-
- if (statusWindow)
- statusWindow->update(skill);
-}
-
-std::pair<int, int> LocalPlayer::getExperience(int skill)
-{
- return mSkillExp[skill];
-}
-
-void LocalPlayer::setHp(int value)
-{
- mHp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::HP);
-}
-
-void LocalPlayer::setMaxHp(int value)
-{
- mMaxHp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::HP);
-}
-
-void LocalPlayer::setLevel(int value)
-{
- mLevel = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::LEVEL);
-}
-
-void LocalPlayer::setExp(int value, bool notify)
-{
- if (mMap && notify && value > mExp)
- {
- addMessageToQueue(toString(value - mExp) + " xp");
- }
- mExp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::EXP);
-}
-
-void LocalPlayer::setExpNeeded(int value)
-{
- mExpNeeded = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::EXP);
-}
-
-void LocalPlayer::setMP(int value)
-{
- mMp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
-}
-
-void LocalPlayer::setMaxMP(int value)
-{
- mMaxMp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
-}
-
-void LocalPlayer::setMoney(int value)
-{
- mMoney = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MONEY);
-}
-
void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount)
{
if (!amount)
diff --git a/src/localplayer.h b/src/localplayer.h
index 403b4530..c087c727 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -259,16 +259,6 @@ class LocalPlayer : public Being, public ActorSpriteListener
*/
void stopWalking(bool sendToServer = true);
- /**
- * Uses a character point to raise an attribute
- */
- void raiseAttribute(int attr);
-
- /**
- * Uses a correction point to lower an attribute
- */
- void lowerAttribute(int attr);
-
void toggleSit();
void emote(Uint8 emotion);
@@ -277,85 +267,6 @@ class LocalPlayer : public Being, public ActorSpriteListener
*/
void pickedUp(const ItemInfo &itemInfo, int amount);
- int getHp() const
- { return mHp; }
-
- int getMaxHp() const
- { return mMaxHp; }
-
- void setHp(int value);
-
- void setMaxHp(int value);
-
- int getLevel() const
- { return mLevel; }
-
- void setLevel(int value);
-
- void setExp(int value, bool notify = true);
-
- int getExp() const
- { return mExp; }
-
- void setExpNeeded(int value);
-
- int getExpNeeded() const
- { return mExpNeeded; }
-
- void setMP(int value);
-
- int getMP() const
- { return mMp; }
-
- void setMaxMP(int value);
-
- int getMaxMP() const
- { return mMaxMp; }
-
- int getMoney() const
- { return mMoney; }
-
- void setMoney(int value);
-
- int getTotalWeight() const
- { return mTotalWeight; }
-
- void setTotalWeight(int value);
-
- int getMaxWeight() const
- { return mMaxWeight; }
-
- void setMaxWeight(int value);
-
- int getAttributeBase(int num)
- { return mAttributeBase[num]; }
-
- void setAttributeBase(int num, int value, bool notify = true);
-
- int getAttributeEffective(int num)
- { return mAttributeEffective[num]; }
-
- void setAttributeEffective(int num, int value);
-
- int getCharacterPoints() const
- { return mCharacterPoints; }
-
- void setCharacterPoints(int n);
-
- int getCorrectionPoints() const
- { return mCorrectionPoints; }
-
- void setCorrectionPoints(int n);
-
- int getSkillPoints() const
- { return mSkillPoints; }
-
- void setSkillPoints(int points);
-
- void setExperience(int skill, int current, int next, bool notify = true);
-
- std::pair<int, int> getExperience(int skill);
-
/** Tells that the path has been set by mouse. */
void pathSetByMouse()
{ mPathSetByMouse = true; }
@@ -434,24 +345,9 @@ class LocalPlayer : public Being, public ActorSpriteListener
int mLastTarget; /** Time stamp of last targeting action, -1 if none. */
// Character status:
- typedef std::map<int, int> IntMap;
- IntMap mAttributeBase;
- IntMap mAttributeEffective;
- std::map<int, std::pair<int, int> > mSkillExp;
- int mCharacterPoints;
- int mCorrectionPoints;
int mLevelProgress;
std::map<int, Special> mSpecials;
char mSpecialRechargeUpdateNeeded;
- int mLevel;
- int mExp, mExpNeeded;
- int mMp, mMaxMp;
- int mMoney;
- int mTotalWeight;
- int mMaxWeight;
- int mHp;
- int mMaxHp;
- int mSkillPoints;
int mGMLevel;
diff --git a/src/net/charhandler.h b/src/net/charhandler.h
index e3c8cfd6..ba06f551 100644
--- a/src/net/charhandler.h
+++ b/src/net/charhandler.h
@@ -24,13 +24,13 @@
#include "localplayer.h"
#include "logindata.h"
+#include "playerinfo.h"
#include <iosfwd>
#include <vector>
class CharCreateDialog;
class CharSelectDialog;
-class LocalPlayer;
namespace Net {
@@ -52,6 +52,7 @@ struct Character
int slot; /**< The index in the list of characters */
LocalPlayer *dummy; /**< A dummy representing this character */
+ PlayerInfoBackend data;
};
typedef std::list<Character*> Characters;
diff --git a/src/net/manaserv/buysellhandler.cpp b/src/net/manaserv/buysellhandler.cpp
index cfd55e2e..c1efca0d 100644
--- a/src/net/manaserv/buysellhandler.cpp
+++ b/src/net/manaserv/buysellhandler.cpp
@@ -23,7 +23,7 @@
#include "actorspritemanager.h"
#include "item.h"
-#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/buy.h"
#include "gui/chat.h"
@@ -63,7 +63,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
BuyDialog* dialog = new BuyDialog(npcId);
dialog->reset();
- dialog->setMoney(player_node->getMoney());
+ dialog->setMoney(PlayerInfo::getAttribute(MONEY));
while (msg.getUnreadLength())
{
@@ -80,7 +80,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
SellDialog* dialog = new SellDialog(npcId);
dialog->reset();
- dialog->setMoney(player_node->getMoney());
+ dialog->setMoney(PlayerInfo::getAttribute(MONEY));
while (msg.getUnreadLength())
{
diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp
index e2c67f35..7e401455 100644
--- a/src/net/manaserv/charhandler.cpp
+++ b/src/net/manaserv/charhandler.cpp
@@ -233,6 +233,7 @@ void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg)
// Prevent the selected local player from being deleted
player_node = mSelectedCharacter->dummy;
+ PlayerInfo::setBackend(mSelectedCharacter->data);
mSelectedCharacter->dummy = 0;
Client::setState(STATE_CONNECT_GAME);
@@ -355,14 +356,14 @@ void CharHandler::updateCharacters()
player->setGender(info.gender);
player->setSprite(SPRITE_HAIR, info.hairStyle * -1,
ColorDB::get(info.hairColor));
- player->setLevel(info.level);
- player->setCharacterPoints(info.characterPoints);
- player->setCorrectionPoints(info.correctionPoints);
- player->setMoney(info.money);
+ character->data.mAttributes[LEVEL] = info.level;
+ character->data.mAttributes[CHAR_POINTS] = info.characterPoints;
+ character->data.mAttributes[CORR_POINTS] = info.correctionPoints;
+ character->data.mAttributes[MONEY] = info.money;
for (int i = 0; i < 7; i++)
{
- player->setAttributeBase(i, info.attribute[i], false);
+ character->data.mStats[i].base = info.attribute[i];
}
mCharacters.push_back(character);
diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp
index bf892b3a..e1559d16 100644
--- a/src/net/manaserv/generalhandler.cpp
+++ b/src/net/manaserv/generalhandler.cpp
@@ -168,7 +168,7 @@ void GeneralHandler::guiWindowsLoaded()
inventoryWindow->setSplitAllowed(true);
skillDialog->loadSkills("mana-skills.xml");
- player_node->setExpNeeded(100);
+ PlayerInfo::setAttribute(EXP_NEEDED, 100);
Stats::informStatusWindow();
}
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp
index 76fca7ae..bf5682c7 100644
--- a/src/net/manaserv/inventoryhandler.cpp
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -26,6 +26,7 @@
#include "item.h"
#include "itemshortcut.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/chat.h"
@@ -70,7 +71,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
unsigned int slot = msg.readInt8();
if (slot == 255)
{
- player_node->setMoney(msg.readInt32());
+ PlayerInfo::setAttribute(MONEY, msg.readInt32());
continue;
}
diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp
index c2803ce1..31074bdb 100644
--- a/src/net/manaserv/playerhandler.cpp
+++ b/src/net/manaserv/playerhandler.cpp
@@ -28,6 +28,7 @@
#include "localplayer.h"
#include "log.h"
#include "particle.h"
+#include "playerinfo.h"
#include "gui/chat.h"
#include "gui/gui.h"
@@ -111,13 +112,13 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
if (stat == BASE_ATTR_HP)
{
- player_node->setMaxHp(base);
- player_node->setHp(value);
+ PlayerInfo::setAttribute(MAX_HP, base);
+ PlayerInfo::setAttribute(HP, value);
}
else
{
- player_node->setAttributeBase(stat, base);
- player_node->setAttributeEffective(stat, value);
+ PlayerInfo::setStatBase(stat, base);
+ PlayerInfo::setStatMod(stat, value - base);
}
}
} break;
@@ -131,15 +132,15 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
int current = msg.readInt32();
int next = msg.readInt32();
- player_node->setExperience(skill, current, next);
+ PlayerInfo::setStatExperience(skill, current, next);
}
} break;
case GPMSG_LEVELUP:
{
- player_node->setLevel(msg.readInt16());
- player_node->setCharacterPoints(msg.readInt16());
- player_node->setCorrectionPoints(msg.readInt16());
+ PlayerInfo::setAttribute(LEVEL, msg.readInt16());
+ PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
+ PlayerInfo::setAttribute(CORR_POINTS, msg.readInt16());
Particle* effect = particleEngine->addEffect("graphics/particles/levelup.particle.xml", 0, 0);
player_node->controlParticle(effect);
} break;
@@ -147,7 +148,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
case GPMSG_LEVEL_PROGRESS:
{
- player_node->setExp(msg.readInt8(), false);
+ PlayerInfo::setAttribute(EXP, msg.readInt8());
} break;
@@ -171,18 +172,19 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
// has to be correct. The server is always right!
// undo attribute change and set points to 0
logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum);
- int attrValue = player_node->getAttributeBase(attrNum) - 1;
- player_node->setCharacterPoints(0);
- player_node->setAttributeBase(attrNum, attrValue);
+ int attrValue = PlayerInfo::getStatBase(attrNum) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, 0);
+ PlayerInfo::setStatBase(attrNum, attrValue);
} break;
case ATTRIBMOD_DENIED:
{
// undo attribute change
logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum);
- int points = player_node->getCharacterPoints() - 1;
- player_node->setCharacterPoints(points);
- int attrValue = player_node->getAttributeBase(attrNum) - 1;
- player_node->setAttributeBase(attrNum, attrValue);
+ int points = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, points);
+
+ int attrValue = PlayerInfo::getStatBase(attrNum) - 1;
+ PlayerInfo::setStatBase(attrNum, attrValue);
} break;
}
} break;
@@ -207,21 +209,23 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
// has to be correct. The server is always right!
// undo attribute change and set points to 0
logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum);
- int attrValue = player_node->getAttributeBase(attrNum) + 1;
- player_node->setCorrectionPoints(0);
- player_node->setAttributeBase(attrNum, attrValue);
+ int attrValue = PlayerInfo::getStatBase(attrNum) + 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, 0);
+ PlayerInfo::setStatBase(attrNum, attrValue);
break;
} break;
case ATTRIBMOD_DENIED:
{
// undo attribute change
logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum);
- int charaPoints = player_node->getCharacterPoints() - 1;
- player_node->setCharacterPoints(charaPoints);
- int correctPoints = player_node->getCorrectionPoints() + 1;
- player_node->setCorrectionPoints(correctPoints);
- int attrValue = player_node->getAttributeBase(attrNum) + 1;
- player_node->setAttributeBase(attrNum, attrValue);
+ int charaPoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
+ PlayerInfo::setAttribute(CHAR_POINTS, charaPoints);
+
+ int correctPoints = PlayerInfo::getAttribute(CORR_POINTS) + 1;
+ PlayerInfo::setAttribute(CORR_POINTS, correctPoints);
+
+ int attrValue = PlayerInfo::getStatBase(attrNum) + 1;
+ PlayerInfo::setStatBase(attrNum, attrValue);
} break;
}
diff --git a/src/net/tmwa/buysellhandler.cpp b/src/net/tmwa/buysellhandler.cpp
index 4a478396..cd12939b 100644
--- a/src/net/tmwa/buysellhandler.cpp
+++ b/src/net/tmwa/buysellhandler.cpp
@@ -25,6 +25,7 @@
#include "inventory.h"
#include "item.h"
#include "localplayer.h"
+#include "playerinfo.h"
#include "gui/buy.h"
#include "gui/buysell.h"
@@ -72,7 +73,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
msg.readInt16(); // length
n_items = (msg.getLength() - 4) / 11;
mBuyDialog = new BuyDialog(mNpcId);
- mBuyDialog->setMoney(player_node->getMoney());
+ mBuyDialog->setMoney(PlayerInfo::getAttribute(MONEY));
for (int k = 0; k < n_items; k++)
{
@@ -90,7 +91,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
if (n_items > 0)
{
SellDialog *dialog = new SellDialog(mNpcId);
- dialog->setMoney(player_node->getMoney());
+ dialog->setMoney(PlayerInfo::getAttribute(MONEY));
for (int k = 0; k < n_items; k++)
{
@@ -119,7 +120,7 @@ void BuySellHandler::handleMessage(Net::MessageIn &msg)
{
// Reset player money since buy dialog already assumed purchase
// would go fine
- mBuyDialog->setMoney(player_node->getMoney());
+ mBuyDialog->setMoney(PlayerInfo::getAttribute(MONEY));
localChatTab->chatLog(_("Unable to buy."), BY_SERVER);
}
break;
diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp
index 8f15691c..820864ce 100644
--- a/src/net/tmwa/charserverhandler.cpp
+++ b/src/net/tmwa/charserverhandler.cpp
@@ -83,12 +83,10 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
for (int i = 0; i < count; ++i)
{
Net::Character *character = new Net::Character;
- int slot;
- character->dummy = readPlayerData(msg, &slot);
- character->slot = slot;
+ readPlayerData(msg, character);
mCharacters.push_back(character);
logger->log("CharServer: Player: %s (%d)",
- character->dummy->getName().c_str(), slot);
+ character->dummy->getName().c_str(), character->slot);
}
Client::setState(STATE_CHAR_SELECT);
@@ -115,9 +113,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
case SMSG_CHAR_CREATE_SUCCEEDED:
{
Net::Character *character = new Net::Character;
- int slot;
- character->dummy = readPlayerData(msg, &slot);
- character->slot = slot;
+ readPlayerData(msg, character);
mCharacters.push_back(character);
updateCharSelectDialog();
@@ -162,6 +158,8 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
// Prevent the selected local player from being deleted
player_node = mSelectedCharacter->dummy;
+ PlayerInfo::setBackend(mSelectedCharacter->data);
+
mSelectedCharacter->dummy = 0;
delete_all(mCharacters);
@@ -191,7 +189,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
}
}
-LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot)
+void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *character)
{
const Token &token =
static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();
@@ -199,30 +197,37 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot)
LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0);
tempPlayer->setGender(token.sex);
- tempPlayer->setExp(msg.readInt32());
- tempPlayer->setMoney(msg.readInt32());
- tempPlayer->setExperience(JOB, msg.readInt32(), 1);
+ character->data.mAttributes[EXP] = msg.readInt32();
+ character->data.mAttributes[MONEY] = msg.readInt32();
+ character->data.mStats[JOB].exp = msg.readInt32();
+
int temp = msg.readInt32();
- tempPlayer->setAttributeBase(JOB, temp, false);
- tempPlayer->setAttributeEffective(JOB, temp);
+ character->data.mStats[JOB].base = temp;
+ character->data.mStats[JOB].mod = temp;
+
tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16());
tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16());
tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16());
tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16());
+
msg.readInt32(); // option
msg.readInt32(); // karma
msg.readInt32(); // manner
msg.skip(2); // unknown
- tempPlayer->setHp(msg.readInt16());
- tempPlayer->setMaxHp(msg.readInt16());
- tempPlayer->setMP(msg.readInt16());
- tempPlayer->setMaxMP(msg.readInt16());
+
+ character->data.mAttributes[HP] = msg.readInt16();
+ character->data.mAttributes[MAX_HP] = msg.readInt16();
+ character->data.mAttributes[MP] = msg.readInt16();
+ character->data.mAttributes[MAX_MP] = msg.readInt16();
+
msg.readInt16(); // speed
tempPlayer->setSubtype(msg.readInt16()); // class (used for race)
int hairStyle = msg.readInt16();
Uint16 weapon = msg.readInt16();
tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true);
- tempPlayer->setLevel(msg.readInt16());
+
+ character->data.mAttributes[LEVEL] = msg.readInt16();
+
msg.readInt16(); // skill point
tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); // head bottom
tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16());
@@ -231,12 +236,14 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot)
tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(msg.readInt16()));
tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16());
tempPlayer->setName(msg.readString(24));
+
+ character->dummy = tempPlayer;
+
for (int i = 0; i < 6; i++)
- tempPlayer->setAttributeBase(i + STR, msg.readInt8(), false);
- *slot = msg.readInt8(); // character slot
- msg.readInt8(); // unknown
+ character->data.mStats[i + STR].base = msg.readInt8();
- return tempPlayer;
+ character->slot = msg.readInt8(); // character slot
+ msg.readInt8(); // unknown
}
void CharServerHandler::setCharSelectDialog(CharSelectDialog *window)
diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h
index 52bac811..2076cbae 100644
--- a/src/net/tmwa/charserverhandler.h
+++ b/src/net/tmwa/charserverhandler.h
@@ -72,7 +72,7 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler
void connect();
private:
- LocalPlayer *readPlayerData(Net::MessageIn &msg, int *slot);
+ void readPlayerData(Net::MessageIn &msg, Net::Character *character);
};
} // namespace TmwAthena
diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp
index 735da082..0ada96d7 100644
--- a/src/net/tmwa/playerhandler.cpp
+++ b/src/net/tmwa/playerhandler.cpp
@@ -24,6 +24,7 @@
#include "game.h"
#include "localplayer.h"
#include "log.h"
+#include "playerinfo.h"
#include "units.h"
#include "gui/buy.h"
@@ -53,9 +54,6 @@ extern OkDialog *deathNotice;
// everything beyond will reset the port hard.
static const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
-#define ATTR_BONUS(atr) \
-(player_node->getAttributeEffective(atr) - player_node->getAttributeBase(atr))
-
// TODO Move somewhere else
namespace {
@@ -236,17 +234,17 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
player_node->setWalkSpeed(Vector(value, value, 0));
break;
case 0x0004: break; // manner
- case 0x0005: player_node->setHp(value); break;
- case 0x0006: player_node->setMaxHp(value); break;
- case 0x0007: player_node->setMP(value); break;
- case 0x0008: player_node->setMaxMP(value); break;
- case 0x0009: player_node->setCharacterPoints(value); break;
- case 0x000b: player_node->setLevel(value); break;
- case 0x000c: player_node->setSkillPoints(value); break;
+ case 0x0005: PlayerInfo::setAttribute(HP, value); break;
+ case 0x0006: PlayerInfo::setAttribute(MAX_HP, value); break;
+ case 0x0007: PlayerInfo::setAttribute(MP, value); break;
+ case 0x0008: PlayerInfo::setAttribute(MAX_MP, value); break;
+ case 0x0009: PlayerInfo::setAttribute(CHAR_POINTS, value); break;
+ case 0x000b: PlayerInfo::setAttribute(LEVEL, value); break;
+ case 0x000c: PlayerInfo::setAttribute(SKILL_POINTS, value); break;
case 0x0018:
- if (value >= player_node->getMaxWeight() / 2 &&
- player_node->getTotalWeight() <
- player_node->getMaxWeight() / 2)
+ if (value >= PlayerInfo::getAttribute(MAX_WEIGHT) / 2 &&
+ PlayerInfo::getAttribute(TOTAL_WEIGHT) <
+ PlayerInfo::getAttribute(MAX_WEIGHT) / 2)
{
weightNotice = new OkDialog(_("Message"),
_("You are carrying more than "
@@ -255,59 +253,37 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
weightNotice->addActionListener(
&weightListener);
}
- player_node->setTotalWeight(value);
+ PlayerInfo::setAttribute(TOTAL_WEIGHT, value);
break;
- case 0x0019: player_node->setMaxWeight(value); break;
+ case 0x0019: PlayerInfo::setAttribute(MAX_WEIGHT, value); break;
- case 0x0029: player_node->setAttributeEffective(ATK, value
- + ATTR_BONUS(ATK));
- player_node->setAttributeBase(ATK, value);
- break;
- case 0x002a: value += player_node->getAttributeBase(ATK);
- player_node->setAttributeEffective(ATK, value); break;
-
- case 0x002b: player_node->setAttributeEffective(MATK, value
- + ATTR_BONUS(MATK));
- player_node->setAttributeBase(MATK, value);
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
- break;
- case 0x002c: value += player_node->getAttributeBase(MATK);
- player_node->setAttributeEffective(MATK, value);
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
- break;
- case 0x002d: player_node->setAttributeEffective(DEF, value
- + ATTR_BONUS(DEF));
- player_node->setAttributeBase(DEF, value); break;
- case 0x002e: value += player_node->getAttributeBase(DEF);
- player_node->setAttributeEffective(DEF, value); break;
-
- case 0x002f: player_node->setAttributeEffective(MDEF, value
- + ATTR_BONUS(MDEF));
- player_node->setAttributeBase(MDEF, value); break;
- case 0x0030: value += player_node->getAttributeBase(MDEF);
- player_node->setAttributeEffective(MDEF, value); break;
-
- case 0x0031: player_node->setAttributeBase(HIT, value);
- player_node->setAttributeEffective(HIT, value); break;
-
- case 0x0032: player_node->setAttributeEffective(FLEE, value
- + ATTR_BONUS(FLEE));
- player_node->setAttributeBase(FLEE, value); break;
- case 0x0033: value += player_node->getAttributeBase(FLEE);
- player_node->setAttributeEffective(FLEE, value); break;
-
- case 0x0034: player_node->setAttributeBase(CRIT, value);
- player_node->setAttributeEffective(CRIT, value); break;
+ case 0x0029: PlayerInfo::setStatBase(ATK, value); break;
+ case 0x002a: PlayerInfo::setStatMod(ATK, value); break;
+
+ case 0x002b: PlayerInfo::setStatBase(MATK, value); break;
+ case 0x002c: PlayerInfo::setStatMod(MATK, value); break;
+
+ case 0x002d: PlayerInfo::setStatBase(DEF, value); break;
+ case 0x002e: PlayerInfo::setStatMod(DEF, value); break;
+
+ case 0x002f: PlayerInfo::setStatBase(MDEF, value); break;
+ case 0x0030: PlayerInfo::setStatMod(MDEF, value); break;
+
+ case 0x0031: PlayerInfo::setStatBase(HIT, value); break;
+
+ case 0x0032: PlayerInfo::setStatBase(FLEE, value); break;
+ case 0x0033: PlayerInfo::setStatMod(FLEE, value); break;
+
+ case 0x0034: PlayerInfo::setStatBase(CRIT, value); break;
case 0x0035: player_node->setAttackSpeed(value); break;
- case 0x0037: player_node->setAttributeBase(JOB, value);
- player_node->setAttributeEffective(JOB, value); break;
+
+ case 0x0037: PlayerInfo::setStatBase(JOB, value); break;
+
case 500: player_node->setGMLevel(value); break;
}
- if (player_node->getHp() == 0 && !deathNotice)
+ if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice)
{
deathNotice = new OkDialog(_("Message"),
randomDeathMessage(),
@@ -322,29 +298,29 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
switch (msg.readInt16())
{
case 0x0001:
- player_node->setExp(msg.readInt32());
+ PlayerInfo::setAttribute(EXP, msg.readInt32());
break;
case 0x0002:
- player_node->setExperience(JOB, msg.readInt32(),
- player_node->getExperience(JOB).second);
+ PlayerInfo::setStatExperience(JOB, msg.readInt32(),
+ PlayerInfo::getStatExperience(JOB).second);
break;
case 0x0014: {
- int curGp = player_node->getMoney();
- player_node->setMoney(msg.readInt32());
- if (player_node->getMoney() > curGp)
+ int oldMoney = PlayerInfo::getAttribute(MONEY);
+ int newMoney = msg.readInt32();
+ if (newMoney > oldMoney)
localChatTab->chatLog(strprintf(_("You picked up "
"%s."),
- Units::formatCurrency(player_node->getMoney()
- - curGp).c_str()), BY_SERVER);
+ Units::formatCurrency(newMoney - oldMoney).c_str()),
+ BY_SERVER);
}
break;
case 0x0016:
- player_node->setExpNeeded(msg.readInt32());
+ PlayerInfo::setAttribute(EXP_NEEDED, msg.readInt32());
break;
case 0x0017:
- player_node->setExperience(JOB,
- player_node->getExperience(JOB).first,
- msg.readInt32());
+ PlayerInfo::setStatExperience(JOB,
+ PlayerInfo::getStatExperience(JOB).first,
+ msg.readInt32());
break;
}
break;
@@ -355,8 +331,8 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
int base = msg.readInt32();
int bonus = msg.readInt32();
- player_node->setAttributeBase(type, base);
- player_node->setAttributeEffective(type, base + bonus);
+ PlayerInfo::setStatBase(type, base, false);
+ PlayerInfo::setStatMod(type, bonus);
}
break;
@@ -372,21 +348,17 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
BY_SERVER);
}
- int bonus = ATTR_BONUS(type);
-
- player_node->setAttributeBase(type, value);
- player_node->setAttributeEffective(type, value + bonus);
+ PlayerInfo::setStatBase(type, value);
}
break;
// Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
- player_node->setCharacterPoints(msg.readInt16());
+ PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
{
int val = msg.readInt8();
- player_node->setAttributeEffective(STR, val + ATTR_BONUS(STR));
- player_node->setAttributeBase(STR, val);
+ PlayerInfo::setStatBase(STR, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(STR, 0);
@@ -398,8 +370,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(AGI, val + ATTR_BONUS(AGI));
- player_node->setAttributeBase(AGI, val);
+ PlayerInfo::setStatBase(AGI, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(AGI, 0);
@@ -411,8 +382,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(VIT, val + ATTR_BONUS(VIT));
- player_node->setAttributeBase(VIT, val);
+ PlayerInfo::setStatBase(VIT, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(VIT, 0);
@@ -424,8 +394,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(INT, val + ATTR_BONUS(INT));
- player_node->setAttributeBase(INT, val);
+ PlayerInfo::setStatBase(INT, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(INT, 0);
@@ -437,8 +406,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(DEX, val + ATTR_BONUS(DEX));
- player_node->setAttributeBase(DEX, val);
+ PlayerInfo::setStatBase(DEX, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(DEX, 0);
@@ -450,8 +418,7 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
}
val = msg.readInt8();
- player_node->setAttributeEffective(LUK, val + ATTR_BONUS(LUK));
- player_node->setAttributeBase(LUK, val);
+ PlayerInfo::setStatBase(LUK, val);
if (val >= 99)
{
statusWindow->setPointsNeeded(LUK, 0);
@@ -462,39 +429,25 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
statusWindow->setPointsNeeded(LUK, msg.readInt8());
}
- val = msg.readInt16(); // ATK
- player_node->setAttributeBase(ATK, val);
- val += msg.readInt16(); // ATK bonus
- player_node->setAttributeEffective(ATK, val);
-
- val = msg.readInt16(); // MATK
- player_node->setAttributeBase(MATK, val);
- val += msg.readInt16(); // MATK bonus
- player_node->setAttributeEffective(MATK, val);
- statusWindow->update(StatusWindow::MP);
-
- val = msg.readInt16(); // DEF
- player_node->setAttributeBase(DEF, val);
- val += msg.readInt16(); // DEF bonus
- player_node->setAttributeEffective(DEF, val);
-
- val = msg.readInt16(); // MDEF
- player_node->setAttributeBase(MDEF, val);
- val += msg.readInt16(); // MDEF bonus
- player_node->setAttributeEffective(MDEF, val);
-
- val = msg.readInt16(); // HIT
- player_node->setAttributeBase(HIT, val);
- player_node->setAttributeEffective(HIT, val);
-
- val = msg.readInt16(); // FLEE
- player_node->setAttributeBase(FLEE, val);
- val += msg.readInt16(); // FLEE bonus
- player_node->setAttributeEffective(FLEE, val);
-
- val = msg.readInt16();
- player_node->setAttributeBase(CRIT, val);
- player_node->setAttributeEffective(CRIT, val);
+ PlayerInfo::setStatBase(ATK, msg.readInt16(), false);
+ PlayerInfo::setStatMod(ATK, msg.readInt16());
+
+ PlayerInfo::setStatBase(MATK, msg.readInt16(), false);
+ PlayerInfo::setStatMod(MATK, msg.readInt16());
+
+
+ PlayerInfo::setStatBase(DEF, msg.readInt16(), false);
+ PlayerInfo::setStatMod(DEF, msg.readInt16());
+
+ PlayerInfo::setStatBase(MDEF, msg.readInt16(), false);
+ PlayerInfo::setStatMod(MDEF, msg.readInt16());
+
+ PlayerInfo::setStatBase(HIT, msg.readInt16());
+
+ PlayerInfo::setStatBase(FLEE, msg.readInt16(), false);
+ PlayerInfo::setStatMod(FLEE, msg.readInt16());
+
+ PlayerInfo::setStatBase(CRIT, msg.readInt16());
}
msg.readInt16(); // manner
@@ -573,7 +526,7 @@ void PlayerHandler::decreaseAttribute(int attr)
void PlayerHandler::increaseSkill(int skillId)
{
- if (player_node->getSkillPoints() <= 0)
+ if (PlayerInfo::getAttribute(SKILL_POINTS) <= 0)
return;
MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST);
@@ -635,7 +588,7 @@ void PlayerHandler::ignoreAll(bool ignore)
bool PlayerHandler::canUseMagic()
{
- return player_node->getAttributeEffective(MATK) > 0;
+ return PlayerInfo::getStatEffective(MATK) > 0;
}
bool PlayerHandler::canCorrectAttributes()
diff --git a/src/net/tmwa/specialhandler.cpp b/src/net/tmwa/specialhandler.cpp
index c5f5d540..f147ef9b 100644
--- a/src/net/tmwa/specialhandler.cpp
+++ b/src/net/tmwa/specialhandler.cpp
@@ -21,8 +21,8 @@
#include "net/tmwa/specialhandler.h"
-#include "localplayer.h"
#include "log.h"
+#include "playerinfo.h"
#include "gui/skilldialog.h"
@@ -105,8 +105,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg)
msg.skip(24); // unused
int up = msg.readInt8();
- player_node->setAttributeBase(skillId, level);
- player_node->setAttributeEffective(skillId, level);
+ PlayerInfo::setStatBase(skillId, level);
skillDialog->setModifiable(skillId, up);
}
break;
@@ -119,8 +118,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg)
msg.readInt16(); // range
int up = msg.readInt8();
- player_node->setAttributeBase(skillId, level);
- player_node->setAttributeEffective(skillId, level);
+ PlayerInfo::setStatBase(skillId, level);
skillDialog->setModifiable(skillId, up);
}
break;
diff --git a/src/playerinfo.cpp b/src/playerinfo.cpp
new file mode 100644
index 00000000..203c26cc
--- /dev/null
+++ b/src/playerinfo.cpp
@@ -0,0 +1,140 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "playerinfo.h"
+
+#include "event.h"
+#include "eventmanager.h"
+
+PlayerInfoBackend PlayerInfo::mData;
+
+void PlayerInfo::setBackend(const PlayerInfoBackend &backend)
+{
+ mData = backend;
+}
+
+// ------------------------------- Attributes --------------------------------------
+
+int PlayerInfo::getAttribute(int id)
+{
+ IntMap::const_iterator it = mData.mAttributes.find(id);
+ if (it != mData.mAttributes.end())
+ return it->second;
+ else
+ return 0;
+}
+
+void PlayerInfo::setAttribute(int id, int value, bool notify)
+{
+ mData.mAttributes[id] = value;
+ if (notify)
+ triggerAttr(id);
+}
+
+// ------------------------------- Stats --------------------------------------
+
+int PlayerInfo::getStatBase(int id)
+{
+ StatMap::const_iterator it = mData.mStats.find(id);
+ if (it != mData.mStats.end())
+ return it->second.base;
+ else
+ return 0;
+}
+
+void PlayerInfo::setStatBase(int id, int value, bool notify)
+{
+ mData.mStats[id].base = value;
+ if (notify)
+ triggerStat(id);
+}
+
+int PlayerInfo::getStatMod(int id)
+{
+
+ StatMap::const_iterator it = mData.mStats.find(id);
+ if (it != mData.mStats.end())
+ return it->second.mod;
+ else
+ return 0;
+}
+
+void PlayerInfo::setStatMod(int id, int value, bool notify)
+{
+ mData.mStats[id].mod = value;
+ if (notify)
+ triggerStat(id);
+}
+
+int PlayerInfo::getStatEffective(int id)
+{
+ StatMap::const_iterator it = mData.mStats.find(id);
+ if (it != mData.mStats.end())
+ return it->second.base + it->second.mod;
+ else
+ return 0;
+}
+
+std::pair<int, int> PlayerInfo::getStatExperience(int id)
+{
+ StatMap::const_iterator it = mData.mStats.find(id);
+ int a, b;
+ if (it != mData.mStats.end())
+ {
+ a = it->second.exp;
+ b = it->second.expneed;
+ }
+ else
+ {
+ a = 0;
+ b = 0;
+ }
+ return std::pair<int, int>(a, b);
+}
+
+void PlayerInfo::setStatExperience(int id, int have, int need, bool notify)
+{
+ mData.mStats[id].exp = have;
+ mData.mStats[id].expneed = need;
+ if (notify)
+ triggerStat(id);
+}
+
+// ------------------------------- Triggers --------------------------------------
+
+void PlayerInfo::triggerAttr(int id)
+{
+ Mana::Event event("UpdateAttribute");
+ event.setInt("id", id);
+ event.setInt("value", mData.mAttributes.find(id)->second);
+ Mana::EventManager::trigger("Attributes", event);
+}
+
+void PlayerInfo::triggerStat(int id)
+{
+ StatMap::iterator it = mData.mStats.find(id);
+ Mana::Event event("UpdateStat");
+ event.setInt("id", id);
+ event.setInt("base", it->second.base);
+ event.setInt("mod", it->second.mod);
+ event.setInt("exp", it->second.exp);
+ event.setInt("expneeded", it->second.expneed);
+ Mana::EventManager::trigger("Attributes", event);
+}
diff --git a/src/playerinfo.h b/src/playerinfo.h
new file mode 100644
index 00000000..421e93bc
--- /dev/null
+++ b/src/playerinfo.h
@@ -0,0 +1,105 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PLAYERINFO_H
+#define PLAYERINFO_H
+
+#include <map>
+#include <string>
+
+enum Attribute
+{
+ LEVEL,
+ HP, MAX_HP,
+ MP, MAX_MP,
+ EXP, EXP_NEEDED,
+ MONEY,
+ TOTAL_WEIGHT, MAX_WEIGHT,
+ SKILL_POINTS,
+ CHAR_POINTS, CORR_POINTS
+};
+
+struct Stat
+{
+ int base;
+ int mod;
+ int exp;
+ int expneed;
+};
+
+typedef std::map<int, int> IntMap;
+typedef std::map<int, Stat> StatMap;
+
+struct PlayerInfoBackend
+{
+ public:
+ IntMap mAttributes;
+ StatMap mStats;
+};
+
+/**
+ * A database like class which holds global info about the localplayer
+ */
+class PlayerInfo
+{
+ // NOTE: All agruements for 'bool notify' is to determine if
+ // a event is to be triggered
+ public:
+ static void setBackend(const PlayerInfoBackend &backend);
+
+ /**
+ * Attributes for things like money and exp
+ */
+ static int getAttribute(int id);
+
+ static void setAttribute(int id, int value, bool notify = true);
+
+
+ /**
+ * Stats are modifiable attributes basicilly, like str, crit, trade
+ */
+
+ static int getStatBase(int id);
+
+ static void setStatBase(int id, int value, bool notify = true);
+
+ static int getStatMod(int id);
+
+ static void setStatMod(int id, int value, bool notify = true);
+
+ // Base + mod
+ static int getStatEffective(int id);
+
+ static void setStatLevel(int id, int value, bool notify = true);
+
+ static std::pair<int, int> getStatExperience(int id);
+
+ static void setStatExperience(int id, int have, int need, bool notify = true);
+
+ private:
+ // Triggers send events for action.
+ static void triggerAttr(int id);
+
+ static void triggerStat(int id);
+
+ static PlayerInfoBackend mData;
+};
+
+#endif