summaryrefslogtreecommitdiff
path: root/src/net/beinghandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/beinghandler.cpp')
-rw-r--r--src/net/beinghandler.cpp356
1 files changed, 356 insertions, 0 deletions
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
new file mode 100644
index 00000000..9578f5c1
--- /dev/null
+++ b/src/net/beinghandler.cpp
@@ -0,0 +1,356 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "beinghandler.h"
+
+#include <SDL_types.h>
+
+#include "messagein.h"
+#include "protocol.h"
+
+#include "../being.h"
+#include "../beingmanager.h"
+#include "../game.h"
+#include "../localplayer.h"
+#include "../log.h"
+#include "../main.h"
+#include "../sound.h"
+
+const int EMOTION_TIME = 150; /**< Duration of emotion icon */
+
+BeingHandler::BeingHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_BEING_VISIBLE,
+ SMSG_BEING_MOVE,
+ SMSG_BEING_REMOVE,
+ SMSG_BEING_ACTION,
+ SMSG_BEING_LEVELUP,
+ SMSG_BEING_EMOTION,
+ SMSG_BEING_CHANGE_LOOKS,
+ SMSG_BEING_NAME_RESPONSE,
+ SMSG_PLAYER_UPDATE_1,
+ SMSG_PLAYER_UPDATE_2,
+ SMSG_PLAYER_MOVE,
+ 0x0119,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void BeingHandler::handleMessage(MessageIn *msg)
+{
+ Uint32 id;
+ Uint16 job, speed;
+ Sint16 param1;
+ Sint8 type;
+ Being *srcBeing, *dstBeing;
+
+ switch (msg->getId())
+ {
+ case SMSG_BEING_VISIBLE:
+ case SMSG_BEING_MOVE:
+ // Information about a being in range
+ id = msg->readInt32();
+ speed = msg->readInt16();
+ msg->readInt16(); // unknown
+ msg->readInt16(); // unknown
+ msg->readInt16(); // option
+ job = msg->readInt16(); // class
+
+ dstBeing = beingManager->findBeing(id);
+
+ if (dstBeing == NULL)
+ {
+ // Being with id >= 110000000 and job 0 are better
+ // known as ghosts, so don't create those.
+ if (job == 0 && id >= 110000000)
+ {
+ break;
+ }
+
+ dstBeing = beingManager->createBeing(id, job);
+ }
+ else if (msg->getId() == 0x0078)
+ {
+ dstBeing->clearPath();
+ dstBeing->mFrame = 0;
+ dstBeing->walk_time = tick_time;
+ dstBeing->action = Being::STAND;
+ }
+
+ // Prevent division by 0 when calculating frame
+ if (speed == 0) { speed = 150; }
+
+ dstBeing->setWalkSpeed(speed);
+ dstBeing->job = job;
+ dstBeing->setHairStyle(msg->readInt16());
+ dstBeing->setWeapon(msg->readInt16());
+ msg->readInt16(); // head option bottom
+
+ if (msg->getId() == SMSG_BEING_MOVE)
+ {
+ msg->readInt32(); // server tick
+ }
+
+ msg->readInt16(); // shield
+ msg->readInt16(); // head option top
+ msg->readInt16(); // head option mid
+ dstBeing->setHairColor(msg->readInt16());
+ msg->readInt16(); // unknown
+ msg->readInt16(); // head dir
+ msg->readInt16(); // guild
+ msg->readInt16(); // unknown
+ msg->readInt16(); // unknown
+ msg->readInt16(); // manner
+ msg->readInt16(); // karma
+ msg->readInt8(); // unknown
+ msg->readInt8(); // sex
+
+ if (msg->getId() == SMSG_BEING_MOVE)
+ {
+ Uint16 srcX, srcY, dstX, dstY;
+ msg->readCoordinatePair(srcX, srcY, dstX, dstY);
+ dstBeing->action = Being::STAND;
+ dstBeing->x = srcX;
+ dstBeing->y = srcY;
+ dstBeing->setDestination(dstX, dstY);
+ }
+ else
+ {
+ msg->readCoordinates(dstBeing->x, dstBeing->y,
+ dstBeing->direction);
+ }
+
+ msg->readInt8(); // unknown
+ msg->readInt8(); // unknown
+ msg->readInt8(); // unknown / sit
+ break;
+
+ case SMSG_BEING_REMOVE:
+ // A being should be removed or has died
+ dstBeing = beingManager->findBeing(msg->readInt32());
+
+ if (!dstBeing)
+ break;
+
+ if (msg->readInt8() == 1)
+ {
+ // Death
+ switch (dstBeing->getType())
+ {
+ case Being::MONSTER:
+ dstBeing->action = Being::MONSTER_DEAD;
+ dstBeing->mFrame = 0;
+ dstBeing->walk_time = tick_time;
+ break;
+
+ default:
+ dstBeing->action = Being::DEAD;
+ break;
+ }
+ }
+ else
+ {
+ beingManager->destroyBeing(dstBeing);
+ }
+
+ if (dstBeing == player_node->getTarget())
+ {
+ player_node->stopAttack();
+ }
+ break;
+
+ case SMSG_BEING_ACTION:
+ srcBeing = beingManager->findBeing(msg->readInt32());
+ dstBeing = beingManager->findBeing(msg->readInt32());
+ msg->readInt32(); // server tick
+ msg->readInt32(); // src speed
+ msg->readInt32(); // dst speed
+ param1 = msg->readInt16();
+ msg->readInt16(); // param 2
+ type = msg->readInt8();
+ msg->readInt16(); // param 3
+
+ switch (type)
+ {
+ case 0: // Damage
+ if (dstBeing == NULL) break;
+
+ dstBeing->setDamage(param1, SPEECH_TIME);
+
+ if (srcBeing != NULL &&
+ srcBeing != player_node)
+ {
+ // buggy
+ srcBeing->action = Being::ATTACK;
+ srcBeing->mFrame = 0;
+ srcBeing->walk_time = tick_time;
+ }
+ break;
+
+ case 2: // Sit
+ if (srcBeing == NULL) break;
+ srcBeing->mFrame = 0;
+ srcBeing->action = Being::SIT;
+ break;
+
+ case 3: // Stand up
+ if (srcBeing == NULL) break;
+ srcBeing->mFrame = 0;
+ srcBeing->action = Being::STAND;
+ break;
+ }
+ break;
+
+ case SMSG_BEING_LEVELUP:
+ if ((Uint32)msg->readInt32() == player_node->getId()) {
+ logger->log("Level up");
+ sound.playSfx("sfx/levelup.ogg");
+ } else {
+ logger->log("Someone else went level up");
+ }
+ msg->readInt32(); // type
+ break;
+
+ case SMSG_BEING_EMOTION:
+ if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ {
+ break;
+ }
+
+ dstBeing->emotion = msg->readInt8();
+ dstBeing->emotion_time = EMOTION_TIME;
+ break;
+
+ case SMSG_BEING_CHANGE_LOOKS:
+ if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ {
+ break;
+ }
+
+ switch (msg->readInt8()) {
+ case 1:
+ dstBeing->setHairStyle(msg->readInt8());
+ break;
+ case 2:
+ dstBeing->setWeapon(msg->readInt8());
+ break;
+ case 6:
+ dstBeing->setHairColor(msg->readInt8());
+ break;
+ default:
+ msg->readInt8(); // unsupported
+ break;
+ }
+ break;
+
+ case SMSG_BEING_NAME_RESPONSE:
+ if ((dstBeing = beingManager->findBeing(msg->readInt32())))
+ {
+ dstBeing->setName(msg->readString(24));
+ }
+ break;
+
+ case SMSG_PLAYER_UPDATE_1:
+ case SMSG_PLAYER_UPDATE_2:
+ case SMSG_PLAYER_MOVE:
+ // An update about a player, potentially including movement.
+ id = msg->readInt32();
+ speed = msg->readInt16();
+ msg->readInt16(); // option 1
+ msg->readInt16(); // option 2
+ msg->readInt16(); // option
+ job = msg->readInt16();
+
+ dstBeing = beingManager->findBeing(id);
+
+ if (dstBeing == NULL)
+ {
+ dstBeing = beingManager->createBeing(id, job);
+ }
+
+ dstBeing->setWalkSpeed(speed);
+ dstBeing->job = job;
+ dstBeing->setHairStyle(msg->readInt16());
+ dstBeing->setWeaponById(msg->readInt16()); // item id 1
+ msg->readInt16(); // item id 2
+ msg->readInt16(); // head option bottom
+
+ if (msg->getId() == SMSG_PLAYER_MOVE)
+ {
+ msg->readInt32(); // server tick
+ }
+
+ msg->readInt16(); // head option top
+ msg->readInt16(); // head option mid
+ dstBeing->setHairColor(msg->readInt16());
+ msg->readInt16(); // unknown
+ msg->readInt16(); // head dir
+ msg->readInt32(); // guild
+ msg->readInt32(); // emblem
+ msg->readInt16(); // manner
+ msg->readInt8(); // karma
+ msg->readInt8(); // sex
+
+ if (msg->getId() == SMSG_PLAYER_MOVE)
+ {
+ Uint16 srcX, srcY, dstX, dstY;
+ msg->readCoordinatePair(srcX, srcY, dstX, dstY);
+ dstBeing->x = srcX;
+ dstBeing->y = srcY;
+ dstBeing->setDestination(dstX, dstY);
+ }
+ else
+ {
+ msg->readCoordinates(dstBeing->x, dstBeing->y,
+ dstBeing->direction);
+ }
+
+ msg->readInt8(); // unknown
+ msg->readInt8(); // unknown
+
+ if (msg->getId() == SMSG_PLAYER_UPDATE_1)
+ {
+ if (msg->readInt8() == 2)
+ {
+ dstBeing->action = Being::SIT;
+ }
+ }
+ else if (msg->getId() == SMSG_PLAYER_MOVE)
+ {
+ msg->readInt8(); // unknown
+ }
+
+ msg->readInt8(); // Lv
+ msg->readInt8(); // unknown
+
+ dstBeing->walk_time = tick_time;
+ dstBeing->mFrame = 0;
+ break;
+
+ case 0x0119:
+ // Change in players look
+ break;
+ }
+}