summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/Makefile.am4
-rw-r--r--src/net/ea/eaprotocol.h23
-rw-r--r--src/net/ea/npchandler.cpp118
-rw-r--r--src/net/ea/npchandler.h83
-rw-r--r--src/net/ea/playerhandler.cpp639
-rw-r--r--src/net/ea/playerhandler.h79
-rw-r--r--src/net/tmwa/npchandler.cpp126
-rw-r--r--src/net/tmwa/npchandler.h21
-rw-r--r--src/net/tmwa/playerhandler.cpp602
-rw-r--r--src/net/tmwa/playerhandler.h15
11 files changed, 1010 insertions, 704 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4348dac03..6ed15974e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -701,8 +701,12 @@ SET(SRCS_EVOL
net/ea/itemhandler.h
net/ea/loginhandler.cpp
net/ea/loginhandler.h
+ net/ea/npchandler.cpp
+ net/ea/npchandler.h
net/ea/partyhandler.cpp
net/ea/partyhandler.h
+ net/ea/playerhandler.cpp
+ net/ea/playerhandler.h
net/ea/token.h
)
diff --git a/src/Makefile.am b/src/Makefile.am
index b55415c78..de2024a0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -685,8 +685,12 @@ manaplus_SOURCES += \
net/ea/itemhandler.h \
net/ea/loginhandler.cpp \
net/ea/loginhandler.h \
+ net/ea/npchandler.cpp \
+ net/ea/npchandler.h \
net/ea/partyhandler.cpp \
net/ea/partyhandler.h \
+ net/ea/playerhandler.cpp \
+ net/ea/playerhandler.h \
net/ea/token.h \
net/tmwa/gui/guildtab.cpp \
net/tmwa/gui/guildtab.h \
diff --git a/src/net/ea/eaprotocol.h b/src/net/ea/eaprotocol.h
index fae3651a8..d34cba0ca 100644
--- a/src/net/ea/eaprotocol.h
+++ b/src/net/ea/eaprotocol.h
@@ -25,6 +25,29 @@
enum
{
+ EA_JOB = 0xa,
+
+ EA_STR = 0xd,
+ EA_AGI,
+ EA_VIT,
+ EA_INT,
+ EA_DEX,
+ EA_LUK,
+
+ EA_ATK,
+ EA_DEF,
+ EA_MATK,
+ EA_MDEF,
+ EA_HIT,
+ EA_FLEE,
+ EA_CRIT
+
+// KARMA,
+// MANNER
+};
+
+enum
+{
EA_SPRITE_BASE = 0,
EA_SPRITE_SHOE,
EA_SPRITE_BOTTOMCLOTHES,
diff --git a/src/net/ea/npchandler.cpp b/src/net/ea/npchandler.cpp
new file mode 100644
index 000000000..9a37ccc26
--- /dev/null
+++ b/src/net/ea/npchandler.cpp
@@ -0,0 +1,118 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011 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 "net/ea/npchandler.h"
+
+#include "gui/npcdialog.h"
+
+#include "net/messagein.h"
+#include "net/net.h"
+
+#include "debug.h"
+
+namespace Ea
+{
+
+NpcHandler::NpcHandler() :
+ mDialog(0)
+{
+}
+
+void NpcHandler::sendLetter(int npcId A_UNUSED,
+ const std::string &recipient A_UNUSED,
+ const std::string &text A_UNUSED)
+{
+ // TODO
+}
+
+void NpcHandler::startShopping(int beingId A_UNUSED)
+{
+ // TODO
+}
+
+void NpcHandler::endShopping(int beingId A_UNUSED)
+{
+ // TODO
+}
+
+void NpcHandler::clearDialogs()
+{
+ NpcDialogs::iterator it = mNpcDialogs.begin();
+ NpcDialogs::iterator it_end = mNpcDialogs.end();
+ while (it != it_end)
+ {
+ delete (*it).second.dialog;
+ ++ it;
+ }
+ mNpcDialogs.clear();
+}
+
+void NpcHandler::processNpcChoice(Net::MessageIn &msg)
+{
+ if (mDialog)
+ {
+ mDialog->choiceRequest();
+ mDialog->parseListItems(msg.readString(msg.getLength() - 8));
+ }
+ else
+ {
+ msg.readString(msg.getLength() - 8);
+ }
+}
+
+void NpcHandler::processNpcMessage(Net::MessageIn &msg)
+{
+ if (mDialog)
+ mDialog->addText(msg.readString(msg.getLength() - 8));
+ else
+ msg.readString(msg.getLength() - 8);
+}
+
+void NpcHandler::processNpcClose(Net::MessageIn &msg A_UNUSED)
+{
+ // Show the close button
+ if (mDialog)
+ mDialog->showCloseButton();
+}
+
+void NpcHandler::processNpcNext(Net::MessageIn &msg A_UNUSED)
+{
+ // Show the next button
+ if (mDialog)
+ mDialog->showNextButton();
+}
+
+void NpcHandler::processNpcIntInput(Net::MessageIn &msg A_UNUSED)
+{
+ // Request for an integer
+ if (mDialog)
+ mDialog->integerRequest(0);
+}
+
+void NpcHandler::processNpcStrInput(Net::MessageIn &msg A_UNUSED)
+{
+ // Request for a string
+ if (mDialog)
+ mDialog->textRequest("");
+}
+
+} // namespace Ea
diff --git a/src/net/ea/npchandler.h b/src/net/ea/npchandler.h
new file mode 100644
index 000000000..44c1c5fb3
--- /dev/null
+++ b/src/net/ea/npchandler.h
@@ -0,0 +1,83 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011 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 NET_EA_NPCHANDLER_H
+#define NET_EA_NPCHANDLER_H
+
+#include "net/messagein.h"
+#include "net/net.h"
+#include "net/npchandler.h"
+
+#include <map>
+
+#ifdef __GNUC__
+#define A_UNUSED __attribute__ ((unused))
+#else
+#define A_UNUSED
+#endif
+
+class NpcDialog;
+
+namespace Ea
+{
+
+class NpcHandler : public Net::NpcHandler
+{
+ public:
+ NpcHandler();
+
+ void sendLetter(int npcId, const std::string &recipient,
+ const std::string &text);
+
+ void startShopping(int beingId);
+
+ void endShopping(int beingId);
+
+ void clearDialogs();
+
+ virtual int getNpc(Net::MessageIn &msg, bool haveLength) = 0;
+
+ void processNpcChoice(Net::MessageIn &msg);
+
+ void processNpcMessage(Net::MessageIn &msg);
+
+ void processNpcClose(Net::MessageIn &msg);
+
+ void processNpcNext(Net::MessageIn &msg);
+
+ void processNpcIntInput(Net::MessageIn &msg);
+
+ void processNpcStrInput(Net::MessageIn &msg);
+
+ protected:
+ typedef struct
+ {
+ NpcDialog* dialog;
+ } Wrapper;
+ typedef std::map<int, Wrapper> NpcDialogs;
+ NpcDialogs mNpcDialogs;
+ NpcDialog *mDialog;
+};
+
+} // namespace Ea
+
+#endif // NET_EA_NPCHANDLER_H
diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp
new file mode 100644
index 000000000..05b6cf9e3
--- /dev/null
+++ b/src/net/ea/playerhandler.cpp
@@ -0,0 +1,639 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011 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 "net/ea/playerhandler.h"
+
+#include "log.h"
+#include "party.h"
+#include "playerinfo.h"
+#include "units.h"
+
+#include "gui/okdialog.h"
+#include "gui/skilldialog.h"
+#include "gui/statuswindow.h"
+#include "gui/viewport.h"
+
+#include "net/messagein.h"
+#include "net/npchandler.h"
+
+#include "net/ea/eaprotocol.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+extern OkDialog *weightNotice;
+extern OkDialog *deathNotice;
+extern int weightNoticeTime;
+
+// Max. distance we are willing to scroll after a teleport;
+// everything beyond will reset the port hard.
+static const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
+
+// TODO Move somewhere else
+namespace
+{
+ /**
+ * Listener used for handling the overweigth message.
+ */
+ struct WeightListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event A_UNUSED)
+ {
+ weightNotice = NULL;
+ }
+ } weightListener;
+
+ /**
+ * Listener used for handling death message.
+ */
+ struct DeathListener : public gcn::ActionListener
+ {
+ void action(const gcn::ActionEvent &event A_UNUSED)
+ {
+ Net::getPlayerHandler()->respawn();
+ deathNotice = NULL;
+
+ Client::closeDialogs();
+
+ if (viewport)
+ viewport->closePopupMenu();
+
+ Net::NpcHandler *handler = Net::getNpcHandler();
+ if (handler)
+ handler->clearDialogs();
+ if (player_node)
+ player_node->respawn();
+ }
+ } deathListener;
+
+} // anonymous namespace
+
+static const char *randomDeathMessage()
+{
+ static char const *const deadMsg[] =
+ {
+ N_("You are dead."),
+ N_("We regret to inform you that your character was killed in "
+ "battle."),
+ N_("You are not that alive anymore."),
+ N_("The cold hands of the grim reaper are grabbing for your soul."),
+ N_("Game Over!"),
+ N_("Insert coin to continue."),
+ N_("No, kids. Your character did not really die. It... "
+ "err... went to a better place."),
+ N_("Your plan of breaking your enemies weapon by "
+ "bashing it with your throat failed."),
+ N_("I guess this did not run too well."),
+ // NetHack reference:
+ N_("Do you want your possessions identified?"),
+ // Secret of Mana reference:
+ N_("Sadly, no trace of you was ever found..."),
+ // Final Fantasy VI reference:
+ N_("Annihilated."),
+ // Earthbound reference:
+ N_("Looks like you got your head handed to you."),
+ // Leisure Suit Larry 1 reference:
+ N_("You screwed up again, dump your body down the tubes "
+ "and get you another one."),
+ // Monty Python references (Dead Parrot sketch mostly):
+ N_("You're not dead yet. You're just resting."),
+ N_("You are no more."),
+ N_("You have ceased to be."),
+ N_("You've expired and gone to meet your maker."),
+ N_("You're a stiff."),
+ N_("Bereft of life, you rest in peace."),
+ N_("If you weren't so animated, you'd be pushing up the daisies."),
+ N_("Your metabolic processes are now history."),
+ N_("You're off the twig."),
+ N_("You've kicked the bucket."),
+ N_("You've shuffled off your mortal coil, run down the "
+ "curtain and joined the bleedin' choir invisibile."),
+ N_("You are an ex-player."),
+ N_("You're pining for the fjords.")
+ };
+
+ const int random = static_cast<int>(rand() % (sizeof(deadMsg)
+ / sizeof(deadMsg[0])));
+ return gettext(deadMsg[random]);
+}
+
+namespace Ea
+{
+
+PlayerHandler::PlayerHandler()
+{
+}
+
+void PlayerHandler::decreaseAttribute(int attr A_UNUSED)
+{
+ // Supported by eA?
+}
+
+void PlayerHandler::ignorePlayer(const std::string &player A_UNUSED,
+ bool ignore A_UNUSED)
+{
+ // TODO
+}
+
+void PlayerHandler::ignoreAll(bool ignore A_UNUSED)
+{
+ // TODO
+}
+
+bool PlayerHandler::canCorrectAttributes() const
+{
+ return false;
+}
+
+Vector PlayerHandler::getDefaultWalkSpeed() const
+{
+ // Return an normalized speed for any side
+ // as the offset is calculated elsewhere.
+ return Vector(150, 150, 0);
+}
+
+void PlayerHandler::processWalkResponse(Net::MessageIn &msg)
+{
+ /*
+ * This client assumes that all walk messages succeed,
+ * and that the server will send a correction notice
+ * otherwise.
+ */
+ Uint16 srcX, srcY, dstX, dstY;
+ msg.readInt32(); //tick
+ msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ if (player_node)
+ player_node->setRealPos(dstX, dstY);
+}
+
+void PlayerHandler::processPlayerWarp(Net::MessageIn &msg)
+{
+ std::string mapPath = msg.readString(16);
+ int x = msg.readInt16();
+ int y = msg.readInt16();
+
+ logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
+
+ if (!player_node)
+ logger->log1("SMSG_PLAYER_WARP player_node null");
+
+ /*
+ * We must clear the local player's target *before* the call
+ * to changeMap, as it deletes all beings.
+ */
+ if (player_node)
+ player_node->stopAttack();
+
+ Game *game = Game::instance();
+
+ const std::string &currentMapName = game->getCurrentMapName();
+ bool sameMap = (currentMapName == mapPath);
+
+ // Switch the actual map, deleting the previous one if necessary
+ mapPath = mapPath.substr(0, mapPath.rfind("."));
+ game->changeMap(mapPath);
+
+ float scrollOffsetX = 0.0f;
+ float scrollOffsetY = 0.0f;
+
+ if (player_node)
+ {
+ Map *map = game->getCurrentMap();
+ if (map)
+ {
+ if (x >= map->getWidth())
+ x = map->getWidth() - 1;
+ if (y >= map->getHeight())
+ y = map->getHeight() - 1;
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ /* Scroll if neccessary */
+ if (!sameMap
+ || (abs(x - player_node->getTileX())
+ > MAP_TELEPORT_SCROLL_DISTANCE)
+ || (abs(y - player_node->getTileY())
+ > MAP_TELEPORT_SCROLL_DISTANCE))
+ {
+ scrollOffsetX = static_cast<float>((x
+ - player_node->getTileX())
+ * map->getTileWidth());
+ scrollOffsetY = static_cast<float>((y
+ - player_node->getTileY())
+ * map->getTileHeight());
+ }
+ }
+
+ player_node->setAction(Being::STAND);
+ player_node->setTileCoords(x, y);
+ player_node->navigateClean();
+ }
+
+ logger->log("Adjust scrolling by %d:%d",
+ static_cast<int>(scrollOffsetX),
+ static_cast<int>(scrollOffsetY));
+
+ if (viewport)
+ viewport->scrollBy(scrollOffsetX, scrollOffsetY);
+}
+
+void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
+{
+ int type = msg.readInt16();
+ int value = msg.readInt32();
+ if (!player_node)
+ return;
+
+ switch (type)
+ {
+ case 0x0000:
+ player_node->setWalkSpeed(Vector(static_cast<float>(
+ value), static_cast<float>(value), 0));
+ PlayerInfo::setStatBase(WALK_SPEED, value);
+ PlayerInfo::setStatMod(WALK_SPEED, 0);
+ break;
+ case 0x0004: break; // manner
+ case 0x0005:
+ PlayerInfo::setAttribute(HP, value);
+ if (player_node->isInParty() && Party::getParty(1))
+ {
+ PartyMember *m = Party::getParty(1)
+ ->getMember(player_node->getId());
+ if (m)
+ {
+ m->setHp(value);
+ m->setMaxHp(PlayerInfo::getAttribute(MAX_HP));
+ }
+ }
+ break;
+ case 0x0006:
+ PlayerInfo::setAttribute(MAX_HP, value);
+
+ if (player_node->isInParty() && Party::getParty(1))
+ {
+ PartyMember *m = Party::getParty(1)->getMember(
+ player_node->getId());
+ if (m)
+ {
+ m->setHp(PlayerInfo::getAttribute(HP));
+ m->setMaxHp(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);
+ if (player_node)
+ {
+ player_node->setLevel(value);
+ player_node->updateName();
+ }
+ break;
+ case 0x000c:
+ PlayerInfo::setAttribute(SKILL_POINTS, value);
+ if (skillDialog)
+ skillDialog->update();
+ break;
+ case 0x0018:
+ if (!weightNotice)
+ {
+ const int max
+ = PlayerInfo::getAttribute(MAX_WEIGHT) / 2;
+ const int total
+ = PlayerInfo::getAttribute(TOTAL_WEIGHT);
+ if (value >= max && total < max)
+ {
+ weightNoticeTime = cur_time + 10;
+ weightNotice = new OkDialog(_("Message"),
+ _("You are carrying more than "
+ "half your weight. You are "
+ "unable to regain health."), false);
+ weightNotice->addActionListener(
+ &weightListener);
+ }
+ else if (value < max && total >= max)
+ {
+ weightNoticeTime = cur_time + 10;
+ weightNotice = new OkDialog(_("Message"),
+ _("You are carrying less than "
+ "half your weight. You "
+ "can regain health."), false);
+ weightNotice->addActionListener(
+ &weightListener);
+ }
+ }
+ PlayerInfo::setAttribute(TOTAL_WEIGHT, value);
+ break;
+ case 0x0019:
+ PlayerInfo::setAttribute(MAX_WEIGHT, value);
+ break;
+
+ case 0x0029:
+ PlayerInfo::setStatBase(EA_ATK, value);
+ break;
+ case 0x002a:
+ PlayerInfo::setStatMod(EA_ATK, value);
+ break;
+
+ case 0x002b:
+ PlayerInfo::setStatBase(EA_MATK, value);
+ break;
+ case 0x002c:
+ PlayerInfo::setStatMod(EA_MATK, value);
+ break;
+
+ case 0x002d:
+ PlayerInfo::setStatBase(EA_DEF, value);
+ break;
+ case 0x002e:
+ PlayerInfo::setStatMod(EA_DEF, value);
+ break;
+
+ case 0x002f:
+ PlayerInfo::setStatBase(EA_MDEF, value);
+ break;
+ case 0x0030:
+ PlayerInfo::setStatMod(EA_MDEF, value);
+ break;
+
+ case 0x0031:
+ PlayerInfo::setStatBase(EA_HIT, value);
+ break;
+
+ case 0x0032:
+ PlayerInfo::setStatBase(EA_FLEE, value);
+ break;
+ case 0x0033:
+ PlayerInfo::setStatMod(EA_FLEE, value);
+ break;
+
+ case 0x0034:
+ PlayerInfo::setStatBase(EA_CRIT, value);
+ break;
+
+ case 0x0035:
+ player_node->setAttackSpeed(value);
+ PlayerInfo::setStatBase(ATTACK_SPEED, value);
+ PlayerInfo::setStatMod(ATTACK_SPEED, 0);
+ break;
+
+ case 0x0037:
+ PlayerInfo::setStatBase(EA_JOB, value);
+ break;
+
+ case 500:
+ player_node->setGMLevel(value);
+ break;
+
+ default:
+ logger->log("QQQQ PLAYER_STAT_UPDATE_1 "
+ + toString(type) + "," + toString(value));
+ break;
+ }
+
+ if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice)
+ {
+ deathNotice = new OkDialog(_("Message"),
+ randomDeathMessage(),
+ false);
+ deathNotice->addActionListener(&deathListener);
+ player_node->setAction(Being::DEAD);
+ }
+}
+
+void PlayerHandler::processPlayerStatUpdate2(Net::MessageIn &msg)
+{
+ int type = msg.readInt16();
+ switch (type)
+ {
+ case 0x0001:
+ PlayerInfo::setAttribute(EXP, msg.readInt32());
+ break;
+ case 0x0002:
+ PlayerInfo::setStatExperience(EA_JOB, msg.readInt32(),
+ PlayerInfo::getStatExperience(EA_JOB).second);
+ break;
+ case 0x0014:
+ {
+ int oldMoney = PlayerInfo::getAttribute(MONEY);
+ int newMoney = msg.readInt32();
+ if (newMoney > oldMoney)
+ {
+ SERVER_NOTICE(strprintf(_("You picked up %s."),
+ Units::formatCurrency(newMoney -
+ oldMoney).c_str()))
+ }
+ else if (newMoney < oldMoney)
+ {
+ SERVER_NOTICE(strprintf(_("You spent %s."),
+ Units::formatCurrency(oldMoney -
+ newMoney).c_str()))
+ }
+
+ PlayerInfo::setAttribute(MONEY, newMoney);
+ break;
+ }
+ case 0x0016:
+ PlayerInfo::setAttribute(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;
+ }
+}
+
+void PlayerHandler::processPlayerStatUpdate3(Net::MessageIn &msg)
+{
+ int type = msg.readInt32();
+ int base = msg.readInt32();
+ int bonus = msg.readInt32();
+
+ PlayerInfo::setStatBase(type, base, false);
+ PlayerInfo::setStatMod(type, bonus);
+}
+
+void PlayerHandler::processPlayerStatUpdate4(Net::MessageIn &msg)
+{
+ int type = msg.readInt16();
+ int ok = msg.readInt8();
+ int value = msg.readInt8();
+
+ if (ok != 1)
+ {
+ int oldValue = PlayerInfo::getStatBase(type);
+ int points = PlayerInfo::getAttribute(CHAR_POINTS);
+ points += oldValue - value;
+ PlayerInfo::setAttribute(CHAR_POINTS, points);
+ SERVER_NOTICE(_("Cannot raise skill!"))
+ }
+
+ PlayerInfo::setStatBase(type, value);
+}
+
+void PlayerHandler::processPlayerStatUpdate5(Net::MessageIn &msg)
+{
+ PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
+
+ int val = msg.readInt8();
+ PlayerInfo::setStatBase(EA_STR, val);
+ if (statusWindow)
+ statusWindow->setPointsNeeded(EA_STR, msg.readInt8());
+ else
+ msg.readInt8();
+
+ val = msg.readInt8();
+ PlayerInfo::setStatBase(EA_AGI, val);
+ if (statusWindow)
+ statusWindow->setPointsNeeded(EA_AGI, msg.readInt8());
+ else
+ msg.readInt8();
+
+ val = msg.readInt8();
+ PlayerInfo::setStatBase(EA_VIT, val);
+ if (statusWindow)
+ statusWindow->setPointsNeeded(EA_VIT, msg.readInt8());
+ else
+ msg.readInt8();
+
+ val = msg.readInt8();
+ PlayerInfo::setStatBase(EA_INT, val);
+ if (statusWindow)
+ statusWindow->setPointsNeeded(EA_INT, msg.readInt8());
+ else
+ msg.readInt8();
+
+ val = msg.readInt8();
+ PlayerInfo::setStatBase(EA_DEX, val);
+ if (statusWindow)
+ statusWindow->setPointsNeeded(EA_DEX, msg.readInt8());
+ else
+ msg.readInt8();
+
+ val = msg.readInt8();
+ PlayerInfo::setStatBase(EA_LUK, val);
+ if (statusWindow)
+ statusWindow->setPointsNeeded(EA_LUK, msg.readInt8());
+ else
+ msg.readInt8();
+
+ PlayerInfo::setStatBase(EA_ATK, msg.readInt16(), false);
+ PlayerInfo::setStatMod(EA_ATK, msg.readInt16());
+
+ val = msg.readInt16();
+ PlayerInfo::setStatBase(EA_MATK, val, false);
+
+ val = msg.readInt16();
+ PlayerInfo::setStatMod(EA_MATK, val);
+
+ PlayerInfo::setStatBase(EA_DEF, msg.readInt16(), false);
+ PlayerInfo::setStatMod(EA_DEF, msg.readInt16());
+
+ PlayerInfo::setStatBase(EA_MDEF, msg.readInt16(), false);
+ PlayerInfo::setStatMod(EA_MDEF, msg.readInt16());
+
+ PlayerInfo::setStatBase(EA_HIT, msg.readInt16());
+
+ PlayerInfo::setStatBase(EA_FLEE, msg.readInt16(), false);
+ PlayerInfo::setStatMod(EA_FLEE, msg.readInt16());
+
+ PlayerInfo::setStatBase(EA_CRIT, msg.readInt16());
+
+ msg.readInt16(); // manner
+}
+
+void PlayerHandler::processPlayerStatUpdate6(Net::MessageIn &msg)
+{
+ int type = msg.readInt16();
+ if (statusWindow)
+ {
+ switch (type)
+ {
+ case 0x0020:
+ statusWindow->setPointsNeeded(EA_STR, msg.readInt8());
+ break;
+ case 0x0021:
+ statusWindow->setPointsNeeded(EA_AGI, msg.readInt8());
+ break;
+ case 0x0022:
+ statusWindow->setPointsNeeded(EA_VIT, msg.readInt8());
+ break;
+ case 0x0023:
+ statusWindow->setPointsNeeded(EA_INT, msg.readInt8());
+ break;
+ case 0x0024:
+ statusWindow->setPointsNeeded(EA_DEX, msg.readInt8());
+ break;
+ case 0x0025:
+ statusWindow->setPointsNeeded(EA_LUK, msg.readInt8());
+ break;
+ default:
+ logger->log("QQQQ PLAYER_STAT_UPDATE_6 "
+ + toString(type));
+ break;
+ }
+ }
+}
+
+void PlayerHandler::processPlayerArrowMessage(Net::MessageIn &msg)
+{
+ int type = msg.readInt16();
+
+ switch (type)
+ {
+ case 0:
+ SERVER_NOTICE(_("Equip arrows first."))
+ break;
+ case 3:
+ // arrows equiped
+ break;
+ default:
+ logger->log("QQQQ 0x013b: Unhandled message %i", type);
+ break;
+ }
+}
+
+bool PlayerHandler::canUseMagic() const
+{
+ return PlayerInfo::getStatEffective(EA_MATK) > 0;
+}
+
+int PlayerHandler::getJobLocation() const
+{
+ return EA_JOB;
+}
+
+} // namespace Ea
diff --git a/src/net/ea/playerhandler.h b/src/net/ea/playerhandler.h
new file mode 100644
index 000000000..8b8751630
--- /dev/null
+++ b/src/net/ea/playerhandler.h
@@ -0,0 +1,79 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011 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 NET_EA_PLAYERHANDLER_H
+#define NET_EA_PLAYERHANDLER_H
+
+#include "net/messagein.h"
+#include "net/net.h"
+#include "net/playerhandler.h"
+
+#ifdef __GNUC__
+#define A_UNUSED __attribute__ ((unused))
+#else
+#define A_UNUSED
+#endif
+
+namespace Ea
+{
+
+class PlayerHandler : public Net::PlayerHandler
+{
+ public:
+ PlayerHandler();
+
+ void decreaseAttribute(int attr);
+
+ void ignorePlayer(const std::string &player, bool ignore);
+
+ void ignoreAll(bool ignore);
+
+ bool canUseMagic() const;
+
+ bool canCorrectAttributes() const;
+
+ Vector getDefaultWalkSpeed() const;
+
+ int getJobLocation() const;
+
+ void processWalkResponse(Net::MessageIn &msg);
+
+ void processPlayerWarp(Net::MessageIn &msg);
+
+ void processPlayerStatUpdate1(Net::MessageIn &msg);
+
+ void processPlayerStatUpdate2(Net::MessageIn &msg);
+
+ void processPlayerStatUpdate3(Net::MessageIn &msg);
+
+ void processPlayerStatUpdate4(Net::MessageIn &msg);
+
+ void processPlayerStatUpdate5(Net::MessageIn &msg);
+
+ void processPlayerStatUpdate6(Net::MessageIn &msg);
+
+ void processPlayerArrowMessage(Net::MessageIn &msg);
+};
+
+} // namespace Ea
+
+#endif // NET_EA_PLAYERHANDLER_H
diff --git a/src/net/tmwa/npchandler.cpp b/src/net/tmwa/npchandler.cpp
index 9bcc640a1..d6549e39f 100644
--- a/src/net/tmwa/npchandler.cpp
+++ b/src/net/tmwa/npchandler.cpp
@@ -22,13 +22,11 @@
#include "net/tmwa/npchandler.h"
-#include "actorspritemanager.h"
#include "localplayer.h"
#include "gui/npcdialog.h"
#include "net/messagein.h"
-#include "net/messageout.h"
#include "net/net.h"
#include "net/npchandler.h"
@@ -36,8 +34,6 @@
#include "net/ea/eaprotocol.h"
-#include <SDL_types.h>
-
#include "debug.h"
extern Net::NpcHandler *npcHandler;
@@ -63,82 +59,33 @@ NpcHandler::NpcHandler()
void NpcHandler::handleMessage(Net::MessageIn &msg)
{
- if (msg.getId() == SMSG_NPC_CHOICE || msg.getId() == SMSG_NPC_MESSAGE)
- msg.readInt16(); // length
-
- int npcId = msg.readInt32();
- NpcDialogs::iterator diag = mNpcDialogs.find(npcId);
- NpcDialog *dialog = 0;
-
- if (diag == mNpcDialogs.end())
- {
- // Empty dialogs don't help
- if (msg.getId() == SMSG_NPC_CLOSE)
- {
- closeDialog(npcId);
- return;
- }
- else if (msg.getId() == SMSG_NPC_NEXT)
- {
- nextDialog(npcId);
- return;
- }
- else
- {
- dialog = new NpcDialog(npcId);
- Wrapper wrap;
- wrap.dialog = dialog;
- mNpcDialogs[npcId] = wrap;
- }
- }
- else
- {
- dialog = diag->second.dialog;
- }
+ getNpc(msg, msg.getId() == SMSG_NPC_CHOICE
+ || msg.getId() == SMSG_NPC_MESSAGE);
switch (msg.getId())
{
case SMSG_NPC_CHOICE:
- if (dialog)
- {
- dialog->choiceRequest();
- dialog->parseListItems(msg.readString(msg.getLength() - 8));
- }
- else
- {
- msg.readString(msg.getLength() - 8);
- }
+ processNpcChoice(msg);
break;
case SMSG_NPC_MESSAGE:
- if (dialog)
- dialog->addText(msg.readString(msg.getLength() - 8));
- else
- msg.readString(msg.getLength() - 8);
+ processNpcMessage(msg);
break;
case SMSG_NPC_CLOSE:
- // Show the close button
- if (dialog)
- dialog->showCloseButton();
+ processNpcClose(msg);
break;
case SMSG_NPC_NEXT:
- // Show the next button
- if (dialog)
- dialog->showNextButton();
+ processNpcNext(msg);
break;
case SMSG_NPC_INT_INPUT:
- // Request for an integer
- if (dialog)
- dialog->integerRequest(0);
+ processNpcIntInput(msg);
break;
case SMSG_NPC_STR_INPUT:
- // Request for a string
- if (dialog)
- dialog->textRequest("");
+ processNpcStrInput(msg);
break;
default:
@@ -147,6 +94,8 @@ void NpcHandler::handleMessage(Net::MessageIn &msg)
if (player_node && player_node->getCurrentAction() != Being::SIT)
player_node->setAction(Being::STAND);
+
+ mDialog = 0;
}
void NpcHandler::talk(int npcId)
@@ -199,18 +148,6 @@ void NpcHandler::stringInput(int npcId, const std::string &value)
outMsg.writeInt8(0); // Prevent problems with string reading
}
-void NpcHandler::sendLetter(int npcId A_UNUSED,
- const std::string &recipient A_UNUSED,
- const std::string &text A_UNUSED)
-{
- // TODO
-}
-
-void NpcHandler::startShopping(int beingId A_UNUSED)
-{
- // TODO
-}
-
void NpcHandler::buy(int beingId)
{
MessageOut outMsg(CMSG_NPC_BUY_SELL_REQUEST);
@@ -253,21 +190,42 @@ void NpcHandler::sellItem(int beingId A_UNUSED, int itemId, int amount)
outMsg.writeInt16(static_cast<Sint16>(amount));
}
-void NpcHandler::endShopping(int beingId A_UNUSED)
+int NpcHandler::getNpc(Net::MessageIn &msg, bool haveLength)
{
- // TODO
-}
+ if (haveLength)
+ msg.readInt16(); // length
-void NpcHandler::clearDialogs()
-{
- NpcDialogs::iterator it = mNpcDialogs.begin();
- NpcDialogs::iterator it_end = mNpcDialogs.end();
- while (it != it_end)
+ const int npcId = msg.readInt32();
+
+ NpcDialogs::iterator diag = mNpcDialogs.find(npcId);
+ mDialog = 0;
+
+ if (diag == mNpcDialogs.end())
+ {
+ // Empty dialogs don't help
+ if (msg.getId() == SMSG_NPC_CLOSE)
+ {
+ closeDialog(npcId);
+ return npcId;
+ }
+ else if (msg.getId() == SMSG_NPC_NEXT)
+ {
+ nextDialog(npcId);
+ return npcId;
+ }
+ else
+ {
+ mDialog = new NpcDialog(npcId);
+ Wrapper wrap;
+ wrap.dialog = mDialog;
+ mNpcDialogs[npcId] = wrap;
+ }
+ }
+ else
{
- delete (*it).second.dialog;
- ++ it;
+ mDialog = diag->second.dialog;
}
- mNpcDialogs.clear();
+ return npcId;
}
} // namespace TmwAthena
diff --git a/src/net/tmwa/npchandler.h b/src/net/tmwa/npchandler.h
index 1b4455854..624f64cbc 100644
--- a/src/net/tmwa/npchandler.h
+++ b/src/net/tmwa/npchandler.h
@@ -26,6 +26,8 @@
#include "net/net.h"
#include "net/npchandler.h"
+#include "net/ea/npchandler.h"
+
#include "net/tmwa/messagehandler.h"
#include <map>
@@ -41,7 +43,7 @@ class NpcDialog;
namespace TmwAthena
{
-class NpcHandler : public MessageHandler, public Net::NpcHandler
+class NpcHandler : public MessageHandler, public Ea::NpcHandler
{
public:
NpcHandler();
@@ -60,11 +62,6 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler
void stringInput(int npcId, const std::string &value);
- void sendLetter(int npcId, const std::string &recipient,
- const std::string &text);
-
- void startShopping(int beingId);
-
void buy(int beingId);
void sell(int beingId);
@@ -73,17 +70,7 @@ class NpcHandler : public MessageHandler, public Net::NpcHandler
void sellItem(int beingId, int itemId, int amount);
- void endShopping(int beingId);
-
- void clearDialogs();
-
- private:
- typedef struct
- {
- NpcDialog* dialog;
- } Wrapper;
- typedef std::map<int, Wrapper> NpcDialogs;
- NpcDialogs mNpcDialogs;
+ int getNpc(Net::MessageIn &msg, bool haveLength);
};
} // namespace TmwAthena
diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp
index 18bed203f..f20ea64a0 100644
--- a/src/net/tmwa/playerhandler.cpp
+++ b/src/net/tmwa/playerhandler.cpp
@@ -22,129 +22,16 @@
#include "net/tmwa/playerhandler.h"
-#include "event.h"
-#include "game.h"
-#include "localplayer.h"
#include "log.h"
-#include "party.h"
-#include "playerinfo.h"
-#include "units.h"
-
-#include "gui/gui.h"
-#include "gui/okdialog.h"
-#include "gui/skilldialog.h"
-#include "gui/statuswindow.h"
-#include "gui/viewport.h"
#include "net/messagein.h"
-#include "net/messageout.h"
#include "net/tmwa/protocol.h"
#include "net/tmwa/npchandler.h"
#include "net/tmwa/inventoryhandler.h"
-#include "utils/stringutils.h"
-#include "utils/gettext.h"
-
#include "debug.h"
-extern OkDialog *weightNotice;
-extern OkDialog *deathNotice;
-extern int weightNoticeTime;
-
-// Max. distance we are willing to scroll after a teleport;
-// everything beyond will reset the port hard.
-static const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
-
-// TODO Move somewhere else
-namespace
-{
- /**
- * Listener used for handling the overweigth message.
- */
- struct WeightListener : public gcn::ActionListener
- {
- void action(const gcn::ActionEvent &event A_UNUSED)
- {
- weightNotice = NULL;
- }
- } weightListener;
-
- /**
- * Listener used for handling death message.
- */
- struct DeathListener : public gcn::ActionListener
- {
- void action(const gcn::ActionEvent &event A_UNUSED)
- {
- Net::getPlayerHandler()->respawn();
- deathNotice = NULL;
-
- Client::closeDialogs();
-
- if (viewport)
- viewport->closePopupMenu();
-
- TmwAthena::NpcHandler *handler =
- static_cast<TmwAthena::NpcHandler*>(Net::getNpcHandler());
- if (handler)
- handler->clearDialogs();
- if (player_node)
- player_node->respawn();
- }
- } deathListener;
-
-} // anonymous namespace
-
-static const char *randomDeathMessage()
-{
- static char const *const deadMsg[] =
- {
- N_("You are dead."),
- N_("We regret to inform you that your character was killed in "
- "battle."),
- N_("You are not that alive anymore."),
- N_("The cold hands of the grim reaper are grabbing for your soul."),
- N_("Game Over!"),
- N_("Insert coin to continue."),
- N_("No, kids. Your character did not really die. It... "
- "err... went to a better place."),
- N_("Your plan of breaking your enemies weapon by "
- "bashing it with your throat failed."),
- N_("I guess this did not run too well."),
- // NetHack reference:
- N_("Do you want your possessions identified?"),
- // Secret of Mana reference:
- N_("Sadly, no trace of you was ever found..."),
- // Final Fantasy VI reference:
- N_("Annihilated."),
- // Earthbound reference:
- N_("Looks like you got your head handed to you."),
- // Leisure Suit Larry 1 reference:
- N_("You screwed up again, dump your body down the tubes "
- "and get you another one."),
- // Monty Python references (Dead Parrot sketch mostly):
- N_("You're not dead yet. You're just resting."),
- N_("You are no more."),
- N_("You have ceased to be."),
- N_("You've expired and gone to meet your maker."),
- N_("You're a stiff."),
- N_("Bereft of life, you rest in peace."),
- N_("If you weren't so animated, you'd be pushing up the daisies."),
- N_("Your metabolic processes are now history."),
- N_("You're off the twig."),
- N_("You've kicked the bucket."),
- N_("You've shuffled off your mortal coil, run down the "
- "curtain and joined the bleedin' choir invisibile."),
- N_("You are an ex-player."),
- N_("You're pining for the fjords.")
- };
-
- const int random = static_cast<int>(rand() % (sizeof(deadMsg)
- / sizeof(deadMsg[0])));
- return gettext(deadMsg[random]);
-}
-
extern Net::PlayerHandler *playerHandler;
namespace TmwAthena
@@ -174,469 +61,40 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg)
switch (msg.getId())
{
case SMSG_WALK_RESPONSE:
- /*
- * This client assumes that all walk messages succeed,
- * and that the server will send a correction notice
- * otherwise.
- */
- Uint16 srcX, srcY, dstX, dstY;
- msg.readInt32(); //tick
- msg.readCoordinatePair(srcX, srcY, dstX, dstY);
- if (player_node)
- player_node->setRealPos(dstX, dstY);
-// if (debugChatTab)
-// debugChatTab->chatLog("move resp: " + toString((int)srcX) + "," + toString((int)srcY) + " "
-// + toString((int)dstX) + "," + toString((int)dstY));
-
+ processWalkResponse(msg);
break;
case SMSG_PLAYER_WARP:
- {
- std::string mapPath = msg.readString(16);
- int x = msg.readInt16();
- int y = msg.readInt16();
-
- logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
-
- if (!player_node)
- logger->log1("SMSG_PLAYER_WARP player_node null");
-
- /*
- * We must clear the local player's target *before* the call
- * to changeMap, as it deletes all beings.
- */
- if (player_node)
- player_node->stopAttack();
-
- Game *game = Game::instance();
-
- const std::string &currentMapName = game->getCurrentMapName();
- bool sameMap = (currentMapName == mapPath);
-
- // Switch the actual map, deleting the previous one if necessary
- mapPath = mapPath.substr(0, mapPath.rfind("."));
- game->changeMap(mapPath);
-
- float scrollOffsetX = 0.0f;
- float scrollOffsetY = 0.0f;
-
- if (player_node)
- {
- Map *map = game->getCurrentMap();
- if (map)
- {
- if (x >= map->getWidth())
- x = map->getWidth() - 1;
- if (y >= map->getHeight())
- y = map->getHeight() - 1;
- if (x < 0)
- x = 0;
- if (y < 0)
- y = 0;
- /* Scroll if neccessary */
- if (!sameMap
- || (abs(x - player_node->getTileX())
- > MAP_TELEPORT_SCROLL_DISTANCE)
- || (abs(y - player_node->getTileY())
- > MAP_TELEPORT_SCROLL_DISTANCE))
- {
- scrollOffsetX = static_cast<float>((x
- - player_node->getTileX())
- * map->getTileWidth());
- scrollOffsetY = static_cast<float>((y
- - player_node->getTileY())
- * map->getTileHeight());
- }
- }
-
- player_node->setAction(Being::STAND);
- player_node->setTileCoords(x, y);
- player_node->navigateClean();
-// player_node->updateNavigateList();
- }
-
- logger->log("Adjust scrolling by %d:%d",
- static_cast<int>(scrollOffsetX),
- static_cast<int>(scrollOffsetY));
-
- if (viewport)
- viewport->scrollBy(scrollOffsetX, scrollOffsetY);
- }
+ processPlayerWarp(msg);
break;
case SMSG_PLAYER_STAT_UPDATE_1:
- {
- int type = msg.readInt16();
- int value = msg.readInt32();
- if (!player_node)
- return;
-
- switch (type)
- {
- case 0x0000:
- player_node->setWalkSpeed(Vector(static_cast<float>(
- value), static_cast<float>(value), 0));
- PlayerInfo::setStatBase(WALK_SPEED, value);
- PlayerInfo::setStatMod(WALK_SPEED, 0);
- break;
- case 0x0004: break; // manner
- case 0x0005:
- PlayerInfo::setAttribute(HP, value);
- if (player_node->isInParty() && Party::getParty(1))
- {
- PartyMember *m = Party::getParty(1)
- ->getMember(player_node->getId());
- if (m)
- {
- m->setHp(value);
- m->setMaxHp(PlayerInfo::getAttribute(MAX_HP));
- }
- }
- break;
- case 0x0006:
- PlayerInfo::setAttribute(MAX_HP, value);
-
- if (player_node->isInParty() && Party::getParty(1))
- {
- PartyMember *m = Party::getParty(1)->getMember(
- player_node->getId());
- if (m)
- {
- m->setHp(PlayerInfo::getAttribute(HP));
- m->setMaxHp(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);
- if (player_node)
- {
- player_node->setLevel(value);
- player_node->updateName();
- }
- break;
- case 0x000c:
- PlayerInfo::setAttribute(SKILL_POINTS, value);
- if (skillDialog)
- skillDialog->update();
- break;
- case 0x0018:
- if (!weightNotice)
- {
- const int max
- = PlayerInfo::getAttribute(MAX_WEIGHT) / 2;
- const int total
- = PlayerInfo::getAttribute(TOTAL_WEIGHT);
- if (value >= max && total < max)
- {
- weightNoticeTime = cur_time + 10;
- weightNotice = new OkDialog(_("Message"),
- _("You are carrying more than "
- "half your weight. You are "
- "unable to regain health."), false);
- weightNotice->addActionListener(
- &weightListener);
- }
- else if (value < max && total >= max)
- {
- weightNoticeTime = cur_time + 10;
- weightNotice = new OkDialog(_("Message"),
- _("You are carrying less than "
- "half your weight. You "
- "can regain health."), false);
- weightNotice->addActionListener(
- &weightListener);
- }
- }
- PlayerInfo::setAttribute(TOTAL_WEIGHT, value);
- break;
- case 0x0019:
- PlayerInfo::setAttribute(MAX_WEIGHT, 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);
- PlayerInfo::setStatBase(ATTACK_SPEED, value);
- PlayerInfo::setStatMod(ATTACK_SPEED, 0);
- break;
-
- case 0x0037:
- PlayerInfo::setStatBase(JOB, value);
- break;
-
- case 500:
- player_node->setGMLevel(value);
- break;
-
- default:
- logger->log("QQQQ PLAYER_STAT_UPDATE_1 "
- + toString(type) + "," + toString(value));
- break;
- }
-
- if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice)
- {
- deathNotice = new OkDialog(_("Message"),
- randomDeathMessage(),
- false);
- deathNotice->addActionListener(&deathListener);
- player_node->setAction(Being::DEAD);
- }
- }
+ processPlayerStatUpdate1(msg);
break;
case SMSG_PLAYER_STAT_UPDATE_2:
- {
- int type = msg.readInt16();
- switch (type)
- {
- case 0x0001:
- PlayerInfo::setAttribute(EXP, msg.readInt32());
- break;
- case 0x0002:
- PlayerInfo::setStatExperience(JOB, msg.readInt32(),
- PlayerInfo::getStatExperience(JOB).second);
- break;
- case 0x0014:
- {
- int oldMoney = PlayerInfo::getAttribute(MONEY);
- int newMoney = msg.readInt32();
- if (newMoney > oldMoney)
- {
- SERVER_NOTICE(strprintf(_("You picked up %s."),
- Units::formatCurrency(newMoney -
- oldMoney).c_str()))
- }
- else if (newMoney < oldMoney)
- {
- SERVER_NOTICE(strprintf(_("You spent %s."),
- Units::formatCurrency(oldMoney -
- newMoney).c_str()))
- }
-
- PlayerInfo::setAttribute(MONEY, newMoney);
- break;
- }
- case 0x0016:
- PlayerInfo::setAttribute(EXP_NEEDED, msg.readInt32());
- break;
- case 0x0017:
- PlayerInfo::setStatExperience(JOB,
- PlayerInfo::getStatExperience(JOB).first,
- msg.readInt32());
- break;
- default:
- logger->log("QQQQ PLAYER_STAT_UPDATE_2 " + toString(type));
- break;
- }
+ processPlayerStatUpdate2(msg);
break;
- }
+
case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute
- {
- int type = msg.readInt32();
- int base = msg.readInt32();
- int bonus = msg.readInt32();
-
- PlayerInfo::setStatBase(type, base, false);
- PlayerInfo::setStatMod(type, bonus);
- }
+ processPlayerStatUpdate3(msg);
break;
case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack
- {
- int type = msg.readInt16();
- int ok = msg.readInt8();
- int value = msg.readInt8();
-
- if (ok != 1)
- {
- int oldValue = PlayerInfo::getStatBase(type);
- int points = PlayerInfo::getAttribute(CHAR_POINTS);
- points += oldValue - value;
- PlayerInfo::setAttribute(CHAR_POINTS, points);
- SERVER_NOTICE(_("Cannot raise skill!"))
- }
-
- PlayerInfo::setStatBase(type, value);
- }
+ processPlayerStatUpdate4(msg);
break;
// Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
- PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
- {
- int val = msg.readInt8();
- PlayerInfo::setStatBase(STR, val);
- if (statusWindow)
- statusWindow->setPointsNeeded(STR, msg.readInt8());
- else
- msg.readInt8();
-
- val = msg.readInt8();
- PlayerInfo::setStatBase(AGI, val);
- if (statusWindow)
- statusWindow->setPointsNeeded(AGI, msg.readInt8());
- else
- msg.readInt8();
-
- val = msg.readInt8();
- PlayerInfo::setStatBase(VIT, val);
- if (statusWindow)
- statusWindow->setPointsNeeded(VIT, msg.readInt8());
- else
- msg.readInt8();
-
- val = msg.readInt8();
- PlayerInfo::setStatBase(INT, val);
- if (statusWindow)
- statusWindow->setPointsNeeded(INT, msg.readInt8());
- else
- msg.readInt8();
-
- val = msg.readInt8();
- PlayerInfo::setStatBase(DEX, val);
- if (statusWindow)
- statusWindow->setPointsNeeded(DEX, msg.readInt8());
- else
- msg.readInt8();
-
- val = msg.readInt8();
- PlayerInfo::setStatBase(LUK, val);
- if (statusWindow)
- statusWindow->setPointsNeeded(LUK, msg.readInt8());
- else
- msg.readInt8();
-
- PlayerInfo::setStatBase(ATK, msg.readInt16(), false);
- PlayerInfo::setStatMod(ATK, msg.readInt16());
-
- val = msg.readInt16();
- PlayerInfo::setStatBase(MATK, val, false);
-
- val = msg.readInt16();
- PlayerInfo::setStatMod(MATK, val);
-
- 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
+ processPlayerStatUpdate5(msg);
break;
case SMSG_PLAYER_STAT_UPDATE_6:
- {
- int type = msg.readInt16();
- if (statusWindow)
- {
- switch (type)
- {
- case 0x0020:
- statusWindow->setPointsNeeded(STR, msg.readInt8());
- break;
- case 0x0021:
- statusWindow->setPointsNeeded(AGI, msg.readInt8());
- break;
- case 0x0022:
- statusWindow->setPointsNeeded(VIT, msg.readInt8());
- break;
- case 0x0023:
- statusWindow->setPointsNeeded(INT, msg.readInt8());
- break;
- case 0x0024:
- statusWindow->setPointsNeeded(DEX, msg.readInt8());
- break;
- case 0x0025:
- statusWindow->setPointsNeeded(LUK, msg.readInt8());
- break;
- default:
- logger->log("QQQQ PLAYER_STAT_UPDATE_6 "
- + toString(type));
- break;
- }
- }
+ processPlayerStatUpdate6(msg);
break;
- }
+
case SMSG_PLAYER_ARROW_MESSAGE:
- {
- int type = msg.readInt16();
-
- switch (type)
- {
- case 0:
- {
- SERVER_NOTICE(_("Equip arrows first."))
- }
- break;
- case 3:
- // arrows equiped
- break;
- default:
- logger->log("QQQQ 0x013b: Unhandled message %i", type);
- break;
- }
- }
+ processPlayerArrowMessage(msg);
break;
default:
@@ -675,11 +133,6 @@ void PlayerHandler::increaseAttribute(int attr)
}
}
-void PlayerHandler::decreaseAttribute(int attr A_UNUSED)
-{
- // Supported by eA?
-}
-
void PlayerHandler::increaseSkill(unsigned short skillId)
{
if (PlayerInfo::getAttribute(SKILL_POINTS) <= 0)
@@ -748,37 +201,4 @@ void PlayerHandler::respawn()
outMsg.writeInt8(0);
}
-void PlayerHandler::ignorePlayer(const std::string &player A_UNUSED,
- bool ignore A_UNUSED)
-{
- // TODO
-}
-
-void PlayerHandler::ignoreAll(bool ignore A_UNUSED)
-{
- // TODO
-}
-
-bool PlayerHandler::canUseMagic() const
-{
- return PlayerInfo::getStatEffective(MATK) > 0;
-}
-
-bool PlayerHandler::canCorrectAttributes() const
-{
- return false;
-}
-
-int PlayerHandler::getJobLocation() const
-{
- return JOB;
-}
-
-Vector PlayerHandler::getDefaultWalkSpeed() const
-{
- // Return an normalized speed for any side
- // as the offset is calculated elsewhere.
- return Vector(150, 150, 0);
-}
-
} // namespace TmwAthena
diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h
index fc4230856..4fd108e94 100644
--- a/src/net/tmwa/playerhandler.h
+++ b/src/net/tmwa/playerhandler.h
@@ -26,6 +26,8 @@
#include "net/net.h"
#include "net/playerhandler.h"
+#include "net/ea/playerhandler.h"
+
#include "net/tmwa/messagehandler.h"
#ifdef __GNUC__
@@ -37,7 +39,7 @@
namespace TmwAthena
{
-class PlayerHandler : public MessageHandler, public Net::PlayerHandler
+class PlayerHandler : public MessageHandler, public Ea::PlayerHandler
{
public:
PlayerHandler();
@@ -49,7 +51,6 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler
void emote(Uint8 emoteId);
void increaseAttribute(int attr);
- void decreaseAttribute(int attr);
void increaseSkill(unsigned short skillId);
void pickUp(FloorItem *floorItem);
@@ -58,16 +59,6 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler
void changeAction(Being::Action action);
void respawn();
-
- void ignorePlayer(const std::string &player, bool ignore);
- void ignoreAll(bool ignore);
-
- bool canUseMagic() const;
- bool canCorrectAttributes() const;
-
- int getJobLocation() const;
-
- Vector getDefaultWalkSpeed() const;
};
} // namespace TmwAthena