summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/net/ea/playerhandler.cpp436
-rw-r--r--src/net/ea/playerhandler.h16
-rw-r--r--src/net/eathena/playerhandler.cpp8
-rw-r--r--src/net/eathena/playerhandler.h5
-rw-r--r--src/net/tmwa/playerhandler.cpp15
-rw-r--r--src/net/tmwa/playerhandler.h5
6 files changed, 269 insertions, 216 deletions
diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp
index 01b83e143..b3e193e1f 100644
--- a/src/net/ea/playerhandler.cpp
+++ b/src/net/ea/playerhandler.cpp
@@ -173,48 +173,192 @@ void PlayerHandler::processPlayerWarp(Net::MessageIn &msg)
BLOCK_END("PlayerHandler::processPlayerWarp")
}
-void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
+void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg) const
{
BLOCK_START("PlayerHandler::processPlayerStatUpdate1")
- const int type = msg.readInt16();
- const int value = msg.readInt32();
+ const int type = msg.readInt16("type");
+ const int value = msg.readInt32("value");
if (!localPlayer)
{
BLOCK_END("PlayerHandler::processPlayerStatUpdate1")
return;
}
+ setStat(type, value, -1, true);
+
+ if (PlayerInfo::getAttribute(Attributes::HP) == 0 && !deathNotice)
+ {
+ // TRANSLATORS: message header
+ deathNotice = new OkDialog(_("Message"),
+ DeadDB::getRandomString(),
+ // TRANSLATORS: ok dialog button
+ _("Revive"),
+ DialogType::OK,
+ false, true, nullptr, 260);
+ deathNotice->addActionListener(&deathListener);
+ if (localPlayer->getCurrentAction() != BeingAction::DEAD)
+ {
+ localPlayer->setAction(BeingAction::DEAD, 0);
+ localPlayer->recalcSpritesOrder();
+ }
+ }
+ BLOCK_END("PlayerHandler::processPlayerStatUpdate1")
+}
+
+void PlayerHandler::processPlayerStatUpdate2(Net::MessageIn &msg) const
+{
+ BLOCK_START("PlayerHandler::processPlayerStatUpdate2")
+ const int type = msg.readInt16("type");
+ const int value = msg.readInt32("value");
+ setStat(type, value, -1, true);
+ BLOCK_END("PlayerHandler::processPlayerStatUpdate2")
+}
+
+void PlayerHandler::processPlayerStatUpdate3(Net::MessageIn &msg) const
+{
+ BLOCK_START("PlayerHandler::processPlayerStatUpdate3")
+ const int type = msg.readInt32("type");
+ const int base = msg.readInt32("base");
+ const int bonus = msg.readInt32("bonus");
+
+ setStat(type, base, bonus, false);
+ if (type == EA_ATK || type == Attributes::ATTACK_DELAY)
+ PlayerInfo::updateAttrs();
+ BLOCK_END("PlayerHandler::processPlayerStatUpdate3")
+}
+
+void PlayerHandler::processPlayerStatUpdate4(Net::MessageIn &msg) const
+{
+ BLOCK_START("PlayerHandler::processPlayerStatUpdate4")
+ const int type = msg.readInt16();
+ const uint8_t ok = msg.readUInt8();
+ const int value = msg.readUInt8();
+
+ if (ok != 1)
+ {
+ const int oldValue = PlayerInfo::getStatBase(type);
+ const int points = PlayerInfo::getAttribute(Attributes::CHAR_POINTS)
+ + oldValue - value;
+ PlayerInfo::setAttribute(Attributes::CHAR_POINTS, points);
+ NotifyManager::notify(NotifyTypes::SKILL_RAISE_ERROR);
+ }
+
+ setStat(type, value, -1, true);
+ BLOCK_END("PlayerHandler::processPlayerStatUpdate4")
+}
+
+void PlayerHandler::processPlayerStatUpdate6(Net::MessageIn &msg) const
+{
+ BLOCK_START("PlayerHandler::processPlayerStatUpdate6")
+ const int type = msg.readInt16("type");
+ const int value = msg.readUInt8("value");
+ if (statusWindow)
+ setStat(type, value, -1, true);
+ BLOCK_END("PlayerHandler::processPlayerStatUpdate6")
+}
+
+void PlayerHandler::processPlayerArrowMessage(Net::MessageIn &msg)
+{
+ BLOCK_START("PlayerHandler::processPlayerArrowMessage")
+ const int type = msg.readInt16();
switch (type)
{
+ case 0:
+ NotifyManager::notify(NotifyTypes::ARROWS_EQUIP_NEEDED);
+ break;
+ case 3:
+ // arrows equiped
+ break;
+ default:
+ logger->log("QQQQ 0x013b: Unhandled message %i", type);
+ break;
+ }
+ BLOCK_END("PlayerHandler::processPlayerArrowMessage")
+}
+
+bool PlayerHandler::canUseMagic() const
+{
+ return PlayerInfo::getStatEffective(EA_MATK) > 0;
+}
+
+int PlayerHandler::getJobLocation() const
+{
+ return EA_JOB;
+}
+
+int PlayerHandler::getAttackLocation() const
+{
+ return EA_ATK;
+}
+
+#define setStatComplex(stat) \
+ PlayerInfo::setStatBase(stat, base, notify); \
+ if (mod != -1) \
+ PlayerInfo::setStatMod(stat, mod)
+
+void PlayerHandler::setStat(const int type,
+ const int base,
+ const int mod,
+ const bool notify) const
+{
+ switch (type)
+ {
+ case EA_STR:
+ setStatComplex(EA_STR);
+ break;
+ case EA_AGI:
+ setStatComplex(EA_AGI);
+ break;
+ case EA_VIT:
+ setStatComplex(EA_VIT);
+ break;
+ case EA_INT:
+ setStatComplex(EA_INT);
+ break;
+ case EA_DEX:
+ setStatComplex(EA_DEX);
+ break;
+ case EA_LUK:
+ setStatComplex(EA_LUK);
+ break;
+
case 0x0000:
localPlayer->setWalkSpeed(Vector(static_cast<float>(
- value), static_cast<float>(value), 0));
- PlayerInfo::setStatBase(Attributes::WALK_SPEED, value);
+ base), static_cast<float>(base), 0));
+ PlayerInfo::setStatBase(Attributes::WALK_SPEED, base);
PlayerInfo::setStatMod(Attributes::WALK_SPEED, 0);
break;
+ case 0x0001:
+ PlayerInfo::setAttribute(Attributes::EXP, base);
+ break;
+ case 0x0002:
+ PlayerInfo::setStatExperience(EA_JOB, base,
+ PlayerInfo::getStatExperience(EA_JOB).second);
+ break;
case 0x0003:
- PlayerInfo::setStatBase(Attributes::KARMA, value);
+ PlayerInfo::setStatBase(Attributes::KARMA, base);
PlayerInfo::setStatMod(Attributes::KARMA, 0);
break;
case 0x0004:
- PlayerInfo::setStatBase(Attributes::MANNER, value);
+ PlayerInfo::setStatBase(Attributes::MANNER, base);
PlayerInfo::setStatMod(Attributes::MANNER, 0);
break;
case 0x0005:
- PlayerInfo::setAttribute(Attributes::HP, value);
+ PlayerInfo::setAttribute(Attributes::HP, base);
if (localPlayer->isInParty() && Party::getParty(1))
{
PartyMember *const m = Party::getParty(1)
->getMember(localPlayer->getId());
if (m)
{
- m->setHp(value);
+ m->setHp(base);
m->setMaxHp(PlayerInfo::getAttribute(Attributes::MAX_HP));
}
}
break;
+
case 0x0006:
- PlayerInfo::setAttribute(Attributes::MAX_HP, value);
+ PlayerInfo::setAttribute(Attributes::MAX_HP, base);
if (localPlayer->isInParty() && Party::getParty(1))
{
@@ -223,32 +367,57 @@ void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
if (m)
{
m->setHp(PlayerInfo::getAttribute(Attributes::HP));
- m->setMaxHp(value);
+ m->setMaxHp(base);
}
}
break;
case 0x0007:
- PlayerInfo::setAttribute(Attributes::MP, value);
+ PlayerInfo::setAttribute(Attributes::MP, base);
break;
case 0x0008:
- PlayerInfo::setAttribute(Attributes::MAX_MP, value);
+ PlayerInfo::setAttribute(Attributes::MAX_MP, base);
break;
case 0x0009:
- PlayerInfo::setAttribute(Attributes::CHAR_POINTS, value);
+ PlayerInfo::setAttribute(Attributes::CHAR_POINTS, base);
break;
case 0x000b:
- PlayerInfo::setAttribute(Attributes::LEVEL, value);
+ PlayerInfo::setAttribute(Attributes::LEVEL, base);
if (localPlayer)
{
- localPlayer->setLevel(value);
+ localPlayer->setLevel(base);
localPlayer->updateName();
}
break;
case 0x000c:
- PlayerInfo::setAttribute(Attributes::SKILL_POINTS, value);
+ PlayerInfo::setAttribute(Attributes::SKILL_POINTS, base);
if (skillDialog)
skillDialog->update();
break;
+ case 0x0014:
+ {
+ const int oldMoney = PlayerInfo::getAttribute(Attributes::MONEY);
+ const int newMoney = base;
+ if (newMoney > oldMoney)
+ {
+ NotifyManager::notify(NotifyTypes::MONEY_GET,
+ Units::formatCurrency(newMoney - oldMoney));
+ }
+ else if (newMoney < oldMoney)
+ {
+ NotifyManager::notify(NotifyTypes::MONEY_SPENT,
+ Units::formatCurrency(oldMoney - newMoney).c_str());
+ }
+
+ PlayerInfo::setAttribute(Attributes::MONEY, newMoney);
+ break;
+ }
+ case 0x0016:
+ PlayerInfo::setAttribute(Attributes::EXP_NEEDED, base);
+ break;
+ case 0x0017:
+ PlayerInfo::setStatExperience(EA_JOB,
+ PlayerInfo::getStatExperience(EA_JOB).first, base);
+ break;
case 0x0018:
if (!weightNotice && config.getBoolValue("weightMsg"))
{
@@ -256,7 +425,7 @@ void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
Attributes::MAX_WEIGHT) / 2;
const int total = PlayerInfo::getAttribute(
Attributes::TOTAL_WEIGHT);
- if (value >= max && total < max)
+ if (base >= max && total < max)
{
weightNoticeTime = cur_time + 5;
// TRANSLATORS: message header
@@ -272,7 +441,7 @@ void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
weightNotice->addActionListener(
&weightListener);
}
- else if (value < max && total >= max)
+ else if (base < max && total >= max)
{
weightNoticeTime = cur_time + 5;
// TRANSLATORS: message header
@@ -289,243 +458,88 @@ void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
&weightListener);
}
}
- PlayerInfo::setAttribute(Attributes::TOTAL_WEIGHT, value);
+ PlayerInfo::setAttribute(Attributes::TOTAL_WEIGHT, base);
break;
case 0x0019:
- PlayerInfo::setAttribute(Attributes::MAX_WEIGHT, value);
+ PlayerInfo::setAttribute(Attributes::MAX_WEIGHT, base);
+ break;
+ case 0x0020:
+ statusWindow->setPointsNeeded(EA_STR, base);
+ break;
+ case 0x0021:
+ statusWindow->setPointsNeeded(EA_AGI, base);
+ break;
+ case 0x0022:
+ statusWindow->setPointsNeeded(EA_VIT, base);
+ break;
+ case 0x0023:
+ statusWindow->setPointsNeeded(EA_INT, base);
+ break;
+ case 0x0024:
+ statusWindow->setPointsNeeded(EA_DEX, base);
+ break;
+ case 0x0025:
+ statusWindow->setPointsNeeded(EA_LUK, base);
break;
case 0x0029:
- PlayerInfo::setStatBase(EA_ATK, value);
+ PlayerInfo::setStatBase(EA_ATK, base);
PlayerInfo::updateAttrs();
break;
case 0x002a:
- PlayerInfo::setStatMod(EA_ATK, value);
+ PlayerInfo::setStatMod(EA_ATK, base);
PlayerInfo::updateAttrs();
break;
case 0x002b:
- PlayerInfo::setStatBase(EA_MATK, value);
+ PlayerInfo::setStatBase(EA_MATK, base);
break;
case 0x002c:
- PlayerInfo::setStatMod(EA_MATK, value);
+ PlayerInfo::setStatMod(EA_MATK, base);
break;
-
case 0x002d:
- PlayerInfo::setStatBase(EA_DEF, value);
+ PlayerInfo::setStatBase(EA_DEF, base);
break;
case 0x002e:
- PlayerInfo::setStatMod(EA_DEF, value);
+ PlayerInfo::setStatMod(EA_DEF, base);
break;
case 0x002f:
- PlayerInfo::setStatBase(EA_MDEF, value);
+ PlayerInfo::setStatBase(EA_MDEF, base);
break;
case 0x0030:
- PlayerInfo::setStatMod(EA_MDEF, value);
+ PlayerInfo::setStatMod(EA_MDEF, base);
break;
case 0x0031:
- PlayerInfo::setStatBase(EA_HIT, value);
+ PlayerInfo::setStatBase(EA_HIT, base);
break;
case 0x0032:
- PlayerInfo::setStatBase(EA_FLEE, value);
+ PlayerInfo::setStatBase(EA_FLEE, base);
break;
case 0x0033:
- PlayerInfo::setStatMod(EA_FLEE, value);
+ PlayerInfo::setStatMod(EA_FLEE, base);
break;
-
case 0x0034:
- PlayerInfo::setStatBase(EA_CRIT, value);
+ PlayerInfo::setStatBase(EA_CRIT, base);
break;
case 0x0035:
- localPlayer->setAttackSpeed(value);
- PlayerInfo::setStatBase(Attributes::ATTACK_DELAY, value);
+ localPlayer->setAttackSpeed(base);
+ PlayerInfo::setStatBase(Attributes::ATTACK_DELAY, base);
PlayerInfo::setStatMod(Attributes::ATTACK_DELAY, 0);
PlayerInfo::updateAttrs();
break;
-
case 0x0037:
- PlayerInfo::setStatBase(EA_JOB, value);
- break;
-
- case 500:
- localPlayer->setGMLevel(value);
- break;
-
- default:
- logger->log("QQQQ PLAYER_STAT_UPDATE_1 "
- + toString(type) + "," + toString(value));
- break;
- }
-
- if (PlayerInfo::getAttribute(Attributes::HP) == 0 && !deathNotice)
- {
- // TRANSLATORS: message header
- deathNotice = new OkDialog(_("Message"),
- DeadDB::getRandomString(),
- // TRANSLATORS: ok dialog button
- _("Revive"),
- DialogType::OK,
- false, true, nullptr, 260);
- deathNotice->addActionListener(&deathListener);
- if (localPlayer->getCurrentAction() != BeingAction::DEAD)
- {
- localPlayer->setAction(BeingAction::DEAD, 0);
- localPlayer->recalcSpritesOrder();
- }
- }
- BLOCK_END("PlayerHandler::processPlayerStatUpdate1")
-}
-
-void PlayerHandler::processPlayerStatUpdate2(Net::MessageIn &msg)
-{
- BLOCK_START("PlayerHandler::processPlayerStatUpdate2")
- const int type = msg.readInt16();
- switch (type)
- {
- case 0x0001:
- PlayerInfo::setAttribute(Attributes::EXP, msg.readInt32());
+ PlayerInfo::setStatBase(EA_JOB, base);
break;
- case 0x0002:
- PlayerInfo::setStatExperience(EA_JOB, msg.readInt32(),
- PlayerInfo::getStatExperience(EA_JOB).second);
- break;
- case 0x0014:
- {
- const int oldMoney = PlayerInfo::getAttribute(Attributes::MONEY);
- const int newMoney = msg.readInt32();
- if (newMoney > oldMoney)
- {
- NotifyManager::notify(NotifyTypes::MONEY_GET,
- Units::formatCurrency(newMoney - oldMoney));
- }
- else if (newMoney < oldMoney)
- {
- NotifyManager::notify(NotifyTypes::MONEY_SPENT,
- Units::formatCurrency(oldMoney - newMoney).c_str());
- }
-
- PlayerInfo::setAttribute(Attributes::MONEY, newMoney);
- break;
- }
- case 0x0016:
- PlayerInfo::setAttribute(Attributes::EXP_NEEDED, msg.readInt32());
- break;
- case 0x0017:
- PlayerInfo::setStatExperience(EA_JOB,
- PlayerInfo::getStatExperience(EA_JOB).first, msg.readInt32());
- break;
- default:
- logger->log("QQQQ PLAYER_STAT_UPDATE_2 " + toString(type));
- break;
- }
- BLOCK_END("PlayerHandler::processPlayerStatUpdate2")
-}
-void PlayerHandler::processPlayerStatUpdate3(Net::MessageIn &msg)
-{
- BLOCK_START("PlayerHandler::processPlayerStatUpdate3")
- const int type = msg.readInt32();
- const int base = msg.readInt32();
- const int bonus = msg.readInt32();
-
- PlayerInfo::setStatBase(type, base, false);
- PlayerInfo::setStatMod(type, bonus);
- if (type == EA_ATK || type == Attributes::ATTACK_DELAY)
- PlayerInfo::updateAttrs();
- BLOCK_END("PlayerHandler::processPlayerStatUpdate3")
-}
-
-void PlayerHandler::processPlayerStatUpdate4(Net::MessageIn &msg)
-{
- BLOCK_START("PlayerHandler::processPlayerStatUpdate4")
- const int type = msg.readInt16();
- const uint8_t ok = msg.readUInt8();
- const int value = msg.readUInt8();
-
- if (ok != 1)
- {
- const int oldValue = PlayerInfo::getStatBase(type);
- const int points = PlayerInfo::getAttribute(Attributes::CHAR_POINTS)
- + oldValue - value;
- PlayerInfo::setAttribute(Attributes::CHAR_POINTS, points);
- NotifyManager::notify(NotifyTypes::SKILL_RAISE_ERROR);
- }
-
- PlayerInfo::setStatBase(type, value);
- BLOCK_END("PlayerHandler::processPlayerStatUpdate4")
-}
-
-void PlayerHandler::processPlayerStatUpdate6(Net::MessageIn &msg)
-{
- BLOCK_START("PlayerHandler::processPlayerStatUpdate6")
- const int type = msg.readInt16();
- if (statusWindow)
- {
- switch (type)
- {
- case 0x0020:
- statusWindow->setPointsNeeded(EA_STR, msg.readUInt8());
- break;
- case 0x0021:
- statusWindow->setPointsNeeded(EA_AGI, msg.readUInt8());
- break;
- case 0x0022:
- statusWindow->setPointsNeeded(EA_VIT, msg.readUInt8());
- break;
- case 0x0023:
- statusWindow->setPointsNeeded(EA_INT, msg.readUInt8());
- break;
- case 0x0024:
- statusWindow->setPointsNeeded(EA_DEX, msg.readUInt8());
- break;
- case 0x0025:
- statusWindow->setPointsNeeded(EA_LUK, msg.readUInt8());
- break;
- default:
- logger->log("QQQQ PLAYER_STAT_UPDATE_6 "
- + toString(type));
- break;
- }
- }
- BLOCK_END("PlayerHandler::processPlayerStatUpdate6")
-}
-
-void PlayerHandler::processPlayerArrowMessage(Net::MessageIn &msg)
-{
- BLOCK_START("PlayerHandler::processPlayerArrowMessage")
- const int type = msg.readInt16();
- switch (type)
- {
- case 0:
- NotifyManager::notify(NotifyTypes::ARROWS_EQUIP_NEEDED);
- break;
- case 3:
- // arrows equiped
- break;
default:
- logger->log("QQQQ 0x013b: Unhandled message %i", type);
+ logger->log("Error: Unknown stat set: %d, values: %d, %d",
+ type, base, mod);
break;
}
- BLOCK_END("PlayerHandler::processPlayerArrowMessage")
-}
-
-bool PlayerHandler::canUseMagic() const
-{
- return PlayerInfo::getStatEffective(EA_MATK) > 0;
-}
-
-int PlayerHandler::getJobLocation() const
-{
- return EA_JOB;
-}
-
-int PlayerHandler::getAttackLocation() const
-{
- return EA_ATK;
}
} // namespace Ea
diff --git a/src/net/ea/playerhandler.h b/src/net/ea/playerhandler.h
index 6669da9ff..a2e126bc2 100644
--- a/src/net/ea/playerhandler.h
+++ b/src/net/ea/playerhandler.h
@@ -57,17 +57,23 @@ class PlayerHandler notfinal : public Net::PlayerHandler
int getAttackLocation() const override final A_WARN_UNUSED;
+ protected:
+ virtual void setStat(const int type,
+ const int base,
+ const int mod,
+ const bool notify) const = 0;
+
static void processPlayerWarp(Net::MessageIn &msg);
- static void processPlayerStatUpdate1(Net::MessageIn &msg);
+ void processPlayerStatUpdate1(Net::MessageIn &msg) const;
- static void processPlayerStatUpdate2(Net::MessageIn &msg);
+ void processPlayerStatUpdate2(Net::MessageIn &msg) const;
- static void processPlayerStatUpdate3(Net::MessageIn &msg);
+ void processPlayerStatUpdate3(Net::MessageIn &msg) const;
- static void processPlayerStatUpdate4(Net::MessageIn &msg);
+ void processPlayerStatUpdate4(Net::MessageIn &msg) const;
- static void processPlayerStatUpdate6(Net::MessageIn &msg);
+ void processPlayerStatUpdate6(Net::MessageIn &msg) const;
static void processPlayerArrowMessage(Net::MessageIn &msg);
};
diff --git a/src/net/eathena/playerhandler.cpp b/src/net/eathena/playerhandler.cpp
index 3a4f46a2c..089a06d26 100644
--- a/src/net/eathena/playerhandler.cpp
+++ b/src/net/eathena/playerhandler.cpp
@@ -436,4 +436,12 @@ void PlayerHandler::processPlayerHeal(Net::MessageIn &msg)
msg.readInt16("value");
}
+void PlayerHandler::setStat(const int type,
+ const int base,
+ const int mod,
+ const bool notify) const
+{
+ Ea::PlayerHandler::setStat(type, base, mod, notify);
+}
+
} // namespace EAthena
diff --git a/src/net/eathena/playerhandler.h b/src/net/eathena/playerhandler.h
index f94fd0652..3a0ba20fa 100644
--- a/src/net/eathena/playerhandler.h
+++ b/src/net/eathena/playerhandler.h
@@ -73,6 +73,11 @@ class PlayerHandler final : public MessageHandler, public Ea::PlayerHandler
void setViewEquipment(const bool allow) const override final;
protected:
+ void setStat(const int type,
+ const int base,
+ const int mod,
+ const bool notify) const override final;
+
void processPlayerStatUpdate5(Net::MessageIn &msg);
void processPlayerGetExp(Net::MessageIn &msg);
diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp
index 9ad631d71..f2b47c607 100644
--- a/src/net/tmwa/playerhandler.cpp
+++ b/src/net/tmwa/playerhandler.cpp
@@ -25,6 +25,7 @@
#include "configuration.h"
#include "game.h"
#include "soundmanager.h"
+#include "units.h"
#include "being/attributes.h"
#include "being/beingflag.h"
@@ -37,6 +38,7 @@
#include "net/tmwa/messageout.h"
#include "net/tmwa/protocol.h"
+#include "gui/windows/skilldialog.h"
#include "gui/windows/whoisonline.h"
#include "gui/onlineplayer.h"
@@ -470,4 +472,17 @@ void PlayerHandler::setViewEquipment(const bool allow A_UNUSED) const
{
}
+void PlayerHandler::setStat(const int type,
+ const int base,
+ const int mod,
+ const bool notify) const
+{
+ if (type == 500)
+ {
+ localPlayer->setGMLevel(base);
+ return;
+ }
+ Ea::PlayerHandler::setStat(type, base, mod, notify);
+}
+
} // namespace TmwAthena
diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h
index 3fb89db83..05b7b1d27 100644
--- a/src/net/tmwa/playerhandler.h
+++ b/src/net/tmwa/playerhandler.h
@@ -82,6 +82,11 @@ class PlayerHandler final : public MessageHandler, public Ea::PlayerHandler
void setViewEquipment(const bool allow) const override final;
protected:
+ void setStat(const int type,
+ const int base,
+ const int mod,
+ const bool notify) const override final;
+
void processPlayerStatUpdate5(Net::MessageIn &msg);
static void processWalkResponse(Net::MessageIn &msg);