summaryrefslogtreecommitdiff
path: root/src/net/ea/beinghandler.cpp
diff options
context:
space:
mode:
authorBertram <yohanndotferreiraatorange.fr>2010-04-16 13:58:56 +0200
committerBertram <yohanndotferreiraatorange.fr>2010-04-17 12:03:44 +0200
commit3ae525b05858af105cc7e3eb6ac7316fc2f5bbd5 (patch)
tree5737c40d37a7b87897b9dc9b422198b28a18b13a /src/net/ea/beinghandler.cpp
parent924760c45e0f1aa1105e192bd83d6a4ce2c80f81 (diff)
downloadmana-3ae525b05858af105cc7e3eb6ac7316fc2f5bbd5.tar.gz
mana-3ae525b05858af105cc7e3eb6ac7316fc2f5bbd5.tar.bz2
mana-3ae525b05858af105cc7e3eb6ac7316fc2f5bbd5.tar.xz
mana-3ae525b05858af105cc7e3eb6ac7316fc2f5bbd5.zip
Changed eAthena protocol name to TmwAthena and changed the config files accordingly.
This makes room for the actual eAthena protocol future inclusion.
Diffstat (limited to 'src/net/ea/beinghandler.cpp')
-rw-r--r--src/net/ea/beinghandler.cpp714
1 files changed, 0 insertions, 714 deletions
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp
deleted file mode 100644
index 55df2ede..00000000
--- a/src/net/ea/beinghandler.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- *
- * This file is part of The Mana Client.
- *
- * This program 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.
- *
- * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "net/ea/beinghandler.h"
-
-#include "being.h"
-#include "beingmanager.h"
-#include "client.h"
-#include "effectmanager.h"
-#include "guild.h"
-#include "localplayer.h"
-#include "log.h"
-#include "npc.h"
-#include "party.h"
-#include "playerrelations.h"
-
-#include "net/ea/protocol.h"
-
-#include "resources/colordb.h"
-
-#include <iostream>
-
-namespace EAthena {
-
-const int EMOTION_TIME = 150; /**< Duration of emotion icon */
-
-BeingHandler::BeingHandler(bool enableSync):
- mSync(enableSync)
-{
- static const Uint16 _messages[] = {
- SMSG_BEING_VISIBLE,
- SMSG_BEING_MOVE,
- SMSG_BEING_MOVE2,
- SMSG_BEING_REMOVE,
- SMSG_SKILL_DAMAGE,
- SMSG_BEING_ACTION,
- SMSG_BEING_SELFEFFECT,
- SMSG_BEING_EMOTION,
- SMSG_BEING_CHANGE_LOOKS,
- SMSG_BEING_CHANGE_LOOKS2,
- SMSG_BEING_NAME_RESPONSE,
- SMSG_PLAYER_GUILD_PARTY_INFO,
- SMSG_BEING_CHANGE_DIRECTION,
- SMSG_PLAYER_UPDATE_1,
- SMSG_PLAYER_UPDATE_2,
- SMSG_PLAYER_MOVE,
- SMSG_PLAYER_STOP,
- SMSG_PLAYER_MOVE_TO_ATTACK,
- SMSG_PLAYER_STATUS_CHANGE,
- SMSG_BEING_STATUS_CHANGE,
- SMSG_BEING_RESURRECT,
- 0
- };
- handledMessages = _messages;
-}
-
-Being *createBeing(int id, short job)
-{
- Being::Type type = Being::UNKNOWN;
- if (job <= 25 || (job >= 4001 && job <= 4049))
- type = Being::PLAYER;
- else if (job >= 46 && job <= 1000)
- type = Being::NPC;
- else if (job > 1000 && job <= 2000)
- type = Being::MONSTER;
- else if (job == 45)
- return NULL; // Skip portals
-
- Being *being = beingManager->createBeing(id, type, job);
-
- if (type == Being::PLAYER || type == Being::NPC)
- {
- MessageOut outMsg(0x0094);
- outMsg.writeInt32(id);//readLong(2));
- }
-
- return being;
-}
-
-void BeingHandler::handleMessage(Net::MessageIn &msg)
-{
- if (!beingManager)
- return;
-
- int id;
- short job, speed, gender;
- Uint16 headTop, headMid, headBottom;
- Uint16 shoes, gloves;
- Uint16 weapon, shield;
- Uint16 gmstatus;
- int param1;
- int stunMode;
- Uint32 statusEffects;
- int type, guild;
- Uint16 status;
- Being *srcBeing, *dstBeing;
- Player *player = 0;
- int hairStyle, hairColor, flag;
- std::string player_followed;
-
- switch (msg.getId())
- {
- case SMSG_BEING_VISIBLE:
- case SMSG_BEING_MOVE:
- // Information about a being in range
- id = msg.readInt32();
- speed = msg.readInt16();
- stunMode = msg.readInt16(); // opt1
- statusEffects = msg.readInt16(); // opt2
- statusEffects |= ((Uint32)msg.readInt16()) << 16; // option
- job = msg.readInt16(); // class
-
- dstBeing = beingManager->findBeing(id);
-
- 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;
- }
-
- dstBeing = createBeing(id, job);
-
- if (!dstBeing)
- break;
- }
-
- if (dstBeing->getType() == Being::PLAYER)
- player = static_cast<Player*>(dstBeing);
-
- if (msg.getId() == 0x0078)
- {
- dstBeing->clearPath();
- dstBeing->setFrame(0);
- dstBeing->setWalkTime(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);
- 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
- gloves = msg.readInt16(); // head dir - "abused" as gloves
- guild = msg.readInt32(); // guild
- if (player)
- {
- if (guild == 0)
- {
- player->clearGuilds();
- }
- else
- {
- player->addGuild(Guild::getGuild(guild));
- }
- }
- msg.readInt16(); // guild emblem
- msg.readInt16(); // manner
- dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3
- msg.readInt8(); // karma
- gender = msg.readInt8();
-
- if (player)
- {
- player->setGender((gender == 0)
- ? GENDER_FEMALE : GENDER_MALE);
- // Set these after the gender, as the sprites may be gender-specific
- player->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor));
- player->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
- player->setSprite(SPRITE_TOPCLOTHES, headMid);
- player->setSprite(SPRITE_HAT, headTop);
- player->setSprite(SPRITE_SHOE, shoes);
- player->setSprite(SPRITE_GLOVES, gloves);
- player->setSprite(SPRITE_WEAPON, weapon, "", true);
- player->setSprite(SPRITE_SHIELD, shield);
- }
-
- 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);
- }
- else
- {
- Uint8 dir;
- Uint16 x, y;
- msg.readCoordinates(x, y, dir);
- dstBeing->setTileCoords(x, y);
- dstBeing->setDirection(dir);
- }
-
- msg.readInt8(); // unknown
- msg.readInt8(); // unknown
- msg.readInt8(); // unknown / sit
-
- dstBeing->setStunMode(stunMode);
- dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
- dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
- 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->setTileCoords(srcX, srcY);
- dstBeing->setDestination(dstX, dstY);
- }
-
- break;
-
- case SMSG_BEING_REMOVE:
- // A being should be removed or has died
- id = msg.readInt32();
-
- dstBeing = beingManager->findBeing(id);
-
- if (!dstBeing)
- break;
-
- player_followed = player_node->getFollow();
-
- if (!player_followed.empty())
- {
- if (dstBeing->getName() == player_followed)
- {
- player_node->setDestination(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);
- else
- beingManager->destroyBeing(dstBeing);
-
- break;
-
- case SMSG_BEING_RESURRECT:
- // A being changed mortality status
- id = msg.readInt32();
-
- dstBeing = beingManager->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);
-
- break;
-
- case SMSG_SKILL_DAMAGE:
- msg.readInt16(); // Skill Id
- srcBeing = beingManager->findBeing(msg.readInt32());
- dstBeing = beingManager->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)
- dstBeing->takeDamage(srcBeing, param1, Being::HIT); // Perhaps a new skill attack type should be created and used?
- if (srcBeing)
- srcBeing->handleAttack(dstBeing, param1, Being::HIT);
- 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 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)
- dstBeing->takeDamage(srcBeing, param1,
- (Being::AttackType)type);
- if (srcBeing)
- srcBeing->handleAttack(dstBeing, param1,
- (Being::AttackType)type);
- break;
-
- case 0x02: // Sit
- if (srcBeing)
- {
- srcBeing->setFrame(0);
- srcBeing->setAction(Being::SIT);
- }
- break;
-
- case 0x03: // Stand up
- if (srcBeing)
- {
- srcBeing->setFrame(0);
- srcBeing->setAction(Being::STAND);
- }
- break;
- }
- break;
-
- case SMSG_BEING_SELFEFFECT: {
- id = (Uint32)msg.readInt32();
- if (!beingManager->findBeing(id))
- break;
-
- int effectType = msg.readInt32();
- Being* being = beingManager->findBeing(id);
-
- effectManager->trigger(effectType, being);
-
- break;
- }
-
- case SMSG_BEING_EMOTION:
- if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
- {
- break;
- }
-
- if (player_relations.hasPermission(dstBeing, PlayerRelation::EMOTE))
- {
- // only set emote if one doesnt already exist
- if (!dstBeing->getEmotion())
- dstBeing->setEmote(msg.readInt8(), EMOTION_TIME);
- }
-
- 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 = beingManager->findBeing(msg.readInt32())))
- {
- break;
- }
-
- if (dstBeing->getType() == Being::PLAYER)
- player = static_cast<Player*>(dstBeing);
-
- int type = msg.readInt8();
- int id = 0;
- int id2 = 0;
-
- if (msg.getId() == SMSG_BEING_CHANGE_LOOKS)
- {
- id = msg.readInt8();
- }
- else
- { // SMSG_BEING_CHANGE_LOOKS2
- id = msg.readInt16();
- id2 = msg.readInt16();
- }
-
- switch (type)
- {
- case 1: // eAthena LOOK_HAIR
- player->setSpriteID(SPRITE_HAIR, id *-1);
- break;
- case 2: // Weapon ID in id, Shield ID in id2
- player->setSprite(SPRITE_WEAPON, id, "", true);
- player->setSprite(SPRITE_SHIELD, id2);
- break;
- case 3: // Change lower headgear for eAthena, pants for us
- player->setSprite(SPRITE_BOTTOMCLOTHES, id);
- break;
- case 4: // Change upper headgear for eAthena, hat for us
- player->setSprite(SPRITE_HAT, id);
- break;
- case 5: // Change middle headgear for eathena, armor for us
- player->setSprite(SPRITE_TOPCLOTHES, id);
- break;
- case 6: // eAthena LOOK_HAIR_COLOR
- player->setSpriteColor(SPRITE_HAIR, ColorDB::get(id));
- break;
- case 8: // eAthena LOOK_SHIELD
- player->setSprite(SPRITE_SHIELD, id);
- break;
- case 9: // eAthena LOOK_SHOES
- player->setSprite(SPRITE_SHOE, id);
- break;
- case 10: // LOOK_GLOVES
- player->setSprite(SPRITE_GLOVES, id);
- break;
- case 11: // LOOK_CAPE
- player->setSprite(SPRITE_CAPE, id);
- break;
- case 12:
- player->setSprite(SPRITE_MISC1, id);
- break;
- case 13:
- player->setSprite(SPRITE_MISC2, id);
- break;
- default:
- logger->log("SMSG_BEING_CHANGE_LOOKS: unsupported type: "
- "%d, id: %d", type, id);
- break;
- }
- }
- break;
-
- case SMSG_BEING_NAME_RESPONSE:
- if ((dstBeing = beingManager->findBeing(msg.readInt32())))
- {
- dstBeing->setName(msg.readString(24));
- }
- break;
- case SMSG_PLAYER_GUILD_PARTY_INFO:
- if ((dstBeing = beingManager->findBeing(msg.readInt32())))
- {
- dstBeing->setPartyName(msg.readString(24));
- dstBeing->setGuildName(msg.readString(24));
- dstBeing->setGuildPos(msg.readString(24));
- msg.readString(24); // Discard this
- }
- break;
- case SMSG_BEING_CHANGE_DIRECTION:
- if (!(dstBeing = beingManager->findBeing(msg.readInt32())))
- {
- break;
- }
-
- msg.readInt16(); // unused
-
- dstBeing->setDirection(msg.readInt8());
-
- 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();
- stunMode = msg.readInt16(); // opt1; Aethyra use this as cape
- statusEffects = msg.readInt16(); // opt2; Aethyra use this as misc1
- statusEffects |= ((Uint32) msg.readInt16())
- << 16; // status.options; Aethyra uses this as misc2
- job = msg.readInt16();
-
- dstBeing = beingManager->findBeing(id);
-
- if (!dstBeing)
- {
- dstBeing = createBeing(id, job);
-
- if (!dstBeing)
- break;
- }
-
- if (dstBeing->getType() == Being::PLAYER)
- player = static_cast<Player*>(dstBeing);
-
- if (Party *party = player_node->getParty()){
- if (party->isMember(id))
- {
- player->setParty(party);
- }
- }
-
- dstBeing->setWalkSpeed(Vector(speed, speed, 0));
- dstBeing->setSubtype(job);
- hairStyle = msg.readInt16();
- weapon = msg.readInt16();
- shield = msg.readInt16();
- headBottom = msg.readInt16();
-
- if (msg.getId() == SMSG_PLAYER_MOVE)
- {
- msg.readInt32(); // server tick
- }
-
- headTop = msg.readInt16();
- headMid = msg.readInt16();
- hairColor = msg.readInt16();
- shoes = msg.readInt16();
- gloves = msg.readInt16();
- msg.readInt32(); // guild
- msg.readInt16(); // emblem
- msg.readInt16(); // manner
- dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3
- msg.readInt8(); // karma
- player->setGender((msg.readInt8() == 0)
- ? GENDER_FEMALE : GENDER_MALE);
-
- // Set these after the gender, as the sprites may be gender-specific
- player->setSprite(SPRITE_WEAPON, weapon, "", true);
- player->setSprite(SPRITE_SHIELD, shield);
- //player->setSprite(SPRITE_SHOE, shoes);
- player->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
- player->setSprite(SPRITE_TOPCLOTHES, headMid);
- player->setSprite(SPRITE_HAT, headTop);
- //player->setSprite(SPRITE_GLOVES, gloves);
- //player->setSprite(SPRITE_CAPE, cape);
- //player->setSprite(SPRITE_MISC1, misc1);
- //player->setSprite(SPRITE_MISC2, misc2);
- player->setSprite(SPRITE_HAIR, hairStyle * -1, ColorDB::get(hairColor));
-
- if (msg.getId() == SMSG_PLAYER_MOVE)
- {
- Uint16 srcX, srcY, dstX, dstY;
- msg.readCoordinatePair(srcX, srcY, dstX, dstY);
- dstBeing->setTileCoords(srcX, srcY);
- dstBeing->setDestination(dstX, dstY);
-
- player_followed = player_node->getFollow();
- if (!player_followed.empty())
- {
- if (dstBeing->getName() == player_followed)
- {
- player_node->setNextDest(dstX, dstY);
- player_node->setDestination(srcX, srcY);
- }
- }
- }
- else
- {
- Uint8 dir;
- Uint16 x, y;
- msg.readCoordinates(x, y, dir);
- dstBeing->setTileCoords(x, y);
- dstBeing->setDirection(dir);
- }
-
- gmstatus = msg.readInt16();
- if (gmstatus & 0x80)
- player->setGM(true);
-
- if (msg.getId() == SMSG_PLAYER_UPDATE_1)
- {
- switch (msg.readInt8())
- {
- case 1:
- dstBeing->setAction(Being::DEAD);
- break;
-
- case 2:
- dstBeing->setAction(Being::SIT);
- break;
- }
- }
- else if (msg.getId() == SMSG_PLAYER_MOVE)
- {
- msg.readInt8(); // unknown
- }
-
- msg.readInt8(); // Lv
- msg.readInt8(); // unknown
-
- dstBeing->setWalkTime(tick_time);
- dstBeing->setFrame(0);
-
- dstBeing->setStunMode(stunMode);
- dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
- dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
- 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)
- {
- Uint16 x, y;
- x = msg.readInt16();
- y = msg.readInt16();
- dstBeing->setTileCoords(x, y);
- if (dstBeing->getCurrentAction() == Being::WALK)
- {
- dstBeing->setFrame(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 SMSG_PLAYER_STATUS_CHANGE:
- // Change in players' flags
- id = msg.readInt32();
- dstBeing = beingManager->findBeing(id);
- stunMode = msg.readInt16();
- statusEffects = msg.readInt16();
- statusEffects |= ((Uint32) msg.readInt16()) << 16;
- msg.readInt8();
-
- if (dstBeing)
- {
- dstBeing->setStunMode(stunMode);
- dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff);
- dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff);
- }
- break;
-
- case SMSG_BEING_STATUS_CHANGE:
- // Status change
- status = msg.readInt16();
- id = msg.readInt32();
- flag = msg.readInt8(); // 0: stop, 1: start
-
- dstBeing = beingManager->findBeing(id);
- if (dstBeing)
- dstBeing->setStatusEffect(status, flag);
- break;
- }
-}
-
-} // namespace EAthena