diff options
Diffstat (limited to 'src/net/beinghandler.cpp')
-rw-r--r-- | src/net/beinghandler.cpp | 145 |
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(), |