diff options
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/net/ea/eaprotocol.h | 23 | ||||
-rw-r--r-- | src/net/ea/npchandler.cpp | 118 | ||||
-rw-r--r-- | src/net/ea/npchandler.h | 83 | ||||
-rw-r--r-- | src/net/ea/playerhandler.cpp | 639 | ||||
-rw-r--r-- | src/net/ea/playerhandler.h | 79 | ||||
-rw-r--r-- | src/net/tmwa/npchandler.cpp | 126 | ||||
-rw-r--r-- | src/net/tmwa/npchandler.h | 21 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.cpp | 602 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.h | 15 |
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 ¤tMapName = 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 ¤tMapName = 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 |