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.cpp145
1 files changed, 122 insertions, 23 deletions
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index be8412d9..c43c674f 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -40,11 +40,13 @@
const int EMOTION_TIME = 150; /**< Duration of emotion icon */
-BeingHandler::BeingHandler()
+BeingHandler::BeingHandler(bool enableSync):
+ mSync(enableSync)
{
static const Uint16 _messages[] = {
SMSG_BEING_VISIBLE,
SMSG_BEING_MOVE,
+ SMSG_BEING_MOVE2,
SMSG_BEING_REMOVE,
SMSG_BEING_ACTION,
SMSG_BEING_LEVELUP,
@@ -55,6 +57,8 @@ BeingHandler::BeingHandler()
SMSG_PLAYER_UPDATE_1,
SMSG_PLAYER_UPDATE_2,
SMSG_PLAYER_MOVE,
+ SMSG_PLAYER_STOP,
+ SMSG_PLAYER_MOVE_TO_ATTACK,
0x0119,
0
};
@@ -66,6 +70,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
Uint32 id;
Uint16 job, speed;
Uint16 headTop, headMid, headBottom;
+ Uint16 shoes, gloves, cape, misc1, misc2;
+ Uint16 weapon, shield;
Sint16 param1;
Sint8 type;
Being *srcBeing, *dstBeing;
@@ -78,8 +84,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
// Information about a being in range
id = msg->readInt32();
speed = msg->readInt16();
- msg->readInt16(); // unknown
- msg->readInt16(); // unknown
+ msg->readInt16(); // opt1
+ msg->readInt16(); // opt2
msg->readInt16(); // option
job = msg->readInt16(); // class
@@ -122,8 +128,10 @@ void BeingHandler::handleMessage(MessageIn *msg)
headTop = msg->readInt16();
headMid = msg->readInt16();
hairColor = msg->readInt16();
- msg->readInt16(); // clothes color -not used
+ msg->readInt16(); // clothes color - not used
msg->readInt16(); // head dir
+ shoes = 0;
+ gloves = 0;
msg->readInt16(); // guild
msg->readInt16(); // unknown
msg->readInt16(); // unknown
@@ -133,9 +141,11 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setGender(1 - msg->readInt8()); // gender
// Set these after the gender, as the sprites may be gender-specific
- dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
- dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, headMid);
- dstBeing->setSprite(Being::HAT_SPRITE, headTop);
+ dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
+ dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, headMid);
+ dstBeing->setSprite(Being::HAT_SPRITE, headTop);
+ dstBeing->setSprite(Being::SHOE_SPRITE, shoes);
+ dstBeing->setSprite(Being::GLOVES_SPRITE, gloves);
dstBeing->setHairStyle(hairStyle, hairColor);
if (msg->getId() == SMSG_BEING_MOVE)
@@ -159,6 +169,33 @@ void BeingHandler::handleMessage(MessageIn *msg)
msg->readInt8(); // unknown / sit
break;
+ case SMSG_BEING_MOVE2:
+ /*
+ * A simplified movement packet, used by the
+ * later versions of eAthena for both mobs and
+ * players
+ */
+ dstBeing = beingManager->findBeing(msg->readInt32());
+
+ Uint16 srcX, srcY, dstX, dstY;
+ msg->readCoordinatePair(srcX, srcY, dstX, dstY);
+ msg->readInt32(); // Server tick
+
+ /*
+ * This packet doesn't have enough info to actually
+ * create a new being, so if the being isn't found,
+ * we'll just pretend the packet didn't happen
+ */
+
+ if (dstBeing) {
+ dstBeing->setAction(Being::STAND);
+ dstBeing->mX = srcX;
+ dstBeing->mY = srcY;
+ dstBeing->setDestination(dstX, dstY);
+ }
+
+ break;
+
case SMSG_BEING_REMOVE:
// A being should be removed or has died
dstBeing = beingManager->findBeing(msg->readInt32());
@@ -166,6 +203,11 @@ void BeingHandler::handleMessage(MessageIn *msg)
if (!dstBeing)
break;
+ if (dstBeing == player_node->getTarget())
+ {
+ player_node->stopAttack();
+ }
+
if (msg->readInt8() == 1)
{
dstBeing->setAction(Being::DEAD);
@@ -175,10 +217,6 @@ void BeingHandler::handleMessage(MessageIn *msg)
beingManager->destroyBeing(dstBeing);
}
- if (dstBeing == player_node->getTarget())
- {
- player_node->stopAttack();
- }
break;
case SMSG_BEING_ACTION:
@@ -257,7 +295,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
case SMSG_BEING_CHANGE_LOOKS2:
{
/*
- * SMSG_BEING_CHANGE_LOOKS (0x00c3) and
+ * SMSG_BEING_CHANGE_LOOKS (0x00c3) and
* SMSG_BEING_CHANGE_LOOKS2 (0x01d7) do basically the same
* thing. The difference is that ...LOOKS carries a single
* 8 bit value, where ...LOOKS2 carries two 16 bit values.
@@ -288,7 +326,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 1: // eAthena LOOK_HAIR
dstBeing->setHairStyle(id, -1);
break;
- case 2: // Weapon ID in id, Shield ID in id2
+ case 2: // Weapon ID in id, Shield ID in id2
dstBeing->setSprite(Being::WEAPON_SPRITE, id);
dstBeing->setSprite(Being::SHIELD_SPRITE, id2);
break;
@@ -304,9 +342,24 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 6: // eAthena LOOK_HAIR_COLOR
dstBeing->setHairStyle(-1, id);
break;
+ case 8: // eAthena LOOK_SHIELD
+ dstBeing->setSprite(Being::SHIELD_SPRITE, id);
+ break;
case 9: // eAthena LOOK_SHOES
dstBeing->setSprite(Being::SHOE_SPRITE, id);
break;
+ case 10: // LOOK_GLOVES
+ dstBeing->setSprite(Being::GLOVES_SPRITE, id);
+ break;
+ case 11: // LOOK_CAPE
+ dstBeing->setSprite(Being::CAPE_SPRITE, id);
+ break;
+ case 12:
+ dstBeing->setSprite(Being::MISC1_SPRITE, id);
+ break;
+ case 13:
+ dstBeing->setSprite(Being::MISC2_SPRITE, id);
+ break;
default:
logger->log("SMSG_BEING_CHANGE_LOOKS: unsupported type: "
"%d, id: %d", type, id);
@@ -328,9 +381,9 @@ void BeingHandler::handleMessage(MessageIn *msg)
// 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
+ cape = msg->readInt16();
+ misc1 = msg->readInt16();
+ misc2 = msg->readInt16();
job = msg->readInt16();
dstBeing = beingManager->findBeing(id);
@@ -343,9 +396,9 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
hairStyle = msg->readInt16();
- dstBeing->setSprite(Being::WEAPON_SPRITE, msg->readInt16());
- dstBeing->setSprite(Being::SHIELD_SPRITE, msg->readInt16());
- headBottom = msg->readInt16();
+ weapon = msg->readInt16();
+ shield = msg->readInt16();
+ headBottom = msg->readInt16();
if (msg->getId() == SMSG_PLAYER_MOVE)
{
@@ -355,7 +408,9 @@ void BeingHandler::handleMessage(MessageIn *msg)
headTop = msg->readInt16();
headMid = msg->readInt16();
hairColor = msg->readInt16();
- msg->readInt16(); // clothes color - not used
+ shoes = 0;
+ gloves = 0;
+ msg->readInt16(); // clothes color - not used
msg->readInt16(); // head dir
msg->readInt32(); // guild
msg->readInt32(); // emblem
@@ -364,9 +419,18 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setGender(1 - msg->readInt8()); // gender
// Set these after the gender, as the sprites may be gender-specific
- dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
+ dstBeing->setSprite(Being::WEAPON_SPRITE, weapon);
+ dstBeing->setSprite(Being::SHIELD_SPRITE, shield);
+ dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, headMid);
dstBeing->setSprite(Being::HAT_SPRITE, headTop);
+ dstBeing->setSprite(Being::SHOE_SPRITE, shoes);
+ // Compensation for the unpatched TMW server
+ if (gloves > 10)
+ dstBeing->setSprite(Being::GLOVES_SPRITE, gloves);
+ dstBeing->setSprite(Being::CAPE_SPRITE, cape);
+ dstBeing->setSprite(Being::MISC1_SPRITE, misc1);
+ dstBeing->setSprite(Being::MISC2_SPRITE, misc2);
dstBeing->setHairStyle(hairStyle, hairColor);
if (msg->getId() == SMSG_PLAYER_MOVE)
@@ -384,8 +448,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setDirection(dir);
}
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown
+ msg->readInt16(); // GM status
if (msg->getId() == SMSG_PLAYER_UPDATE_1)
{
@@ -406,6 +469,42 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->mFrame = 0;
break;
+ case SMSG_PLAYER_STOP:
+ /*
+ * Instruction from server to stop walking at x, y.
+ *
+ * Some people like having this enabled. Others absolutely
+ * despise it. So I'm setting to so that it only affects the
+ * local player if the person has set a key "EnableSync" to "1"
+ * in their config.xml file.
+ *
+ * This packet will be honored for all other beings, regardless
+ * of the config setting.
+ */
+
+ id = msg->readInt32();
+ if (mSync || id != player_node->getId()) {
+ dstBeing = beingManager->findBeing(id);
+ if (dstBeing) {
+ dstBeing->mX = msg->readInt16();
+ dstBeing->mY = msg->readInt16();
+ if (dstBeing->mAction == Being::WALK) {
+ dstBeing->mFrame = 0;
+ dstBeing->setAction(Being::STAND);
+ }
+ }
+ }
+ break;
+
+ case SMSG_PLAYER_MOVE_TO_ATTACK:
+ /*
+ * This is an *advisory* message, telling the client that
+ * it needs to move the character before attacking
+ * a target (out of range, obstruction in line of fire).
+ * We can safely ignore this...
+ */
+ break;
+
case 0x0119:
// Change in players look
logger->log("0x0119 %i %i %i %x %i", msg->readInt32(),