diff options
-rw-r--r-- | src/net/ea/beinghandler.cpp | 240 | ||||
-rw-r--r-- | src/net/ea/beinghandler.h | 3 | ||||
-rw-r--r-- | src/net/eathena/beinghandler.cpp | 7 | ||||
-rw-r--r-- | src/net/eathena/beinghandler.h | 5 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.cpp | 249 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.h | 2 |
6 files changed, 256 insertions, 250 deletions
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp index 7ee755a5f..cd8158781 100644 --- a/src/net/ea/beinghandler.cpp +++ b/src/net/ea/beinghandler.cpp @@ -95,246 +95,6 @@ void BeingHandler::setSprite(Being *const being, const unsigned int slot, being->updateSprite(slot, id, color, colorId, isWeapon, isTempSprite); } -void BeingHandler::processBeingVisibleOrMove(Net::MessageIn &msg, - const bool visible) -{ - BLOCK_START("BeingHandler::processBeingVisibleOrMove") - if (!actorManager) - { - BLOCK_END("BeingHandler::processBeingVisibleOrMove") - return; - } - - int spawnId; - - // Information about a being in range - const int id = msg.readInt32(); - if (id == mSpawnId) - spawnId = mSpawnId; - else - spawnId = 0; - mSpawnId = 0; - int16_t speed = msg.readInt16(); - const uint16_t stunMode = msg.readInt16(); // opt1 - uint32_t statusEffects = msg.readInt16(); // opt2 - statusEffects |= (static_cast<uint32_t>(msg.readInt16())) << 16; // option - const int16_t job = msg.readInt16(); // class - int disguiseId = 0; - if (id == localPlayer->getId() && job >= 1000) - disguiseId = job; - - Being *dstBeing = actorManager->findBeing(id); - - if (dstBeing && dstBeing->getType() == ActorType::MONSTER - && !dstBeing->isAlive()) - { - actorManager->destroy(dstBeing); - actorManager->erase(dstBeing); - dstBeing = nullptr; - } - - if (!dstBeing) - { - // Being with id >= 110000000 and job 0 are better - // known as ghosts, so don't create those. - if (job == 0 && id >= 110000000) - { - BLOCK_END("BeingHandler::processBeingVisibleOrMove") - return; - } - - if (actorManager->isBlocked(id) == true) - { - BLOCK_END("BeingHandler::processBeingVisibleOrMove") - return; - } - - dstBeing = createBeing(id, job); - - if (!dstBeing) - { - BLOCK_END("BeingHandler::processBeingVisibleOrMove") - return; - } - - if (job == 1022 && killStats) - killStats->jackoAlive(dstBeing->getId()); - } - else - { - if (dstBeing->getType() == ActorType::NPC) - { - actorManager->undelete(dstBeing); - if (serverVersion < 1) - requestNameById(id); - } - } - - if (dstBeing->getType() == ActorType::PLAYER) - dstBeing->setMoveTime(); - - if (spawnId) - { - dstBeing->setAction(BeingAction::SPAWN, 0); - } - else if (visible) - { - dstBeing->clearPath(); - dstBeing->setActionTime(tick_time); - dstBeing->setAction(BeingAction::STAND, 0); - } - - // Prevent division by 0 when calculating frame - if (speed == 0) - speed = 150; - - const uint8_t hairStyle = msg.readUInt8(); - const uint8_t look = msg.readUInt8(); - dstBeing->setSubtype(job, look); - if (dstBeing->getType() == ActorType::MONSTER && localPlayer) - localPlayer->checkNewName(dstBeing); - dstBeing->setWalkSpeed(Vector(speed, speed, 0)); - const uint16_t weapon = msg.readInt16(); - const uint16_t headBottom = msg.readInt16(); - - if (!visible) - msg.readInt32(); // server tick - - const uint16_t shield = msg.readInt16(); - const uint16_t headTop = msg.readInt16(); - const uint16_t headMid = msg.readInt16(); - const uint8_t hairColor = msg.readUInt8(); - msg.readUInt8(); // free - const uint16_t shoes = msg.readInt16(); // clothes color - - uint16_t gloves; - if (dstBeing->getType() == ActorType::MONSTER) - { - if (serverVersion > 0 || tmwServerVersion >= 0x0E0701) - { - const int hp = msg.readInt32(); - const int maxHP = msg.readInt32(); - if (hp && maxHP) - { - dstBeing->setMaxHP(maxHP); - const int oldHP = dstBeing->getHP(); - if (!oldHP || oldHP > hp) - dstBeing->setHP(hp); - } - } - else - { - msg.readInt32(); - msg.readInt32(); - } - gloves = 0; - } - else - { - gloves = msg.readInt16(); // head dir - "abused" as gloves - msg.readInt32(); // guild - msg.readInt16(); // guild emblem - } -// logger->log("being guild: " + toString(guild)); - - msg.readInt16(); // manner - dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 - if (serverVersion > 0 && dstBeing->getType() == ActorType::MONSTER) - { - const int attackRange = static_cast<int>(msg.readUInt8()); // karma - dstBeing->setAttackRange(attackRange); - } - else - { - msg.readUInt8(); // karma - } - uint8_t gender = msg.readUInt8(); - - if (!disguiseId && dstBeing->getType() == ActorType::PLAYER) - { - // reserving bits for future usage - gender &= 3; - dstBeing->setGender(Being::intToGender(gender)); - // Set these after the gender, as the sprites may be gender-specific - setSprite(dstBeing, EA_SPRITE_HAIR, hairStyle * -1, - ItemDB::get(-hairStyle).getDyeColorsString(hairColor)); - dstBeing->setHairColor(hairColor); - setSprite(dstBeing, EA_SPRITE_BOTTOMCLOTHES, headBottom); - setSprite(dstBeing, EA_SPRITE_TOPCLOTHES, headMid); - setSprite(dstBeing, EA_SPRITE_HAT, headTop); - setSprite(dstBeing, EA_SPRITE_SHOE, shoes); - setSprite(dstBeing, EA_SPRITE_GLOVES, gloves); - setSprite(dstBeing, EA_SPRITE_WEAPON, weapon, "", 1, true); - if (!mHideShield) - setSprite(dstBeing, EA_SPRITE_SHIELD, shield); - } - else if (dstBeing->getType() == ActorType::NPC) - { - switch (gender) - { - case 2: - dstBeing->setGender(Gender::FEMALE); - break; - case 3: - dstBeing->setGender(Gender::MALE); - break; - case 4: - dstBeing->setGender(Gender::OTHER); - break; - default: - dstBeing->setGender(Gender::UNSPECIFIED); - break; - } - } - - if (!visible) - { - uint16_t srcX, srcY, dstX, dstY; - msg.readCoordinatePair(srcX, srcY, dstX, dstY); - if (!disguiseId) - { - dstBeing->setAction(BeingAction::STAND, 0); - dstBeing->setTileCoords(srcX, srcY); - if (serverVersion < 10) - dstBeing->setDestination(dstX, dstY); - } - } - else - { - uint8_t dir; - uint16_t x, y; - msg.readCoordinates(x, y, dir); - dstBeing->setTileCoords(x, y); - - if (job == 45 && socialWindow && outfitWindow) - { - const int num = socialWindow->getPortalIndex(x, y); - if (num >= 0) - { - dstBeing->setName(keyboard.getKeyShortString( - outfitWindow->keyName(num))); - } - else - { - dstBeing->setName(""); - } - } - - dstBeing->setDirection(dir); - } - - msg.readUInt8(); // unknown - msg.readUInt8(); // unknown - msg.readInt16(); - - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, static_cast<uint16_t>( - (statusEffects >> 16) & 0xffff)); - dstBeing->setStatusEffectBlock(16, static_cast<uint16_t>( - statusEffects & 0xffff)); - BLOCK_END("BeingHandler::processBeingVisibleOrMove") -} - void BeingHandler::processBeingMove2(Net::MessageIn &msg) const { BLOCK_START("BeingHandler::processBeingMove2") diff --git a/src/net/ea/beinghandler.h b/src/net/ea/beinghandler.h index b460ae358..293ef92e1 100644 --- a/src/net/ea/beinghandler.h +++ b/src/net/ea/beinghandler.h @@ -46,9 +46,6 @@ class BeingHandler notfinal : public Net::BeingHandler const bool isWeapon = false, const bool isTempSprite = false) const; - virtual void processBeingVisibleOrMove(Net::MessageIn &msg, - const bool visible); - virtual void processBeingMove2(Net::MessageIn &msg) const; virtual void processBeingSpawn(Net::MessageIn &msg); diff --git a/src/net/eathena/beinghandler.cpp b/src/net/eathena/beinghandler.cpp index fe153a474..35c183569 100644 --- a/src/net/eathena/beinghandler.cpp +++ b/src/net/eathena/beinghandler.cpp @@ -109,7 +109,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { case SMSG_BEING_VISIBLE: // changed case SMSG_BEING_MOVE: - processBeingVisibleOrMove(msg, msg.getId() == SMSG_BEING_VISIBLE); + processBeingVisibleOrMove(msg); break; case SMSG_BEING_MOVE2: @@ -628,12 +628,13 @@ void BeingHandler::processPlayerMoveUpdate(Net::MessageIn &msg, dstBeing->setMoveTime(); } -void BeingHandler::processBeingVisibleOrMove(Net::MessageIn &msg, - const bool visible) +void BeingHandler::processBeingVisibleOrMove(Net::MessageIn &msg) { if (!actorManager) return; + const bool visible = msg.getId() == SMSG_BEING_VISIBLE; + if (visible) msg.readUInt8(); // padding? diff --git a/src/net/eathena/beinghandler.h b/src/net/eathena/beinghandler.h index 54271edff..fdbde2afa 100644 --- a/src/net/eathena/beinghandler.h +++ b/src/net/eathena/beinghandler.h @@ -43,10 +43,9 @@ class BeingHandler final : public MessageHandler, public Ea::BeingHandler void undress(Being *const being) const override final; - void processBeingVisibleOrMove(Net::MessageIn &msg, - const bool visible) override final; - protected: + void processBeingVisibleOrMove(Net::MessageIn &msg); + void processBeingChangeLook(Net::MessageIn &msg, const bool look2) const; diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 2ea77d925..a9c98d295 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -30,6 +30,12 @@ #include "being/localplayer.h" +#include "input/keyboardconfig.h" + +#include "gui/windows/killstats.h" +#include "gui/windows/outfitwindow.h" +#include "gui/windows/socialwindow.h" + #include "net/tmwa/messageout.h" #include "net/tmwa/protocol.h" #include "net/tmwa/sprite.h" @@ -46,6 +52,7 @@ extern Net::BeingHandler *beingHandler; extern int serverVersion; +extern unsigned int tmwServerVersion; namespace TmwAthena { @@ -106,7 +113,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { case SMSG_BEING_VISIBLE: case SMSG_BEING_MOVE: - processBeingVisibleOrMove(msg, msg.getId() == SMSG_BEING_VISIBLE); + processBeingVisibleOrMove(msg); break; case SMSG_BEING_MOVE2: @@ -727,4 +734,244 @@ void BeingHandler::processBeingMove3(Net::MessageIn &msg) BLOCK_END("BeingHandler::processBeingMove3") } +void BeingHandler::processBeingVisibleOrMove(Net::MessageIn &msg) +{ + BLOCK_START("BeingHandler::processBeingVisibleOrMove") + if (!actorManager) + { + BLOCK_END("BeingHandler::processBeingVisibleOrMove") + return; + } + + const bool visible = msg.getId() == SMSG_BEING_VISIBLE; + int spawnId; + + // Information about a being in range + const int id = msg.readInt32(); + if (id == mSpawnId) + spawnId = mSpawnId; + else + spawnId = 0; + mSpawnId = 0; + int16_t speed = msg.readInt16(); + const uint16_t stunMode = msg.readInt16(); // opt1 + uint32_t statusEffects = msg.readInt16(); // opt2 + statusEffects |= (static_cast<uint32_t>(msg.readInt16())) << 16; // option + const int16_t job = msg.readInt16(); // class + int disguiseId = 0; + if (id == localPlayer->getId() && job >= 1000) + disguiseId = job; + + Being *dstBeing = actorManager->findBeing(id); + + if (dstBeing && dstBeing->getType() == ActorType::MONSTER + && !dstBeing->isAlive()) + { + actorManager->destroy(dstBeing); + actorManager->erase(dstBeing); + dstBeing = nullptr; + } + + if (!dstBeing) + { + // Being with id >= 110000000 and job 0 are better + // known as ghosts, so don't create those. + if (job == 0 && id >= 110000000) + { + BLOCK_END("BeingHandler::processBeingVisibleOrMove") + return; + } + + if (actorManager->isBlocked(id) == true) + { + BLOCK_END("BeingHandler::processBeingVisibleOrMove") + return; + } + + dstBeing = createBeing(id, job); + + if (!dstBeing) + { + BLOCK_END("BeingHandler::processBeingVisibleOrMove") + return; + } + + if (job == 1022 && killStats) + killStats->jackoAlive(dstBeing->getId()); + } + else + { + if (dstBeing->getType() == ActorType::NPC) + { + actorManager->undelete(dstBeing); + if (serverVersion < 1) + requestNameById(id); + } + } + + if (dstBeing->getType() == ActorType::PLAYER) + dstBeing->setMoveTime(); + + if (spawnId) + { + dstBeing->setAction(BeingAction::SPAWN, 0); + } + else if (visible) + { + dstBeing->clearPath(); + dstBeing->setActionTime(tick_time); + dstBeing->setAction(BeingAction::STAND, 0); + } + + // Prevent division by 0 when calculating frame + if (speed == 0) + speed = 150; + + const uint8_t hairStyle = msg.readUInt8(); + const uint8_t look = msg.readUInt8(); + dstBeing->setSubtype(job, look); + if (dstBeing->getType() == ActorType::MONSTER && localPlayer) + localPlayer->checkNewName(dstBeing); + dstBeing->setWalkSpeed(Vector(speed, speed, 0)); + const uint16_t weapon = msg.readInt16(); + const uint16_t headBottom = msg.readInt16(); + + if (!visible) + msg.readInt32(); // server tick + + const uint16_t shield = msg.readInt16(); + const uint16_t headTop = msg.readInt16(); + const uint16_t headMid = msg.readInt16(); + const uint8_t hairColor = msg.readUInt8(); + msg.readUInt8(); // free + const uint16_t shoes = msg.readInt16(); // clothes color + + uint16_t gloves; + if (dstBeing->getType() == ActorType::MONSTER) + { + if (serverVersion > 0 || tmwServerVersion >= 0x0E0701) + { + const int hp = msg.readInt32(); + const int maxHP = msg.readInt32(); + if (hp && maxHP) + { + dstBeing->setMaxHP(maxHP); + const int oldHP = dstBeing->getHP(); + if (!oldHP || oldHP > hp) + dstBeing->setHP(hp); + } + } + else + { + msg.readInt32(); + msg.readInt32(); + } + gloves = 0; + } + else + { + gloves = msg.readInt16(); // head dir - "abused" as gloves + msg.readInt32(); // guild + msg.readInt16(); // guild emblem + } +// logger->log("being guild: " + toString(guild)); + + msg.readInt16(); // manner + dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 + if (serverVersion > 0 && dstBeing->getType() == ActorType::MONSTER) + { + const int attackRange = static_cast<int>(msg.readUInt8()); // karma + dstBeing->setAttackRange(attackRange); + } + else + { + msg.readUInt8(); // karma + } + uint8_t gender = msg.readUInt8(); + + if (!disguiseId && dstBeing->getType() == ActorType::PLAYER) + { + // reserving bits for future usage + gender &= 3; + dstBeing->setGender(Being::intToGender(gender)); + // Set these after the gender, as the sprites may be gender-specific + setSprite(dstBeing, SPRITE_HAIR, hairStyle * -1, + ItemDB::get(-hairStyle).getDyeColorsString(hairColor)); + dstBeing->setHairColor(hairColor); + setSprite(dstBeing, SPRITE_BOTTOMCLOTHES, headBottom); + setSprite(dstBeing, SPRITE_TOPCLOTHES, headMid); + setSprite(dstBeing, SPRITE_HAT, headTop); + setSprite(dstBeing, SPRITE_SHOE, shoes); + setSprite(dstBeing, SPRITE_GLOVES, gloves); + setSprite(dstBeing, SPRITE_WEAPON, weapon, "", 1, true); + if (!mHideShield) + setSprite(dstBeing, SPRITE_SHIELD, shield); + } + else if (dstBeing->getType() == ActorType::NPC) + { + switch (gender) + { + case 2: + dstBeing->setGender(Gender::FEMALE); + break; + case 3: + dstBeing->setGender(Gender::MALE); + break; + case 4: + dstBeing->setGender(Gender::OTHER); + break; + default: + dstBeing->setGender(Gender::UNSPECIFIED); + break; + } + } + + if (!visible) + { + uint16_t srcX, srcY, dstX, dstY; + msg.readCoordinatePair(srcX, srcY, dstX, dstY); + if (!disguiseId) + { + dstBeing->setAction(BeingAction::STAND, 0); + dstBeing->setTileCoords(srcX, srcY); + if (serverVersion < 10) + dstBeing->setDestination(dstX, dstY); + } + } + else + { + uint8_t dir; + uint16_t x, y; + msg.readCoordinates(x, y, dir); + dstBeing->setTileCoords(x, y); + + if (job == 45 && socialWindow && outfitWindow) + { + const int num = socialWindow->getPortalIndex(x, y); + if (num >= 0) + { + dstBeing->setName(keyboard.getKeyShortString( + outfitWindow->keyName(num))); + } + else + { + dstBeing->setName(""); + } + } + + dstBeing->setDirection(dir); + } + + msg.readUInt8(); // unknown + msg.readUInt8(); // unknown + msg.readInt16(); + + dstBeing->setStunMode(stunMode); + dstBeing->setStatusEffectBlock(0, static_cast<uint16_t>( + (statusEffects >> 16) & 0xffff)); + dstBeing->setStatusEffectBlock(16, static_cast<uint16_t>( + statusEffects & 0xffff)); + BLOCK_END("BeingHandler::processBeingVisibleOrMove") +} + } // namespace TmwAthena diff --git a/src/net/tmwa/beinghandler.h b/src/net/tmwa/beinghandler.h index f3b57b023..870ea4a1a 100644 --- a/src/net/tmwa/beinghandler.h +++ b/src/net/tmwa/beinghandler.h @@ -47,6 +47,8 @@ class BeingHandler final : public MessageHandler, public Ea::BeingHandler void processBeingChangeLook(Net::MessageIn &msg, const bool look2) const; + void processBeingVisibleOrMove(Net::MessageIn &msg); + static void processNameResponse2(Net::MessageIn &msg); void processPlayerMoveUpdate(Net::MessageIn &msg, |