summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/Makefile.am3
-rw-r--r--src/being/localplayer.cpp56
-rw-r--r--src/being/localplayer.h8
-rw-r--r--src/being/playerinfo.cpp7
-rw-r--r--src/gui/windows/chatwindow.cpp56
-rw-r--r--src/gui/windows/chatwindow.h11
-rw-r--r--src/gui/windows/inventorywindow.cpp22
-rw-r--r--src/gui/windows/inventorywindow.h12
-rw-r--r--src/gui/windows/killstats.cpp25
-rw-r--r--src/gui/windows/killstats.h13
-rw-r--r--src/gui/windows/ministatuswindow.cpp52
-rw-r--r--src/gui/windows/ministatuswindow.h8
-rw-r--r--src/gui/windows/statuswindow.cpp137
-rw-r--r--src/gui/windows/statuswindow.h11
-rw-r--r--src/listeners/attributelistener.cpp61
-rw-r--r--src/listeners/attributelistener.h51
-rw-r--r--src/listeners/baselistener.hpp36
18 files changed, 377 insertions, 195 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 20500cdcb..2e94548ef 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -603,6 +603,9 @@ SET(SRCS
being/actorsprite.cpp
being/actorsprite.h
listeners/actorspritelistener.h
+ listeners/attributelistener.cpp
+ listeners/attributelistener.h
+ listeners/baselistener.hpp
actormanager.cpp
actormanager.h
animatedsprite.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 72a28fb0b..409847682 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -685,6 +685,9 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \
being/actorsprite.cpp \
being/actorsprite.h \
listeners/actorspritelistener.h \
+ listeners/attributelistener.cpp \
+ listeners/attributelistener.h \
+ listeners/baselistener.hpp \
actormanager.cpp \
actormanager.h \
animatedsprite.cpp \
diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp
index b75ee0ebd..ad26a15c2 100644
--- a/src/being/localplayer.cpp
+++ b/src/being/localplayer.cpp
@@ -96,6 +96,7 @@ extern SkillDialog *skillDialog;
LocalPlayer::LocalPlayer(const int id, const int subtype) :
Being(id, PLAYER, subtype, nullptr),
+ AttributeListener(),
mGMLevel(0),
mInvertDirection(0),
mCrazyMoveType(config.getIntValue("crazyMoveType")),
@@ -1029,33 +1030,7 @@ void LocalPlayer::processEvent(const Channels channel,
{
if (channel == CHANNEL_ATTRIBUTES)
{
- if (event.getName() == EVENT_UPDATEATTRIBUTE)
- {
- switch (event.getInt("id"))
- {
- case PlayerInfo::EXP:
- {
- if (event.getInt("oldValue") > event.getInt("newValue"))
- break;
-
- const int change = event.getInt("newValue")
- - event.getInt("oldValue");
-
- if (change != 0)
- {
- // TRANSLATORS: get xp message
- addMessageToQueue(strprintf("%d %s", change, _("xp")));
- }
- break;
- }
- case PlayerInfo::LEVEL:
- mLevel = event.getInt("newValue");
- break;
- default:
- break;
- };
- }
- else if (event.getName() == EVENT_UPDATESTAT)
+ if (event.getName() == EVENT_UPDATESTAT)
{
if (!mShowJobExp)
return;
@@ -1107,6 +1082,33 @@ void LocalPlayer::processEvent(const Channels channel,
}
}
+void LocalPlayer::attributeChanged(const int id,
+ const int oldVal,
+ const int newVal)
+{
+ switch (id)
+ {
+ case PlayerInfo::EXP:
+ {
+ if (oldVal > newVal)
+ break;
+
+ const int change = newVal - oldVal;
+ if (change != 0)
+ {
+ // TRANSLATORS: get xp message
+ addMessageToQueue(strprintf("%d %s", change, _("xp")));
+ }
+ break;
+ }
+ case PlayerInfo::LEVEL:
+ mLevel = newVal;
+ break;
+ default:
+ break;
+ }
+}
+
void LocalPlayer::moveTo(const int x, const int y)
{
setDestination(x, y);
diff --git a/src/being/localplayer.h b/src/being/localplayer.h
index 280e245cd..ecf118799 100644
--- a/src/being/localplayer.h
+++ b/src/being/localplayer.h
@@ -31,6 +31,7 @@
#include "listeners/actionlistener.h"
#include "listeners/actorspritelistener.h"
+#include "listeners/attributelistener.h"
#include <vector>
@@ -66,7 +67,8 @@ enum
*/
class LocalPlayer final : public Being,
public ActorSpriteListener,
- public DepricatedListener
+ public DepricatedListener,
+ public AttributeListener
{
public:
/**
@@ -509,6 +511,10 @@ class LocalPlayer final : public Being,
int getLastAttackY() const override final
{ return mTarget ? mTarget->getTileY() : mLastAttackY; }
+ void attributeChanged(const int id,
+ const int oldVal,
+ const int newVal) override final;
+
protected:
void updateCoords() override final;
diff --git a/src/being/playerinfo.cpp b/src/being/playerinfo.cpp
index 12ce1e6d3..d7652abe0 100644
--- a/src/being/playerinfo.cpp
+++ b/src/being/playerinfo.cpp
@@ -58,11 +58,8 @@ std::set<int> mProtectedItems;
void triggerAttr(const int id, const int old)
{
- DepricatedEvent event(EVENT_UPDATEATTRIBUTE);
- event.setInt("id", id);
- event.setInt("oldValue", old);
- event.setInt("newValue", mData.mAttributes.find(id)->second);
- DepricatedEvent::trigger(CHANNEL_ATTRIBUTES, event);
+ AttributeListener::distributeEvent(id, old,
+ mData.mAttributes.find(id)->second);
}
void triggerStat(const int id, const std::string &changed,
diff --git a/src/gui/windows/chatwindow.cpp b/src/gui/windows/chatwindow.cpp
index be2daf6a9..dbda471c4 100644
--- a/src/gui/windows/chatwindow.cpp
+++ b/src/gui/windows/chatwindow.cpp
@@ -156,6 +156,7 @@ ChatWindow::ChatWindow():
Window(_("Chat"), false, nullptr, "chat.xml"),
ActionListener(),
KeyListener(),
+ AttributeListener(),
mItemLinkHandler(new ItemLinkHandler),
mChatTabs(new TabbedArea(this)),
mChatInput(new ChatInput(this)),
@@ -964,34 +965,7 @@ void ChatWindow::processEvent(const Channels channel,
if (!mShowBattleEvents)
return;
- if (event.getName() == EVENT_UPDATEATTRIBUTE)
- {
- switch (event.getInt("id"))
- {
- case PlayerInfo::EXP:
- {
- if (event.getInt("oldValue") > event.getInt("newValue"))
- break;
-
- const int change = event.getInt("newValue")
- - event.getInt("oldValue");
-
- if (change != 0)
- {
- battleChatLog(std::string("+").append(toString(
- change)).append(" xp"));
- }
- break;
- }
- case PlayerInfo::LEVEL:
- battleChatLog(std::string("Level: ").append(toString(
- event.getInt("newValue"))));
- break;
- default:
- break;
- };
- }
- else if (event.getName() == EVENT_UPDATESTAT)
+ if (event.getName() == EVENT_UPDATESTAT)
{
if (!config.getBoolValue("showJobExp"))
return;
@@ -1018,6 +992,32 @@ void ChatWindow::processEvent(const Channels channel,
}
}
+void ChatWindow::attributeChanged(const int id,
+ const int oldVal,
+ const int newVal)
+{
+ switch (id)
+ {
+ case PlayerInfo::EXP:
+ {
+ if (oldVal > newVal)
+ break;
+ const int change = newVal - oldVal;
+ if (change != 0)
+ {
+ battleChatLog(std::string("+").append(toString(
+ change)).append(" xp"));
+ }
+ break;
+ }
+ case PlayerInfo::LEVEL:
+ battleChatLog(std::string("Level: ").append(toString(newVal)));
+ break;
+ default:
+ break;
+ };
+}
+
void ChatWindow::addInputText(const std::string &text, const bool space)
{
const int caretPos = mChatInput->getCaretPosition();
diff --git a/src/gui/windows/chatwindow.h b/src/gui/windows/chatwindow.h
index e755e43f2..d345b5abc 100644
--- a/src/gui/windows/chatwindow.h
+++ b/src/gui/windows/chatwindow.h
@@ -23,9 +23,9 @@
#ifndef GUI_WINDOWS_CHATWINDOW_H
#define GUI_WINDOWS_CHATWINDOW_H
-#include "listeners/depricatedlistener.h"
-
+#include "listeners/attributelistener.h"
#include "listeners/configlistener.h"
+#include "listeners/depricatedlistener.h"
#include "gui/widgets/window.h"
@@ -86,7 +86,8 @@ class ChatWindow final : public Window,
public ActionListener,
public KeyListener,
public DepricatedListener,
- public ConfigListener
+ public ConfigListener,
+ public AttributeListener
{
public:
/**
@@ -294,6 +295,10 @@ class ChatWindow final : public Window,
bool isTabPresent(const ChatTab *const tab) const A_WARN_UNUSED;
+ void attributeChanged(const int id,
+ const int oldVal,
+ const int newVal) override final;
+
static void localPetSay(const std::string &nick,
const std::string &text);
diff --git a/src/gui/windows/inventorywindow.cpp b/src/gui/windows/inventorywindow.cpp
index 01e5e052d..2122fce2f 100644
--- a/src/gui/windows/inventorywindow.cpp
+++ b/src/gui/windows/inventorywindow.cpp
@@ -73,6 +73,7 @@ InventoryWindow::InventoryWindow(Inventory *const inventory):
KeyListener(),
SelectionListener(),
InventoryListener(),
+ AttributeListener(),
mInventory(inventory),
mItems(new ItemContainer(this, mInventory)),
mUseButton(nullptr),
@@ -131,8 +132,6 @@ InventoryWindow::InventoryWindow(Inventory *const inventory):
mSortDropDown->setSelected(0);
}
- listen(CHANNEL_ATTRIBUTES);
-
if (setupWindow)
setupWindow->registerWindowForReset(this);
@@ -690,17 +689,6 @@ void InventoryWindow::close()
}
}
-void InventoryWindow::processEvent(const Channels channel A_UNUSED,
- const DepricatedEvent &event)
-{
- if (event.getName() == EVENT_UPDATEATTRIBUTE)
- {
- const int id = event.getInt("id");
- if (id == PlayerInfo::TOTAL_WEIGHT || id == PlayerInfo::MAX_WEIGHT)
- updateWeight();
- }
-}
-
void InventoryWindow::updateWeight()
{
if (!isMainInventory() || !mWeightBar)
@@ -821,3 +809,11 @@ void InventoryWindow::unsetInventory()
}
mInventory = nullptr;
}
+
+void InventoryWindow::attributeChanged(const int id,
+ const int oldVal A_UNUSED,
+ const int newVal A_UNUSED)
+{
+ if (id == PlayerInfo::TOTAL_WEIGHT || id == PlayerInfo::MAX_WEIGHT)
+ updateWeight();
+}
diff --git a/src/gui/windows/inventorywindow.h b/src/gui/windows/inventorywindow.h
index 10e1e21e2..538d9a47d 100644
--- a/src/gui/windows/inventorywindow.h
+++ b/src/gui/windows/inventorywindow.h
@@ -25,11 +25,10 @@
#include "inventory.h"
-#include "listeners/depricatedlistener.h"
-
#include "gui/widgets/window.h"
#include "listeners/actionlistener.h"
+#include "listeners/attributelistener.h"
#include "listeners/keylistener.h"
#include "listeners/selectionlistener.h"
@@ -54,7 +53,7 @@ class InventoryWindow final : public Window,
public KeyListener,
public SelectionListener,
public InventoryListener,
- public DepricatedListener
+ public AttributeListener
{
public:
/**
@@ -137,9 +136,6 @@ class InventoryWindow final : public Window,
void updateDropButton();
- void processEvent(const Channels channel,
- const DepricatedEvent &event) override final;
-
void updateButtons(const Item *item = nullptr);
bool isInputFocused() const A_WARN_UNUSED;
@@ -154,6 +150,10 @@ class InventoryWindow final : public Window,
void unsetInventory();
+ void attributeChanged(const int id,
+ const int oldVal,
+ const int newVal) override final;
+
static bool isAnyInputFocused();
private:
diff --git a/src/gui/windows/killstats.cpp b/src/gui/windows/killstats.cpp
index 467d27524..832892fac 100644
--- a/src/gui/windows/killstats.cpp
+++ b/src/gui/windows/killstats.cpp
@@ -41,6 +41,7 @@ KillStats::KillStats() :
// TRANSLATORS: kill stats window name
Window(_("Kill stats"), false, nullptr, "killstats.xml"),
ActionListener(),
+ AttributeListener(),
mKillTimer(0),
// TRANSLATORS: kill stats window button
mResetButton(new Button(this, _("Reset stats"), "reset", this)),
@@ -108,7 +109,6 @@ KillStats::KillStats() :
setStickyButtonLock(true);
setDefaultSize(250, 250, 350, 300);
- listen(CHANNEL_ATTRIBUTES);
const int xp(PlayerInfo::getAttribute(PlayerInfo::EXP));
int xpNextLevel(PlayerInfo::getAttribute(PlayerInfo::EXP_NEEDED));
@@ -489,18 +489,17 @@ void KillStats::validateJacko()
}
}
-void KillStats::processEvent(const Channels channel A_UNUSED,
- const DepricatedEvent &event)
+void KillStats::attributeChanged(const int id,
+ const int oldVal,
+ const int newVal)
{
- if (event.getName() == EVENT_UPDATEATTRIBUTE)
+ switch (id)
{
- const int id = event.getInt("id");
- if (id == PlayerInfo::EXP || id == PlayerInfo::EXP_NEEDED)
- {
- gainXp(event.getInt("newValue") - event.getInt("oldValue"));
- }
- else if (id == PlayerInfo::LEVEL)
- {
+ case PlayerInfo::EXP:
+ case PlayerInfo::EXP_NEEDED:
+ gainXp(newVal - oldVal);
+ break;
+ case PlayerInfo::LEVEL:
mKillCounter = 0;
mKillTCounter = 0;
mExpCounter = 0;
@@ -520,6 +519,8 @@ void KillStats::processEvent(const Channels channel A_UNUSED,
_("Kills/Min: %s, Exp/Min: %s"), "?", "?"));
resetTimes();
- }
+ break;
+ default:
+ break;
}
}
diff --git a/src/gui/windows/killstats.h b/src/gui/windows/killstats.h
index 26e30e9eb..1e2da9ada 100644
--- a/src/gui/windows/killstats.h
+++ b/src/gui/windows/killstats.h
@@ -24,7 +24,7 @@
#define GUI_WINDOWS_KILLSTATS_H
#include "listeners/actionlistener.h"
-#include "listeners/depricatedlistener.h"
+#include "listeners/attributelistener.h"
#include "gui/widgets/window.h"
@@ -32,8 +32,8 @@ class Label;
class Button;
class KillStats final : public Window,
- private ActionListener,
- public DepricatedListener
+ public ActionListener,
+ public AttributeListener
{
public:
/**
@@ -75,11 +75,12 @@ class KillStats final : public Window,
void jackoAlive(const int id);
- void processEvent(const Channels channel A_UNUSED,
- const DepricatedEvent &event) override;
-
void resetTimes();
+ void attributeChanged(const int id,
+ const int oldVal,
+ const int newVal) override final;
+
private:
void validateJacko();
diff --git a/src/gui/windows/ministatuswindow.cpp b/src/gui/windows/ministatuswindow.cpp
index 93a6a6a10..6fb330bbf 100644
--- a/src/gui/windows/ministatuswindow.cpp
+++ b/src/gui/windows/ministatuswindow.cpp
@@ -55,6 +55,7 @@ typedef std::vector <ProgressBar*>::const_iterator ProgressBarVectorCIter;
MiniStatusWindow::MiniStatusWindow() :
Window("MiniStatus", false, nullptr, "ministatus.xml"),
InventoryListener(),
+ AttributeListener(),
mBars(),
mBarNames(),
mIcons(),
@@ -253,35 +254,40 @@ void MiniStatusWindow::drawIcons(Graphics *const graphics)
void MiniStatusWindow::processEvent(const Channels channel A_UNUSED,
const DepricatedEvent &event)
{
- if (event.getName() == EVENT_UPDATEATTRIBUTE)
+ if (event.getName() == EVENT_UPDATESTAT)
{
- const int id = event.getInt("id");
- if (id == PlayerInfo::HP || id == PlayerInfo::MAX_HP)
- {
+ statusWindow->updateMPBar(mMpBar);
+ StatusWindow::updateJobBar(mJobBar);
+ }
+}
+
+void MiniStatusWindow::attributeChanged(const int id,
+ const int oldVal A_UNUSED,
+ const int newVal A_UNUSED)
+{
+ switch (id)
+ {
+ case PlayerInfo::HP:
+ case PlayerInfo::MAX_HP:
StatusWindow::updateHPBar(mHpBar);
- }
- else if (id == PlayerInfo::MP || id == PlayerInfo::MAX_MP)
- {
+ break;
+ case PlayerInfo::MP:
+ case PlayerInfo::MAX_MP:
statusWindow->updateMPBar(mMpBar);
- }
- else if (id == PlayerInfo::EXP || id == PlayerInfo::EXP_NEEDED)
- {
+ break;
+ case PlayerInfo::EXP:
+ case PlayerInfo::EXP_NEEDED:
StatusWindow::updateXPBar(mXpBar);
- }
- else if (id == PlayerInfo::TOTAL_WEIGHT
- || id == PlayerInfo::MAX_WEIGHT)
- {
+ break;
+ case PlayerInfo::TOTAL_WEIGHT:
+ case PlayerInfo::MAX_WEIGHT:
StatusWindow::updateWeightBar(mWeightBar);
- }
- else if (id == PlayerInfo::MONEY)
- {
+ break;
+ case PlayerInfo::MONEY:
StatusWindow::updateMoneyBar(mMoneyBar);
- }
- }
- else if (event.getName() == EVENT_UPDATESTAT)
- {
- statusWindow->updateMPBar(mMpBar);
- StatusWindow::updateJobBar(mJobBar);
+ break;
+ default:
+ break;
}
}
diff --git a/src/gui/windows/ministatuswindow.h b/src/gui/windows/ministatuswindow.h
index 6939f8f54..bab117c19 100644
--- a/src/gui/windows/ministatuswindow.h
+++ b/src/gui/windows/ministatuswindow.h
@@ -25,6 +25,7 @@
#include "inventory.h"
+#include "listeners/attributelistener.h"
#include "listeners/depricatedlistener.h"
#include "gui/widgets/window.h"
@@ -44,7 +45,8 @@ class TextPopup;
*/
class MiniStatusWindow final : public Window,
public InventoryListener,
- public DepricatedListener
+ public DepricatedListener,
+ public AttributeListener
{
public:
MiniStatusWindow();
@@ -90,6 +92,10 @@ class MiniStatusWindow final : public Window,
Rect getChildrenArea() override final A_WARN_UNUSED;
+ void attributeChanged(const int id,
+ const int oldVal,
+ const int newVal) override final;
+
#ifdef USE_PROFILER
void logicChildren();
#endif
diff --git a/src/gui/windows/statuswindow.cpp b/src/gui/windows/statuswindow.cpp
index 98d3ea82e..5897ae64b 100644
--- a/src/gui/windows/statuswindow.cpp
+++ b/src/gui/windows/statuswindow.cpp
@@ -144,6 +144,7 @@ StatusWindow::StatusWindow() :
Window(player_node ? player_node->getName() :
"?", false, nullptr, "status.xml"),
ActionListener(),
+ AttributeListener(),
// TRANSLATORS: status window label
mLvlLabel(new Label(this, strprintf(_("Level: %d"), 0))),
// TRANSLATORS: status window label
@@ -342,73 +343,7 @@ void StatusWindow::processEvent(const Channels channel A_UNUSED,
return;
const DepricatedEvents &eventName = event.getName();
- if (eventName == EVENT_UPDATEATTRIBUTE)
- {
- switch (event.getInt("id"))
- {
- case PlayerInfo::HP:
- case PlayerInfo::MAX_HP:
- updateHPBar(mHpBar, true);
- break;
-
- case PlayerInfo::MP:
- case PlayerInfo::MAX_MP:
- updateMPBar(mMpBar, true);
- break;
-
- case PlayerInfo::EXP:
- case PlayerInfo::EXP_NEEDED:
- updateXPBar(mXpBar, false);
- break;
-
- case PlayerInfo::MONEY:
- // TRANSLATORS: status window label
- mMoneyLabel->setCaption(strprintf(_("Money: %s"),
- Units::formatCurrency(event.getInt("newValue")).c_str()));
- mMoneyLabel->adjustSize();
- break;
-
- case PlayerInfo::CHAR_POINTS:
- mCharacterPointsLabel->setCaption(strprintf(
- // TRANSLATORS: status window label
- _("Character points: %d"), event.getInt("newValue")));
-
- mCharacterPointsLabel->adjustSize();
- // Update all attributes
- for (Attrs::const_iterator it = mAttrs.begin();
- it != mAttrs.end(); ++it)
- {
- if (it->second)
- it->second->update();
- }
- break;
-
- case PlayerInfo::CORR_POINTS:
- mCorrectionPointsLabel->setCaption(strprintf(
- // TRANSLATORS: status window label
- _("Correction points: %d"), event.getInt("newValue")));
- mCorrectionPointsLabel->adjustSize();
- // Update all attributes
- for (Attrs::const_iterator it = mAttrs.begin();
- it != mAttrs.end(); ++it)
- {
- if (it->second)
- it->second->update();
- }
- break;
-
- case PlayerInfo::LEVEL:
- // TRANSLATORS: status window label
- mLvlLabel->setCaption(strprintf(_("Level: %d"),
- event.getInt("newValue")));
- mLvlLabel->adjustSize();
- break;
-
- default:
- break;
- }
- }
- else if (eventName == EVENT_UPDATESTAT)
+ if (eventName == EVENT_UPDATESTAT)
{
const int id = event.getInt("id");
if (id == Net::getPlayerHandler()->getJobLocation())
@@ -465,6 +400,74 @@ void StatusWindow::processEvent(const Channels channel A_UNUSED,
}
}
+void StatusWindow::attributeChanged(const int id,
+ const int oldVal A_UNUSED,
+ const int newVal)
+{
+ switch (id)
+ {
+ case PlayerInfo::HP:
+ case PlayerInfo::MAX_HP:
+ updateHPBar(mHpBar, true);
+ break;
+
+ case PlayerInfo::MP:
+ case PlayerInfo::MAX_MP:
+ updateMPBar(mMpBar, true);
+ break;
+
+ case PlayerInfo::EXP:
+ case PlayerInfo::EXP_NEEDED:
+ updateXPBar(mXpBar, false);
+ break;
+
+ case PlayerInfo::MONEY:
+ // TRANSLATORS: status window label
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"),
+ Units::formatCurrency(newVal).c_str()));
+ mMoneyLabel->adjustSize();
+ break;
+
+ case PlayerInfo::CHAR_POINTS:
+ mCharacterPointsLabel->setCaption(strprintf(
+ // TRANSLATORS: status window label
+ _("Character points: %d"), newVal));
+
+ mCharacterPointsLabel->adjustSize();
+ // Update all attributes
+ for (Attrs::const_iterator it = mAttrs.begin();
+ it != mAttrs.end(); ++it)
+ {
+ if (it->second)
+ it->second->update();
+ }
+ break;
+
+ case PlayerInfo::CORR_POINTS:
+ mCorrectionPointsLabel->setCaption(strprintf(
+ // TRANSLATORS: status window label
+ _("Correction points: %d"), newVal));
+ mCorrectionPointsLabel->adjustSize();
+ // Update all attributes
+ for (Attrs::const_iterator it = mAttrs.begin();
+ it != mAttrs.end(); ++it)
+ {
+ if (it->second)
+ it->second->update();
+ }
+ break;
+
+ case PlayerInfo::LEVEL:
+ // TRANSLATORS: status window label
+ mLvlLabel->setCaption(strprintf(_("Level: %d"), newVal));
+ mLvlLabel->adjustSize();
+ break;
+
+ default:
+ break;
+ }
+}
+
void StatusWindow::setPointsNeeded(const int id, const int needed)
{
const Attrs::const_iterator it = mAttrs.find(id);
diff --git a/src/gui/windows/statuswindow.h b/src/gui/windows/statuswindow.h
index 35bba74cd..11aa2ad05 100644
--- a/src/gui/windows/statuswindow.h
+++ b/src/gui/windows/statuswindow.h
@@ -23,11 +23,11 @@
#ifndef GUI_WINDOWS_STATUSWINDOW_H
#define GUI_WINDOWS_STATUSWINDOW_H
-#include "listeners/depricatedlistener.h"
-
#include "gui/widgets/window.h"
#include "listeners/actionlistener.h"
+#include "listeners/attributelistener.h"
+#include "listeners/depricatedlistener.h"
#include <map>
@@ -45,7 +45,8 @@ class VertContainer;
*/
class StatusWindow final : public Window,
public ActionListener,
- public DepricatedListener
+ public DepricatedListener,
+ public AttributeListener
{
public:
/**
@@ -87,6 +88,10 @@ class StatusWindow final : public Window,
void clearAttributes();
+ void attributeChanged(const int id,
+ const int oldVal,
+ const int newVal) override final;
+
private:
static std::string translateLetter(const char *const letters);
static std::string translateLetter2(std::string letters);
diff --git a/src/listeners/attributelistener.cpp b/src/listeners/attributelistener.cpp
new file mode 100644
index 000000000..b547cb219
--- /dev/null
+++ b/src/listeners/attributelistener.cpp
@@ -0,0 +1,61 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus 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 "listeners/attributelistener.h"
+
+#include "listeners/baselistener.hpp"
+
+#include "debug.h"
+
+std::vector<AttributeListener*> AttributeListener::mListeners;
+
+AttributeListener::AttributeListener()
+{
+ addListener(this);
+}
+
+AttributeListener::~AttributeListener()
+{
+ removeListener(this);
+}
+
+void AttributeListener::addListener(AttributeListener *const listener)
+{
+ mListeners.push_back(listener);
+}
+
+void AttributeListener::removeListener(AttributeListener *const listener)
+{
+ listenerRemoveListener;
+}
+
+void AttributeListener::distributeEvent(const int id,
+ const int oldVal,
+ const int newVal)
+{
+ FOR_EACH (std::vector<AttributeListener*>::iterator,
+ it, mListeners)
+ {
+ AttributeListener *const listener = *it;
+ if (listener)
+ listener->attributeChanged(id, oldVal, newVal);
+ }
+}
+
diff --git a/src/listeners/attributelistener.h b/src/listeners/attributelistener.h
new file mode 100644
index 000000000..83605ffe9
--- /dev/null
+++ b/src/listeners/attributelistener.h
@@ -0,0 +1,51 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus 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 LISTENERS_ATTRIBUTELISTENER_H
+#define LISTENERS_ATTRIBUTELISTENER_H
+
+#include <vector>
+
+#include "localconsts.h"
+
+class AttributeListener
+{
+ public:
+ AttributeListener();
+
+ virtual ~AttributeListener();
+
+ virtual void attributeChanged(const int id,
+ const int oldVal,
+ const int newVal) = 0;
+
+ static void addListener(AttributeListener *const listener);
+
+ static void removeListener(AttributeListener *const listener);
+
+ static void distributeEvent(const int id,
+ const int oldVal,
+ const int newVal);
+
+ private:
+ static std::vector<AttributeListener*> mListeners;
+};
+
+#endif // LISTENERS_ATTRIBUTELISTENER_H
diff --git a/src/listeners/baselistener.hpp b/src/listeners/baselistener.hpp
new file mode 100644
index 000000000..ae3c7112e
--- /dev/null
+++ b/src/listeners/baselistener.hpp
@@ -0,0 +1,36 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus 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 LISTENERS_BASELISTENER_HPP
+#define LISTENERS_BASELISTENER_HPP
+
+#define listenerRemoveListener \
+ { \
+ std::vector<AttributeListener*>::iterator it = mListeners.begin(); \
+ while (it != mListeners.end()) \
+ { \
+ if (*it == listener) \
+ it = mListeners.erase(it); \
+ else \
+ ++ it; \
+ } \
+ }
+
+#endif // LISTENERS_BASELISTENER_HPP