diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-05-19 23:41:05 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-05-20 20:50:00 +0300 |
commit | 78ab801cc5dfe687718ec7e027c3050bed62a1e9 (patch) | |
tree | 064fc82cf6aed1dbcd0a5650b146e74cf23a20a0 /src/net/tmwa/beinghandler.cpp | |
parent | 2a2155ae3c601fe1f813f9214b1421e4ac634148 (diff) | |
download | manaverse-78ab801cc5dfe687718ec7e027c3050bed62a1e9.tar.gz manaverse-78ab801cc5dfe687718ec7e027c3050bed62a1e9.tar.bz2 manaverse-78ab801cc5dfe687718ec7e027c3050bed62a1e9.tar.xz manaverse-78ab801cc5dfe687718ec7e027c3050bed62a1e9.zip |
Start separating netcode to functions and moving some code to ea name space
for future usage for different server types.
Processed classes: adminhandler, beinghandler, buysellhandler.
Diffstat (limited to 'src/net/tmwa/beinghandler.cpp')
-rw-r--r-- | src/net/tmwa/beinghandler.cpp | 1424 |
1 files changed, 427 insertions, 997 deletions
diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 582f755f1..ff458b31b 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -56,13 +56,8 @@ extern Net::BeingHandler *beingHandler; namespace TmwAthena { -const int EMOTION_TIME = 500; /**< Duration of emotion icon */ - -Being *createBeing(int id, short job); - BeingHandler::BeingHandler(bool enableSync): - mSync(enableSync), - mSpawnId(0) + Ea::BeingHandler(enableSync) { static const Uint16 _messages[] = { @@ -102,46 +97,6 @@ BeingHandler::BeingHandler(bool enableSync): beingHandler = this; } -Being *createBeing(int id, short job) -{ - if (!actorSpriteManager) - return 0; - - ActorSprite::Type type = ActorSprite::UNKNOWN; - if (job <= 25 || (job >= 4001 && job <= 4049)) - type = ActorSprite::PLAYER; - else if (job >= 46 && job <= 1000) - type = ActorSprite::NPC; - else if (job > 1000 && job <= 2000) - type = ActorSprite::MONSTER; - else if (job == 45) - type = ActorSprite::PORTAL; - - Being *being = actorSpriteManager->createBeing(id, type, job); - - if (type == ActorSprite::PLAYER || type == ActorSprite::NPC) - { - if (!being->updateFromCache()) - { - MessageOut outMsg(0x0094); - outMsg.writeInt32(id); //readLong(2)); - } - else - { - if (player_node) - player_node->checkNewName(being); - } - } - if (type == Being::PLAYER) - { - if (botCheckerWindow) - botCheckerWindow->updateList(); - if (socialWindow) - socialWindow->updateActiveList(); - } - return being; -} - void BeingHandler::requestNameById(int id) { MessageOut outMsg(0x0094); @@ -150,1071 +105,546 @@ void BeingHandler::requestNameById(int id) void BeingHandler::handleMessage(Net::MessageIn &msg) { - if (!actorSpriteManager) - return; - - int id; - short job, speed, gender; - Uint16 headTop, headMid, headBottom; - Uint16 shoes, gloves; - Uint16 weapon, shield; - Uint16 gmstatus; - int param1; - Uint16 stunMode; - int level; - Uint32 statusEffects; - int type, guild; - Uint16 status; - Being *srcBeing, *dstBeing; - int hairStyle, hairColor, flag; - int hp, maxHP, oldHP; - unsigned char colors[9]; - Uint8 dir; - int spawnId; - switch (msg.getId()) { case SMSG_BEING_VISIBLE: case SMSG_BEING_MOVE: - // Information about a being in range - id = msg.readInt32(); - if (id == mSpawnId) - spawnId = mSpawnId; - else - spawnId = 0; - mSpawnId = 0; - speed = msg.readInt16(); - stunMode = msg.readInt16(); // opt1 - statusEffects = msg.readInt16(); // opt2 - statusEffects |= (static_cast<Uint32>( - msg.readInt16())) << 16; // option - job = msg.readInt16(); // class - - dstBeing = actorSpriteManager->findBeing(id); - - if (dstBeing && dstBeing->getType() == Being::MONSTER - && !dstBeing->isAlive()) - { - actorSpriteManager->destroy(dstBeing); - actorSpriteManager->erase(dstBeing); - dstBeing = 0; - } - - if (!dstBeing) - { - // Being with id >= 110000000 and job 0 are better - // known as ghosts, so don't create those. - if (job == 0 && id >= 110000000) - break; - - if (actorSpriteManager->isBlocked(id) == true) - break; - - dstBeing = createBeing(id, job); - - if (!dstBeing) - break; - - - if (job == 1022 && killStats) - killStats->jackoAlive(dstBeing->getId()); - } - else - { - // undeleting marked for deletion being - if (dstBeing->getType() == Being::NPC) - { - actorSpriteManager->undelete(dstBeing); - } - } - - if (dstBeing->getType() == Being::PLAYER) - dstBeing->setMoveTime(); - - if (spawnId) - { - dstBeing->setAction(Being::SPAWN); - } - else if (msg.getId() == SMSG_BEING_VISIBLE) - { - dstBeing->clearPath(); - dstBeing->setActionTime(tick_time); - dstBeing->setAction(Being::STAND); - } - - // Prevent division by 0 when calculating frame - if (speed == 0) - speed = 150; - - dstBeing->setWalkSpeed(Vector(speed, speed, 0)); - dstBeing->setSubtype(job); - if (dstBeing->getType() == ActorSprite::MONSTER && player_node) - player_node->checkNewName(dstBeing); - - hairStyle = msg.readInt16(); - weapon = msg.readInt16(); - headBottom = msg.readInt16(); - - if (msg.getId() == SMSG_BEING_MOVE) - msg.readInt32(); // server tick - - shield = msg.readInt16(); - headTop = msg.readInt16(); - headMid = msg.readInt16(); - hairColor = msg.readInt16(); - shoes = msg.readInt16(); // clothes color - "abused" as shoes - - if (dstBeing->getType() == ActorSprite::MONSTER) - { - hp = msg.readInt32(); - maxHP = msg.readInt32(); - if (hp && maxHP) - { - oldHP = dstBeing->getHP(); - if (!oldHP || oldHP > hp) - dstBeing->setHP(hp); - dstBeing->setMaxHP(maxHP); - } - gloves = 0; - guild = 0; - } - else - { - gloves = msg.readInt16(); // head dir - "abused" as gloves - guild = msg.readInt32(); // guild - msg.readInt16(); // guild emblem - } -// logger->log("being guild: " + toString(guild)); -/* - if (guild == 0) - dstBeing->clearGuilds(); - else - dstBeing->setGuild(Guild::getGuild(static_cast<short>(guild))); -*/ - - msg.readInt16(); // manner - dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 - msg.readInt8(); // karma - gender = msg.readInt8(); - - if (dstBeing->getType() == ActorSprite::PLAYER) - { - dstBeing->setGender((gender == 0) - ? GENDER_FEMALE : GENDER_MALE); - // Set these after the gender, as the sprites may be gender-specific - dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, - ColorDB::getHairColor(hairColor)); - dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); - dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); - dstBeing->setSprite(SPRITE_HAT, headTop); - dstBeing->setSprite(SPRITE_SHOE, shoes); - dstBeing->setSprite(SPRITE_GLOVES, gloves); - dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true); - if (!config.getBoolValue("hideShield")) - dstBeing->setSprite(SPRITE_SHIELD, shield); - } - else if (dstBeing->getType() == ActorSprite::NPC) - { - switch (gender) - { - case 2: - dstBeing->setGender(GENDER_FEMALE); - break; - case 3: - dstBeing->setGender(GENDER_MALE); - break; - default: - dstBeing->setGender(GENDER_UNSPECIFIED); - break; - } - } - - if (msg.getId() == SMSG_BEING_MOVE) - { - Uint16 srcX, srcY, dstX, dstY; - msg.readCoordinatePair(srcX, srcY, dstX, dstY); - dstBeing->setAction(Being::STAND); - dstBeing->setTileCoords(srcX, srcY); - dstBeing->setDestination(dstX, dstY); - -// if (player_node && player_node->getTarget() == dstBeing) -// player_node->targetMoved(); - } - else - { - Uint8 dir; - Uint16 x, y; - msg.readCoordinates(x, y, dir); - dstBeing->setTileCoords(x, y); - - if (job == 45 && socialWindow && outfitWindow) - { - int num = socialWindow->getPortalIndex(x, y); - if (num >= 0) - { - dstBeing->setName(keyboard.getKeyShortString( - outfitWindow->keyName(num))); - } - else - { - dstBeing->setName(""); - } - } - - dstBeing->setDirection(dir); - } - - msg.readInt8(); // unknown - msg.readInt8(); // unknown -// msg.readInt8(); // unknown / sit - msg.readInt16(); - - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, static_cast<Uint16>( - (statusEffects >> 16) & 0xffff)); - dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); + processBeingVisibleOrMove(msg, msg.getId() == SMSG_BEING_VISIBLE); break; case SMSG_BEING_MOVE2: - /* - * A simplified movement packet, used by the - * later versions of eAthena for both mobs and - * players - */ - dstBeing = actorSpriteManager->findBeing(msg.readInt32()); - - /* - * 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) - break; - - Uint16 srcX, srcY, dstX, dstY; - msg.readCoordinatePair(srcX, srcY, dstX, dstY); - msg.readInt32(); // Server tick - - dstBeing->setAction(Being::STAND); - dstBeing->setTileCoords(srcX, srcY); - dstBeing->setDestination(dstX, dstY); - if (dstBeing->getType() == Being::PLAYER) - dstBeing->setMoveTime(); - -// if (player_node && player_node->getTarget() == dstBeing) -// { -// logger->log("SMSG_BEING_MOVE2"); -// player_node->targetMoved(); -// } - + processBeingMove2(msg); break; case SMSG_BEING_SPAWN: - // skipping this packet - mSpawnId = msg.readInt32(); // id - msg.readInt16(); // speed - msg.readInt16(); // opt1 - msg.readInt16(); // opt2 - msg.readInt16(); // option - msg.readInt16(); // disguise + processBeingSpawn(msg); break; case SMSG_BEING_REMOVE: - // A being should be removed or has died - - id = msg.readInt32(); - dstBeing = actorSpriteManager->findBeing(id); - if (!dstBeing) - break; - - player_node->followMoveTo(dstBeing, player_node->getNextDestX(), - player_node->getNextDestY()); - - // If this is player's current target, clear it. - if (dstBeing == player_node->getTarget()) - player_node->stopAttack(); - - if (msg.readInt8() == 1) - { - dstBeing->setAction(Being::DEAD); - if (dstBeing->getName() == "Jack O" && killStats) - killStats->jackoDead(id); - } - else - { - if (dstBeing->getType() == Being::PLAYER) - { - if (botCheckerWindow) - botCheckerWindow->updateList(); - if (socialWindow) - socialWindow->updateActiveList(); - } - actorSpriteManager->destroy(dstBeing); - } + processBeingRemove(msg); break; case SMSG_BEING_RESURRECT: - // A being changed mortality status - - id = msg.readInt32(); - dstBeing = actorSpriteManager->findBeing(id); - if (!dstBeing) - break; - - // If this is player's current target, clear it. - if (dstBeing == player_node->getTarget()) - player_node->stopAttack(); - - if (msg.readInt8() == 1) - dstBeing->setAction(Being::STAND); - + processBeingResurrect(msg); break; case SMSG_SKILL_DAMAGE: { - msg.readInt16(); // Skill Id - srcBeing = actorSpriteManager->findBeing(msg.readInt32()); - dstBeing = actorSpriteManager->findBeing(msg.readInt32()); - msg.readInt32(); // Server tick - msg.readInt32(); // src speed - msg.readInt32(); // dst speed - param1 = msg.readInt32(); // Damage - msg.readInt16(); // Skill level - msg.readInt16(); // Div - msg.readInt8(); // Skill hit/type (?) - if (dstBeing) - { - // Perhaps a new skill attack type should be created and used? -// if (dstSpeed) -// dstBeing->setAttackDelay(dstSpeed); - dstBeing->takeDamage(srcBeing, param1, Being::HIT); - } - if (srcBeing) - { -// if (srcSpeed) -// srcBeing->setAttackDelay(srcSpeed); - srcBeing->handleAttack(dstBeing, param1, Being::HIT); - } + processSkillDamage(msg); break; } case SMSG_BEING_ACTION: { - srcBeing = actorSpriteManager->findBeing(msg.readInt32()); - dstBeing = actorSpriteManager->findBeing(msg.readInt32()); - - msg.readInt32(); // server tick - int srcSpeed = 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 Being::HIT: // Damage - case Being::CRITICAL: // Critical Damage - case Being::MULTI: // Critical Damage - case Being::REFLECT: // Reflected Damage - case Being::FLEE: // Lucky Dodge - if (dstBeing) - { -// if (dstSpeed) -// dstBeing->setAttackDelay(dstSpeed); - dstBeing->takeDamage(srcBeing, param1, - static_cast<Being::AttackType>(type)); - } - if (srcBeing) - { - if (srcSpeed && srcBeing->getType() == Being::PLAYER) - srcBeing->setAttackDelay(srcSpeed); - srcBeing->handleAttack(dstBeing, param1, - static_cast<Being::AttackType>(type)); - if (srcBeing->getType() == Being::PLAYER) - srcBeing->setAttackTime(); - } - break; - - case 0x02: // Sit - if (srcBeing) - { - srcBeing->setAction(Being::SIT); - if (srcBeing->getType() == Being::PLAYER) - { - srcBeing->setMoveTime(); - if (player_node) - { - player_node->imitateAction( - srcBeing, Being::SIT); - } - } - } - break; - - case 0x03: // Stand up - if (srcBeing) - { - srcBeing->setAction(Being::STAND); - if (srcBeing->getType() == Being::PLAYER) - { - srcBeing->setMoveTime(); - if (player_node) - { - player_node->imitateAction( - srcBeing, Being::STAND); - } - } - } - break; - default: - break; -/* - logger->log("QQQ1 SMSG_BEING_ACTION:"); - if (srcBeing) - logger->log("srcBeing:" + toString(srcBeing->getId())); - if (dstBeing) - logger->log("dstBeing:" + toString(dstBeing->getId())); - logger->log("type: " + toString(type)); -*/ - } + processBeingAction(msg); break; } case SMSG_BEING_SELFEFFECT: { - if (!effectManager) - return; - - id = static_cast<Uint32>(msg.readInt32()); - Being* being = actorSpriteManager->findBeing(id); - if (!being) - break; - - int effectType = msg.readInt32(); - - effectManager->trigger(effectType, being); - - if (being && effectType == 3 - && being->getType() == Being::PLAYER - && socialWindow) - { //reset received damage - socialWindow->resetDamage(being->getName()); - } - + processBeingSelfEffect(msg); break; } case SMSG_BEING_EMOTION: - if (!player_node) - break; - - if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) - break; - - if (player_relations.hasPermission(dstBeing, - PlayerRelation::EMOTE)) - { - unsigned char emote = msg.readInt8(); - if (emote) - { - dstBeing->setEmote(emote, EMOTION_TIME); - player_node->imitateEmote(dstBeing, emote); - } - } - if (dstBeing->getType() == Being::PLAYER) - dstBeing->setOtherTime(); - + processBeingEmotion(msg); break; case SMSG_BEING_CHANGE_LOOKS: case SMSG_BEING_CHANGE_LOOKS2: - { - /* - * 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. - * - * If type = 2, then the first 16 bit value is the weapon ID, - * and the second 16 bit value is the shield ID. If no - * shield is equipped, or type is not 2, then the second - * 16 bit value will be 0. - */ - - if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) - break; - - int type = msg.readInt8(); - int id = 0; - int id2 = 0; - std::string color; - - if (msg.getId() == SMSG_BEING_CHANGE_LOOKS) - { - id = msg.readInt8(); - id2 = 1; // default color - } - else - { // SMSG_BEING_CHANGE_LOOKS2 - id = msg.readInt16(); - if (type == 2 || serverVersion > 0) - id2 = msg.readInt16(); - else - id2 = 1; - color = ""; - } - - if (dstBeing->getType() == Being::PLAYER) - dstBeing->setOtherTime(); - - if (!player_node) - break; - - switch (type) - { - case 0: // change race - dstBeing->setSubtype(static_cast<Uint16>(id)); - break; - case 1: // eAthena LOOK_HAIR - dstBeing->setSpriteID(SPRITE_HAIR, id *-1); - break; - case 2: // Weapon ID in id, Shield ID in id2 - dstBeing->setSprite(SPRITE_WEAPON, id, "", 1, true); - if (!config.getBoolValue("hideShield")) - dstBeing->setSprite(SPRITE_SHIELD, id2); - player_node->imitateOutfit(dstBeing, SPRITE_SHIELD); - break; - case 3: // Change lower headgear for eAthena, pants for us - dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_BOTTOMCLOTHES); - break; - case 4: // Change upper headgear for eAthena, hat for us - dstBeing->setSprite(SPRITE_HAT, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_HAT); - break; - case 5: // Change middle headgear for eathena, armor for us - dstBeing->setSprite(SPRITE_TOPCLOTHES, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_TOPCLOTHES); - break; - case 6: // eAthena LOOK_HAIR_COLOR - dstBeing->setSpriteColor(SPRITE_HAIR, - ColorDB::getHairColor(id)); - break; - case 8: // eAthena LOOK_SHIELD - if (!config.getBoolValue("hideShield")) - { - dstBeing->setSprite(SPRITE_SHIELD, id, color, - static_cast<unsigned char>(id2)); - } - player_node->imitateOutfit(dstBeing, SPRITE_SHIELD); - break; - case 9: // eAthena LOOK_SHOES - dstBeing->setSprite(SPRITE_SHOE, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_SHOE); - break; - case 10: // LOOK_GLOVES - dstBeing->setSprite(SPRITE_GLOVES, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_GLOVES); - break; - case 11: // LOOK_CAPE - dstBeing->setSprite(SPRITE_CAPE, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_CAPE); - break; - case 12: - dstBeing->setSprite(SPRITE_MISC1, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_MISC1); - break; - case 13: - dstBeing->setSprite(SPRITE_MISC2, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_MISC2); - break; - case 14: - dstBeing->setSprite(SPRITE_EVOL1, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_EVOL1); - break; - case 15: - dstBeing->setSprite(SPRITE_EVOL2, id, color, - static_cast<unsigned char>(id2)); - player_node->imitateOutfit(dstBeing, SPRITE_EVOL2); - break; - default: - logger->log("QQQ3 CHANGE_LOOKS: unsupported type: " - "%d, id: %d", type, id); - if (dstBeing) - { - logger->log("ID: " + toString(dstBeing->getId())); - logger->log("name: " + toString(dstBeing->getName())); - } - break; - } - } + processBeingChangeLook(msg, + msg.getId() == SMSG_BEING_CHANGE_LOOKS2); break; case SMSG_BEING_NAME_RESPONSE: - { - int beingId = msg.readInt32(); - if ((dstBeing = actorSpriteManager->findBeing(beingId))) - { - if (beingId == player_node->getId()) - { - player_node->pingResponse(); - } - else - { - dstBeing->setName(msg.readString(24)); - dstBeing->updateGuild(); - dstBeing->addToCache(); - - if (dstBeing->getType() == Being::PLAYER) - dstBeing->updateColors(); - - if (player_node) - { - Party *party = player_node->getParty(); - if (party && party->isMember(dstBeing->getId())) - { - PartyMember *member = party->getMember( - dstBeing->getId()); - - if (member) - member->setName(dstBeing->getName()); - } - player_node->checkNewName(dstBeing); - } - } - } - } + processNameResponse(msg); break; + case SMSG_BEING_NAME_RESPONSE2: - { - int len = msg.readInt16(); - int beingId = msg.readInt32(); - std::string str = msg.readString(len - 8); - if ((dstBeing = actorSpriteManager->findBeing(beingId))) - { - if (beingId == player_node->getId()) - { - player_node->pingResponse(); - } - else - { - dstBeing->setName(str); - dstBeing->updateGuild(); - dstBeing->addToCache(); - - if (dstBeing->getType() == Being::PLAYER) - dstBeing->updateColors(); - - if (player_node) - { - Party *party = player_node->getParty(); - if (party && party->isMember(dstBeing->getId())) - { - PartyMember *member = party->getMember( - dstBeing->getId()); - - if (member) - member->setName(dstBeing->getName()); - } - player_node->checkNewName(dstBeing); - } - } - } - } + processNameResponse2(msg); break; + case SMSG_BEING_IP_RESPONSE: - { - if ((dstBeing = actorSpriteManager->findBeing( - msg.readInt32()))) - { - dstBeing->setIp(ipToString(msg.readInt32())); - } - } + processIpResponse(msg); break; + case SMSG_SOLVE_CHAR_NAME: - { - logger->log1("SMSG_SOLVE_CHAR_NAME"); - logger->log(toString(msg.readInt32())); - logger->log(msg.readString(24)); - } break; + case SMSG_PLAYER_GUILD_PARTY_INFO: - if ((dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) - { - dstBeing->setPartyName(msg.readString(24)); - dstBeing->setGuildName(msg.readString(24)); - dstBeing->setGuildPos(msg.readString(24)); - dstBeing->addToCache(); - msg.readString(24); // Discard this - } + processPlayerGuilPartyInfo(msg); break; - case SMSG_BEING_CHANGE_DIRECTION: - { - if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) - break; - - msg.readInt16(); // unused - unsigned char dir = msg.readInt8(); - dstBeing->setDirection(dir); - if (player_node) - player_node->imitateDirection(dstBeing, dir); + case SMSG_BEING_CHANGE_DIRECTION: + processBeingChangeDirection(msg); break; - } + case SMSG_PLAYER_UPDATE_1: case SMSG_PLAYER_UPDATE_2: case SMSG_PLAYER_MOVE: - if (!actorSpriteManager || !player_node) - break; + int type; + switch (msg.getId()) + { + case SMSG_PLAYER_UPDATE_1: + type = 1; + break; + case SMSG_PLAYER_UPDATE_2: + type = 2; + break; + case SMSG_PLAYER_MOVE: + type = 3; + break; + default: + return; + } + processPlayerMoveUpdate(msg, type); - // An update about a player, potentially including movement. - id = msg.readInt32(); - speed = msg.readInt16(); - stunMode = msg.readInt16(); // opt1; Aethyra use this as cape - statusEffects = msg.readInt16(); // opt2; Aethyra use this as misc1 - statusEffects |= (static_cast<Uint32>(msg.readInt16())) - << 16; // status.options; Aethyra uses this as misc2 - job = msg.readInt16(); + break; + case SMSG_PLAYER_STOP: + processPlayerStop(msg); + break; - dstBeing = actorSpriteManager->findBeing(id); + case SMSG_PLAYER_MOVE_TO_ATTACK: + processPlayerMoveToAttack(msg); + break; - if (!dstBeing) - { - if (actorSpriteManager->isBlocked(id) == true) - break; + case SMSG_PLAYER_STATUS_CHANGE: + processPlaterStatusChange(msg); + break; - dstBeing = createBeing(id, job); + case SMSG_BEING_STATUS_CHANGE: + processBeingStatusChange(msg); + break; - if (!dstBeing) - break; - } + case SMSG_SKILL_CASTING: + processSkilCasting(msg); + break; - dir = dstBeing->getDirectionDelayed(); - if (dir) - { - if (dir != dstBeing->getDirection()) - dstBeing->setDirection(dir); - } + case SMSG_SKILL_CAST_CANCEL: + msg.readInt32(); // id + break; - if (Party *party = player_node->getParty()) - { - if (party->isMember(id)) - dstBeing->setParty(party); - } + case SMSG_SKILL_NO_DAMAGE: + processSkillNoDamage(msg); + break; - dstBeing->setWalkSpeed(Vector(speed, speed, 0)); - dstBeing->setSubtype(job); - hairStyle = msg.readInt16(); - weapon = msg.readInt16(); - shield = msg.readInt16(); - headBottom = msg.readInt16(); + case SMSG_PVP_MAP_MODE: + processPvpMapMode(msg); + break; - if (msg.getId() == SMSG_PLAYER_MOVE) - msg.readInt32(); // server tick + case SMSG_PVP_SET: + processPvpSet(msg); + break; + + default: + break; + } +} + +void BeingHandler::undress(Being *being) +{ + being->setSprite(SPRITE_BOTTOMCLOTHES, 0); + being->setSprite(SPRITE_TOPCLOTHES, 0); + being->setSprite(SPRITE_HAT, 0); + being->setSprite(SPRITE_SHOE, 0); + being->setSprite(SPRITE_GLOVES, 0); +// being->setSprite(SPRITE_WEAPON, 0, "", true); +} - headTop = msg.readInt16(); - headMid = msg.readInt16(); - hairColor = msg.readInt16(); +void BeingHandler::processBeingChangeLook(Net::MessageIn &msg, bool look2) +{ + if (!actorSpriteManager) + return; - colors[0] = msg.readInt8(); - colors[1] = msg.readInt8(); - colors[2] = msg.readInt8(); + Being *dstBeing; + /* + * 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. + * + * If type = 2, then the first 16 bit value is the weapon ID, + * and the second 16 bit value is the shield ID. If no + * shield is equipped, or type is not 2, then the second + * 16 bit value will be 0. + */ + + if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) + return; - msg.readInt8(); //unused -// shoes = msg.readInt16(); -// gloves = msg.readInt16(); //sd->head_dir + int type = msg.readInt8(); + int id = 0; + int id2 = 0; + std::string color; - guild = msg.readInt32(); // guild + if (!look2) + { + id = msg.readInt8(); + id2 = 1; // default color + } + else + { // SMSG_BEING_CHANGE_LOOKS2 + id = msg.readInt16(); + if (type == 2 || serverVersion > 0) + id2 = msg.readInt16(); + else + id2 = 1; + color = ""; + } - if (guild == 0) - dstBeing->clearGuilds(); - else - dstBeing->setGuild(Guild::getGuild(static_cast<short>(guild))); + if (dstBeing->getType() == Being::PLAYER) + dstBeing->setOtherTime(); - msg.readInt16(); // emblem - msg.readInt16(); // manner - dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 - msg.readInt8(); // karma - dstBeing->setGender((msg.readInt8() == 0) - ? GENDER_FEMALE : GENDER_MALE); + if (!player_node) + return; - // Set these after the gender, as the sprites may be gender-specific - dstBeing->setSprite(SPRITE_WEAPON, weapon, "", 1, true); + switch (type) + { + case 0: // change race + dstBeing->setSubtype(static_cast<Uint16>(id)); + break; + case 1: // eAthena LOOK_HAIR + dstBeing->setSpriteID(SPRITE_HAIR, id *-1); + break; + case 2: // Weapon ID in id, Shield ID in id2 + dstBeing->setSprite(SPRITE_WEAPON, id, "", 1, true); + if (!config.getBoolValue("hideShield")) + dstBeing->setSprite(SPRITE_SHIELD, id2); + player_node->imitateOutfit(dstBeing, SPRITE_SHIELD); + break; + case 3: // Change lower headgear for eAthena, pants for us + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_BOTTOMCLOTHES); + break; + case 4: // Change upper headgear for eAthena, hat for us + dstBeing->setSprite(SPRITE_HAT, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_HAT); + break; + case 5: // Change middle headgear for eathena, armor for us + dstBeing->setSprite(SPRITE_TOPCLOTHES, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_TOPCLOTHES); + break; + case 6: // eAthena LOOK_HAIR_COLOR + dstBeing->setSpriteColor(SPRITE_HAIR, + ColorDB::getHairColor(id)); + break; + case 8: // eAthena LOOK_SHIELD if (!config.getBoolValue("hideShield")) - dstBeing->setSprite(SPRITE_SHIELD, shield); - //dstBeing->setSprite(SPRITE_SHOE, shoes); - if (serverVersion > 0) { - dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom, - "", colors[0]); - dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid, "", colors[2]); - dstBeing->setSprite(SPRITE_HAT, headTop, "", colors[1]); + dstBeing->setSprite(SPRITE_SHIELD, id, color, + static_cast<unsigned char>(id2)); } - else + player_node->imitateOutfit(dstBeing, SPRITE_SHIELD); + break; + case 9: // eAthena LOOK_SHOES + dstBeing->setSprite(SPRITE_SHOE, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_SHOE); + break; + case 10: // LOOK_GLOVES + dstBeing->setSprite(SPRITE_GLOVES, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_GLOVES); + break; + case 11: // LOOK_CAPE + dstBeing->setSprite(SPRITE_CAPE, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_CAPE); + break; + case 12: + dstBeing->setSprite(SPRITE_MISC1, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_MISC1); + break; + case 13: + dstBeing->setSprite(SPRITE_MISC2, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_MISC2); + break; + case 14: + dstBeing->setSprite(SPRITE_EVOL1, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_EVOL1); + break; + case 15: + dstBeing->setSprite(SPRITE_EVOL2, id, color, + static_cast<unsigned char>(id2)); + player_node->imitateOutfit(dstBeing, SPRITE_EVOL2); + break; + default: + logger->log("QQQ3 CHANGE_LOOKS: unsupported type: " + "%d, id: %d", type, id); + if (dstBeing) { - dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); - dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); - dstBeing->setSprite(SPRITE_HAT, headTop); + logger->log("ID: " + toString(dstBeing->getId())); + logger->log("name: " + toString(dstBeing->getName())); } - //dstBeing->setSprite(SPRITE_GLOVES, gloves); - //dstBeing->setSprite(SPRITE_CAPE, cape); - //dstBeing->setSprite(SPRITE_MISC1, misc1); - //dstBeing->setSprite(SPRITE_MISC2, misc2); - dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, - ColorDB::getHairColor(hairColor)); - - player_node->imitateOutfit(dstBeing); + break; + } +} - if (msg.getId() == SMSG_PLAYER_MOVE) - { - Uint16 srcX, srcY, dstX, dstY; - msg.readCoordinatePair(srcX, srcY, dstX, dstY); +void BeingHandler::processNameResponse2(Net::MessageIn &msg) +{ + if (!actorSpriteManager || !player_node) + return; - player_node->followMoveTo(dstBeing, srcX, srcY, dstX, dstY); + Being *dstBeing; - dstBeing->setTileCoords(srcX, srcY); - dstBeing->setDestination(dstX, dstY); + int len = msg.readInt16(); + int beingId = msg.readInt32(); + std::string str = msg.readString(len - 8); + if ((dstBeing = actorSpriteManager->findBeing(beingId))) + { + if (beingId == player_node->getId()) + { + player_node->pingResponse(); + } + else + { + dstBeing->setName(str); + dstBeing->updateGuild(); + dstBeing->addToCache(); - // because server dont send direction in move packet, - // we fixing it + if (dstBeing->getType() == Being::PLAYER) + dstBeing->updateColors(); - if (srcX != dstX || srcY != dstY) + if (player_node) + { + Party *party = player_node->getParty(); + if (party && party->isMember(dstBeing->getId())) { - int dir = dstBeing->calcDirection(dstX, dstY); + PartyMember *member = party->getMember( + dstBeing->getId()); - if (dir && dstBeing->getDirection() != dir) - dstBeing->setDirectionDelayed(static_cast<Uint8>(dir)); + if (member) + member->setName(dstBeing->getName()); } - - if (player_node->getCurrentAction() != Being::STAND) - player_node->imitateAction(dstBeing, Being::STAND); - if (player_node->getDirection() != dstBeing->getDirection()) - { - player_node->imitateDirection(dstBeing, - dstBeing->getDirection()); - } - } - else - { - Uint8 dir; - Uint16 x, y; - msg.readCoordinates(x, y, dir); - dstBeing->setTileCoords(x, y); - dstBeing->setDirection(dir); - - player_node->imitateDirection(dstBeing, dir); + player_node->checkNewName(dstBeing); } + } + } +} - gmstatus = msg.readInt16(); +void BeingHandler::processPlayerMoveUpdate(Net::MessageIn &msg, int msgType) +{ + if (!actorSpriteManager || !player_node) + return; - if (gmstatus & 0x80) - dstBeing->setGM(true); + Uint16 headTop, headMid, headBottom; + Uint16 weapon, shield; + Uint16 gmstatus; + int level; + int guild; + Being *dstBeing; + int hairStyle, hairColor; + unsigned char colors[9]; + Uint8 dir; - if (msg.getId() == SMSG_PLAYER_UPDATE_1) - { - int type = msg.readInt8(); - switch (type) - { - case 0: - dstBeing->setAction(Being::STAND); - player_node->imitateAction(dstBeing, Being::STAND); - break; - - case 1: - dstBeing->setAction(Being::DEAD); - break; - - case 2: - dstBeing->setAction(Being::SIT); - player_node->imitateAction(dstBeing, Being::SIT); - break; - - default: - //need set stay state? - logger->log("QQQ2 SMSG_PLAYER_UPDATE_1:" - + toString(id) + " " + toString(type)); - if (dstBeing) - { - logger->log("dstBeing id:" - + toString(dstBeing->getId())); - logger->log("dstBeing name:" - + dstBeing->getName()); - } - break; + // An update about a player, potentially including movement. + int id = msg.readInt32(); + short speed = msg.readInt16(); + Uint16 stunMode = msg.readInt16(); // opt1; Aethyra use this as cape + Uint32 statusEffects = msg.readInt16(); // opt2; Aethyra use this as misc1 + statusEffects |= (static_cast<Uint32>(msg.readInt16())) + << 16; // status.options; Aethyra uses this as misc2 + short job = msg.readInt16(); - } - } - else if (msg.getId() == SMSG_PLAYER_MOVE) - { - msg.readInt8(); // unknown - } + dstBeing = actorSpriteManager->findBeing(id); - level = msg.readInt8(); // Lv - if (level) - dstBeing->setLevel(level); + if (!dstBeing) + { + if (actorSpriteManager->isBlocked(id) == true) + return; - msg.readInt8(); // unknown + dstBeing = createBeing(id, job); - if (dstBeing->getType() != Being::PLAYER - || msg.getId() != SMSG_PLAYER_MOVE) - { - dstBeing->setActionTime(tick_time); -// dstBeing->reset(); - } + if (!dstBeing) + return; + } - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, static_cast<Uint16>( - (statusEffects >> 16) & 0xffff)); - dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); + dir = dstBeing->getDirectionDelayed(); + if (dir) + { + if (dir != dstBeing->getDirection()) + dstBeing->setDirection(dir); + } - if (msg.getId() == SMSG_PLAYER_MOVE - && dstBeing->getType() == Being::PLAYER) - { - dstBeing->setMoveTime(); - } + if (Party *party = player_node->getParty()) + { + if (party->isMember(id)) + dstBeing->setParty(party); + } - 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 = actorSpriteManager->findBeing(id); - if (dstBeing) - { - Uint16 x, y; - x = msg.readInt16(); - y = msg.readInt16(); - dstBeing->setTileCoords(x, y); - if (dstBeing->getCurrentAction() == Being::MOVE) - dstBeing->setAction(Being::STAND); - } - } - break; + dstBeing->setWalkSpeed(Vector(speed, speed, 0)); + dstBeing->setSubtype(job); + hairStyle = msg.readInt16(); + weapon = msg.readInt16(); + shield = msg.readInt16(); + headBottom = msg.readInt16(); - 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... - */ - if (player_node) - player_node->fixAttackTarget(); - break; + if (msgType == 3) + msg.readInt32(); // server tick - case SMSG_PLAYER_STATUS_CHANGE: - // Change in players' flags + headTop = msg.readInt16(); + headMid = msg.readInt16(); + hairColor = msg.readInt16(); - id = msg.readInt32(); - dstBeing = actorSpriteManager->findBeing(id); - if (!dstBeing) - break; + colors[0] = msg.readInt8(); + colors[1] = msg.readInt8(); + colors[2] = msg.readInt8(); - stunMode = msg.readInt16(); - statusEffects = msg.readInt16(); - statusEffects |= (static_cast<Uint32>(msg.readInt16())) << 16; - msg.readInt8(); // Unused? + msg.readInt8(); //unused +// shoes = msg.readInt16(); +// gloves = msg.readInt16(); //sd->head_dir - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, static_cast<Uint16>( - (statusEffects >> 16) & 0xffff)); - dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); - break; + guild = msg.readInt32(); // guild + + if (guild == 0) + dstBeing->clearGuilds(); + else + dstBeing->setGuild(Guild::getGuild(static_cast<short>(guild))); + + msg.readInt16(); // emblem + msg.readInt16(); // manner + dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 + msg.readInt8(); // karma + dstBeing->setGender((msg.readInt8() == 0) + ? GENDER_FEMALE : GENDER_MALE); + + // Set these after the gender, as the sprites may be gender-specific + dstBeing->setSprite(SPRITE_WEAPON, weapon, "", 1, true); + if (!config.getBoolValue("hideShield")) + dstBeing->setSprite(SPRITE_SHIELD, shield); + //dstBeing->setSprite(SPRITE_SHOE, shoes); + if (serverVersion > 0) + { + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom, + "", colors[0]); + dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid, "", colors[2]); + dstBeing->setSprite(SPRITE_HAT, headTop, "", colors[1]); + } + else + { + dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); + dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); + dstBeing->setSprite(SPRITE_HAT, headTop); + } + //dstBeing->setSprite(SPRITE_GLOVES, gloves); + //dstBeing->setSprite(SPRITE_CAPE, cape); + //dstBeing->setSprite(SPRITE_MISC1, misc1); + //dstBeing->setSprite(SPRITE_MISC2, misc2); + dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, + ColorDB::getHairColor(hairColor)); - case SMSG_BEING_STATUS_CHANGE: - // Status change - status = msg.readInt16(); - id = msg.readInt32(); - flag = msg.readInt8(); // 0: stop, 1: start + player_node->imitateOutfit(dstBeing); - dstBeing = actorSpriteManager->findBeing(id); - if (dstBeing) - dstBeing->setStatusEffect(status, flag); - break; + if (msgType == 3) + { + Uint16 srcX, srcY, dstX, dstY; + msg.readCoordinatePair(srcX, srcY, dstX, dstY); - case SMSG_SKILL_CASTING: - msg.readInt32(); // src id - msg.readInt32(); // dst id - msg.readInt16(); // dst x - msg.readInt16(); // dst y - msg.readInt16(); // skill num - msg.readInt32(); // skill get pl - msg.readInt32(); // cast time - break; + player_node->followMoveTo(dstBeing, srcX, srcY, dstX, dstY); - case SMSG_SKILL_CAST_CANCEL: - msg.readInt32(); // id - break; + dstBeing->setTileCoords(srcX, srcY); + dstBeing->setDestination(dstX, dstY); - case SMSG_SKILL_NO_DAMAGE: - msg.readInt16(); // skill id - msg.readInt16(); // heal - msg.readInt32(); // dst id - msg.readInt32(); // src id - msg.readInt8(); // fail - break; + // because server dont send direction in move packet, + // we fixing it - case SMSG_PVP_MAP_MODE: + if (srcX != dstX || srcY != dstY) { - Game *game = Game::instance(); - if (!game) - break; + int dir = dstBeing->calcDirection(dstX, dstY); - Map *map = game->getCurrentMap(); - if (map) - map->setPvpMode(msg.readInt16()); - break; + if (dir && dstBeing->getDirection() != dir) + dstBeing->setDirectionDelayed(static_cast<Uint8>(dir)); } - case SMSG_PVP_SET: + if (player_node->getCurrentAction() != Being::STAND) + player_node->imitateAction(dstBeing, Being::STAND); + if (player_node->getDirection() != dstBeing->getDirection()) { - int id = msg.readInt32(); // id - int rank = msg.readInt32(); // rank - msg.readInt32(); // num - if (actorSpriteManager) - { - dstBeing = actorSpriteManager->findBeing(id); + player_node->imitateDirection(dstBeing, + dstBeing->getDirection()); + } + } + else + { + Uint8 dir; + Uint16 x, y; + msg.readCoordinates(x, y, dir); + dstBeing->setTileCoords(x, y); + dstBeing->setDirection(dir); + + player_node->imitateDirection(dstBeing, dir); + } + + gmstatus = msg.readInt16(); + + if (gmstatus & 0x80) + dstBeing->setGM(true); + + if (msgType == 1) + { + int type = msg.readInt8(); + switch (type) + { + case 0: + dstBeing->setAction(Being::STAND); + player_node->imitateAction(dstBeing, Being::STAND); + break; + + case 1: + dstBeing->setAction(Being::DEAD); + break; + + case 2: + dstBeing->setAction(Being::SIT); + player_node->imitateAction(dstBeing, Being::SIT); + break; + + default: + //need set stay state? + logger->log("QQQ2 SMSG_PLAYER_UPDATE_1:" + + toString(id) + " " + toString(type)); if (dstBeing) - dstBeing->setPvpRank(rank); - } - break; + { + logger->log("dstBeing id:" + + toString(dstBeing->getId())); + logger->log("dstBeing name:" + + dstBeing->getName()); + } + break; + } + } + else if (msgType == 3) + { + msg.readInt8(); // unknown + } - default: - break; + level = msg.readInt8(); // Lv + if (level) + dstBeing->setLevel(level); + + msg.readInt8(); // unknown + + if (dstBeing->getType() != Being::PLAYER + || msgType != 3) + { + dstBeing->setActionTime(tick_time); +// dstBeing->reset(); } -} -void BeingHandler::undress(Being *being) -{ - being->setSprite(SPRITE_BOTTOMCLOTHES, 0); - being->setSprite(SPRITE_TOPCLOTHES, 0); - being->setSprite(SPRITE_HAT, 0); - being->setSprite(SPRITE_SHOE, 0); - being->setSprite(SPRITE_GLOVES, 0); -// being->setSprite(SPRITE_WEAPON, 0, "", true); + dstBeing->setStunMode(stunMode); + dstBeing->setStatusEffectBlock(0, static_cast<Uint16>( + (statusEffects >> 16) & 0xffff)); + dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); + + if (msgType == 3 && dstBeing->getType() == Being::PLAYER) + dstBeing->setMoveTime(); } + + } // namespace TmwAthena |