summaryrefslogtreecommitdiff
path: root/src/net/ea
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/ea')
-rw-r--r--src/net/ea/beinghandler.cpp23
-rw-r--r--src/net/ea/charserverhandler.cpp33
-rw-r--r--src/net/ea/chathandler.cpp2
-rw-r--r--src/net/ea/equipmenthandler.cpp193
-rw-r--r--src/net/ea/equipmenthandler.h6
-rw-r--r--src/net/ea/generalhandler.cpp42
-rw-r--r--src/net/ea/generalhandler.h2
-rw-r--r--src/net/ea/inventoryhandler.cpp45
-rw-r--r--src/net/ea/loginhandler.cpp22
-rw-r--r--src/net/ea/maphandler.cpp20
-rw-r--r--src/net/ea/network.cpp6
-rw-r--r--src/net/ea/partyhandler.cpp1
-rw-r--r--src/net/ea/playerhandler.cpp290
-rw-r--r--src/net/ea/playerhandler.h8
-rw-r--r--src/net/ea/protocol.h25
-rw-r--r--src/net/ea/specialhandler.cpp (renamed from src/net/ea/skillhandler.cpp)87
-rw-r--r--src/net/ea/specialhandler.h (renamed from src/net/ea/skillhandler.h)14
17 files changed, 476 insertions, 343 deletions
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp
index f149f15f..1d780a60 100644
--- a/src/net/ea/beinghandler.cpp
+++ b/src/net/ea/beinghandler.cpp
@@ -194,14 +194,15 @@ void BeingHandler::handleMessage(MessageIn &msg)
Uint16 srcX, srcY, dstX, dstY;
msg.readCoordinatePair(srcX, srcY, dstX, dstY);
dstBeing->setAction(Being::STAND);
- dstBeing->mX = srcX;
- dstBeing->mY = srcY;
+ dstBeing->setTileCoords(srcX, srcY);
dstBeing->setDestination(dstX, dstY);
}
else
{
Uint8 dir;
- msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir);
+ Uint16 x, y;
+ msg.readCoordinates(x, y, dir);
+ dstBeing->setTileCoords(x, y);
dstBeing->setDirection(dir);
}
@@ -234,8 +235,7 @@ void BeingHandler::handleMessage(MessageIn &msg)
if (dstBeing) {
dstBeing->setAction(Being::STAND);
- dstBeing->mX = srcX;
- dstBeing->mY = srcY;
+ dstBeing->setTileCoords(srcX, srcY);
dstBeing->setDestination(dstX, dstY);
}
@@ -515,14 +515,15 @@ void BeingHandler::handleMessage(MessageIn &msg)
{
Uint16 srcX, srcY, dstX, dstY;
msg.readCoordinatePair(srcX, srcY, dstX, dstY);
- dstBeing->mX = srcX;
- dstBeing->mY = srcY;
+ dstBeing->setTileCoords(srcX, srcY);
dstBeing->setDestination(dstX, dstY);
}
else
{
Uint8 dir;
- msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir);
+ Uint16 x, y;
+ msg.readCoordinates(x, y, dir);
+ dstBeing->setTileCoords(x, y);
dstBeing->setDirection(dir);
}
@@ -577,8 +578,10 @@ void BeingHandler::handleMessage(MessageIn &msg)
if (mSync || id != player_node->getId()) {
dstBeing = beingManager->findBeing(id);
if (dstBeing) {
- dstBeing->mX = msg.readInt16();
- dstBeing->mY = msg.readInt16();
+ Uint16 x, y;
+ x = msg.readInt16();
+ y = msg.readInt16();
+ dstBeing->setTileCoords(x, y);
if (dstBeing->mAction == Being::WALK) {
dstBeing->mFrame = 0;
dstBeing->setAction(Being::STAND);
diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp
index 77bfaa50..6fae1864 100644
--- a/src/net/ea/charserverhandler.cpp
+++ b/src/net/ea/charserverhandler.cpp
@@ -61,18 +61,16 @@ CharServerHandler::CharServerHandler():
void CharServerHandler::handleMessage(MessageIn &msg)
{
- int slot, flags;
+ int slot;
LocalPlayer *tempPlayer;
logger->log("CharServerHandler: Packet ID: %x, Length: %d",
msg.getId(), msg.getLength());
switch (msg.getId())
{
- case 0x006b:
+ case SMSG_CHAR_LOGIN:
msg.skip(2); // Length word
- flags = msg.readInt32(); // Aethyra extensions flags
- logger->log("Server flags are: %x", flags);
- msg.skip(16); // Unused
+ msg.skip(20); // Unused
// Derive number of characters from message length
n_character = (msg.getLength() - 24) / 106;
@@ -92,13 +90,13 @@ void CharServerHandler::handleMessage(MessageIn &msg)
case SMSG_CHAR_LOGIN_ERROR:
switch (msg.readInt8()) {
case 0:
- errorMessage = _("Access denied");
+ errorMessage = _("Access denied.");
break;
case 1:
- errorMessage = _("Cannot use this ID");
+ errorMessage = _("Cannot use this ID.");
break;
default:
- errorMessage = _("Unknown failure to select character");
+ errorMessage = _("Unknown failure to select character.");
break;
}
mCharInfo->unlock();
@@ -169,14 +167,15 @@ void CharServerHandler::handleMessage(MessageIn &msg)
LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
{
- LocalPlayer *tempPlayer = new LocalPlayer(mLoginData->account_ID, 0, NULL);
+ LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0, NULL);
tempPlayer->setGender(mLoginData->sex);
- tempPlayer->mCharId = msg.readInt32();
- tempPlayer->setXp(msg.readInt32());
+ tempPlayer->setExp(msg.readInt32());
tempPlayer->setMoney(msg.readInt32());
- tempPlayer->mJobXp = msg.readInt32();
- tempPlayer->mJobLevel = msg.readInt32();
+ tempPlayer->setExperience(JOB, msg.readInt32(), 1);
+ int temp = msg.readInt32();
+ tempPlayer->setAttributeBase(JOB, temp);
+ tempPlayer->setAttributeEffective(JOB, temp);
tempPlayer->setSprite(Being::SHOE_SPRITE, msg.readInt16());
tempPlayer->setSprite(Being::GLOVES_SPRITE, msg.readInt16());
tempPlayer->setSprite(Being::CAPE_SPRITE, msg.readInt16());
@@ -187,8 +186,8 @@ LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
msg.skip(2); // unknown
tempPlayer->setHp(msg.readInt16());
tempPlayer->setMaxHp(msg.readInt16());
- tempPlayer->mMp = msg.readInt16();
- tempPlayer->mMaxMp = msg.readInt16();
+ tempPlayer->setMP(msg.readInt16());
+ tempPlayer->setMaxMP(msg.readInt16());
msg.readInt16(); // speed
msg.readInt16(); // class
int hairStyle = msg.readInt16();
@@ -205,7 +204,7 @@ LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
tempPlayer->setSprite(Being::MISC2_SPRITE, msg.readInt16());
tempPlayer->setName(msg.readString(24));
for (int i = 0; i < 6; i++) {
- tempPlayer->mAttr[i] = msg.readInt8();
+ tempPlayer->setAttributeBase(i + STR, msg.readInt8());
}
slot = msg.readInt8(); // character slot
msg.readInt8(); // unknown
@@ -272,7 +271,7 @@ void CharServerHandler::newCharacter(const std::string &name, int slot,
void CharServerHandler::deleteCharacter(int slot, LocalPlayer* character)
{
MessageOut outMsg(CMSG_CHAR_DELETE);
- outMsg.writeInt32(character->mCharId);
+ outMsg.writeInt32(character->getId());
outMsg.writeString("a@a.com", 40);
}
diff --git a/src/net/ea/chathandler.cpp b/src/net/ea/chathandler.cpp
index 49f83e67..65f1db3c 100644
--- a/src/net/ea/chathandler.cpp
+++ b/src/net/ea/chathandler.cpp
@@ -166,7 +166,7 @@ void ChatHandler::handleMessage(MessageIn &msg)
case SMSG_MVP:
// Display MVP player
msg.readInt32(); // id
- localChatTab->chatLog("MVP player", BY_SERVER);
+ localChatTab->chatLog(_("MVP player."), BY_SERVER);
break;
}
}
diff --git a/src/net/ea/equipmenthandler.cpp b/src/net/ea/equipmenthandler.cpp
index 0153b5da..3520bca5 100644
--- a/src/net/ea/equipmenthandler.cpp
+++ b/src/net/ea/equipmenthandler.cpp
@@ -35,10 +35,112 @@
#include "utils/gettext.h"
+const Equipment::EquipmentSlots EQUIP_POINTS[Equipment::EQUIP_VECTOREND] = {
+ Equipment::EQUIP_LEGS_SLOT,
+ Equipment::EQUIP_FIGHT1_SLOT,
+ Equipment::EQUIP_GLOVES_SLOT,
+ Equipment::EQUIP_RING2_SLOT,
+ Equipment::EQUIP_RING1_SLOT,
+ Equipment::EQUIP_FIGHT2_SLOT,
+ Equipment::EQUIP_FEET_SLOT,
+ Equipment::EQUIP_NECK_SLOT,
+ Equipment::EQUIP_HEAD_SLOT,
+ Equipment::EQUIP_TORSO_SLOT,
+ Equipment::EQUIP_PROJECTILE_SLOT};
+
+Item *equips[Equipment::EQUIP_VECTOREND];
+
namespace EAthena {
enum { debugEquipment = 1 };
+void setEquipment(int eAthenaSlot, int index, bool equiped)
+{
+ if (!eAthenaSlot)
+ return;
+
+ Item *item = player_node->getInventory()->getItem(index);
+
+ if (!item)
+ return;
+
+ int position = 0;
+
+ if (eAthenaSlot & 0x8000) { // Arrows
+ position = Equipment::EQUIP_PROJECTILE_SLOT;
+ }
+ else
+ {
+ /*
+ * An item may occupy more than 1 slot. If so, it's
+ * only shown as equipped on the *first* slot.
+ */
+ int mask = 1;
+ while (!(eAthenaSlot & mask))
+ {
+ mask <<= 1;
+ position++;
+ }
+
+ position = EQUIP_POINTS[position];
+ }
+
+ if (equips[position])
+ equips[position]->setEquipped(false);
+
+ if (equiped && item)
+ {
+ equips[position] = item;
+ item->setEquipped(true);
+ player_node->mEquipment->setEquipment(position, item->getId(), item->getQuantity());
+
+ if (debugEquipment)
+ {
+ logger->log("Equipping: %i %i at position %i",
+ index, eAthenaSlot, position);
+ }
+ }
+ else
+ {
+ equips[position] = NULL;
+ player_node->mEquipment->setEquipment(position, -1);
+
+ if (debugEquipment)
+ {
+ logger->log("Unequipping: %i %i at position %i",
+ index, eAthenaSlot, position);
+ }
+ }
+}
+
+void clearEquipment()
+{
+ for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++)
+ {
+ if (equips[i])
+ {
+ equips[i]->setEquipped(false);
+ player_node->mEquipment->setEquipment(i, -1);
+ }
+
+ equips[i] = NULL;
+ }
+}
+
+Item *getRealEquipedItem(const Item *equipped)
+{
+ if (!equipped)
+ return NULL;
+
+ for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++)
+ {
+ if (equips[i] && equipped->getId() == equips[i]->getId())
+ return equips[i];
+ }
+
+ return NULL;
+}
+
EquipmentHandler::EquipmentHandler()
{
static const Uint16 _messages[] = {
@@ -50,6 +152,7 @@ EquipmentHandler::EquipmentHandler()
0
};
handledMessages = _messages;
+ memset(equips, 0, sizeof(equips));
}
void EquipmentHandler::handleMessage(MessageIn &msg)
@@ -57,8 +160,6 @@ void EquipmentHandler::handleMessage(MessageIn &msg)
int itemCount;
int index, equipPoint, itemId;
int type;
- int mask, position;
- Item *item;
Inventory *inventory = player_node->getInventory();
switch (msg.getId())
@@ -79,25 +180,9 @@ void EquipmentHandler::handleMessage(MessageIn &msg)
msg.readInt8(); // refine
msg.skip(8); // card
- if (debugEquipment)
- {
- logger->log("Index: %d, ID: %d", index, itemId);
- }
-
inventory->setItem(index, itemId, 1, true);
- if (equipPoint)
- {
- mask = 1;
- position = 0;
- while (!(equipPoint & mask))
- {
- mask <<= 1;
- position++;
- }
- item = inventory->getItem(index);
- player_node->mEquipment->setEquipment(position, index);
- }
+ setEquipment(equipPoint, index, true);
}
break;
@@ -112,35 +197,7 @@ void EquipmentHandler::handleMessage(MessageIn &msg)
break;
}
- // No point in searching when no point given
- if (!equipPoint)
- break;
-
- /*
- * An item may occupy more than 1 slot. If so, it's
- * only shown as equipped on the *first* slot.
- */
- mask = 1;
- position = 0;
- while (!(equipPoint & mask)) {
- mask <<= 1;
- position++;
- }
-
- if (debugEquipment)
- {
- logger->log("Equipping: %i %i %i at position %i",
- index, equipPoint, type, position);
- }
-
- item = inventory->getItem(player_node->mEquipment->getEquipment(position));
-
- // Unequip any existing equipped item in this position
- if (item)
- item->setEquipped(false);
-
- item = inventory->getItem(index);
- player_node->mEquipment->setEquipment(position, index);
+ setEquipment(equipPoint, index, true);
break;
case SMSG_PLAYER_UNEQUIP:
@@ -153,36 +210,7 @@ void EquipmentHandler::handleMessage(MessageIn &msg)
break;
}
- if (!equipPoint) {
- // No point given, no point in searching
- break;
- }
-
- mask = 1;
- position = 0;
- while (!(equipPoint & mask)) {
- mask <<= 1;
- position++;
- }
-
- item = inventory->getItem(index);
- if (!item)
- break;
-
- item->setEquipped(false);
-
- if (equipPoint & 0x8000) { // Arrows
- player_node->mEquipment->setArrows(-1);
- }
- else {
- player_node->mEquipment->removeEquipment(position);
- }
-
- if (debugEquipment)
- {
- logger->log("Unequipping: %i %i(%i) %i",
- index, equipPoint, type, position);
- }
+ setEquipment(equipPoint, index, false);
break;
case SMSG_PLAYER_ATTACK_RANGE:
@@ -197,13 +225,8 @@ void EquipmentHandler::handleMessage(MessageIn &msg)
index -= INVENTORY_OFFSET;
- item = inventory->getItem(index);
-
- if (item) {
- item->setEquipped(true);
- player_node->mEquipment->setArrows(index);
- logger->log("Arrows equipped: %i", index);
- }
+ logger->log("Arrows equipped: %i", index);
+ setEquipment(0x8000, index, true);
break;
}
}
diff --git a/src/net/ea/equipmenthandler.h b/src/net/ea/equipmenthandler.h
index 852be3c9..47c2f803 100644
--- a/src/net/ea/equipmenthandler.h
+++ b/src/net/ea/equipmenthandler.h
@@ -24,8 +24,14 @@
#include "net/messagehandler.h"
+class Item;
+
namespace EAthena {
+void setEquipment(int eAthenaSlot, int index, bool equiped);
+void clearEquipment();
+Item *getRealEquipedItem(const Item *equipped);
+
class EquipmentHandler : public MessageHandler
{
public:
diff --git a/src/net/ea/generalhandler.cpp b/src/net/ea/generalhandler.cpp
index 404bff69..1d500d62 100644
--- a/src/net/ea/generalhandler.cpp
+++ b/src/net/ea/generalhandler.cpp
@@ -19,10 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "gui/inventorywindow.h"
-
#include "net/ea/generalhandler.h"
+#include "gui/inventorywindow.h"
+#include "gui/skilldialog.h"
+#include "gui/statuswindow.h"
+
#include "net/ea/network.h"
#include "net/ea/protocol.h"
@@ -41,7 +43,7 @@
#include "net/ea/playerhandler.h"
#include "net/ea/partyhandler.h"
#include "net/ea/tradehandler.h"
-#include "net/ea/skillhandler.h"
+#include "net/ea/specialhandler.h"
#include "net/ea/gui/partytab.h"
@@ -77,7 +79,7 @@ GeneralHandler::GeneralHandler():
mNpcHandler(new NpcHandler),
mPartyHandler(new PartyHandler),
mPlayerHandler(new PlayerHandler),
- mSkillHandler(new SkillHandler),
+ mSpecialHandler(new SpecialHandler),
mTradeHandler(new TradeHandler)
{
static const Uint16 _messages[] = {
@@ -115,26 +117,26 @@ void GeneralHandler::handleMessage(MessageIn &msg)
switch (code) {
case 0:
- errorMessage = _("Authentication failed");
+ errorMessage = _("Authentication failed.");
break;
case 1:
- errorMessage = _("No servers available");
+ errorMessage = _("No servers available.");
break;
case 2:
if (state == STATE_GAME)
errorMessage = _("Someone else is trying to use this "
- "account");
+ "account.");
else
- errorMessage = _("This account is already logged in");
+ errorMessage = _("This account is already logged in.");
break;
case 3:
- errorMessage = _("Speed hack detected");
+ errorMessage = _("Speed hack detected.");
break;
case 8:
- errorMessage = _("Duplicated login");
+ errorMessage = _("Duplicated login.");
break;
default:
- errorMessage = _("Unknown connection error");
+ errorMessage = _("Unknown connection error.");
break;
}
state = STATE_ERROR;
@@ -157,7 +159,7 @@ void GeneralHandler::load()
mNetwork->registerHandler(mMapHandler.get());
mNetwork->registerHandler(mNpcHandler.get());
mNetwork->registerHandler(mPlayerHandler.get());
- mNetwork->registerHandler(mSkillHandler.get());
+ mNetwork->registerHandler(mSpecialHandler.get());
mNetwork->registerHandler(mTradeHandler.get());
mNetwork->registerHandler(mPartyHandler.get());
}
@@ -201,6 +203,22 @@ void GeneralHandler::guiWindowsLoaded()
{
partyTab = new PartyTab;
inventoryWindow->setSplitAllowed(false);
+ skillDialog->loadSkills("ea-skills.xml");
+
+ statusWindow->addAttribute(STR, _("Strength"), true);
+ statusWindow->addAttribute(AGI, _("Agility"), true);
+ statusWindow->addAttribute(VIT, _("Vitality"), true);
+ statusWindow->addAttribute(INT, _("Intelligence"), true);
+ statusWindow->addAttribute(DEX, _("Dexterity"), true);
+ statusWindow->addAttribute(LUK, _("Luck"), true);
+
+ statusWindow->addAttribute(ATK, _("Attack"), false);
+ statusWindow->addAttribute(DEF, _("Defense"), false);
+ statusWindow->addAttribute(MATK, _("M.Attack"), false);
+ statusWindow->addAttribute(MDEF, _("M.Defense"), false);
+ statusWindow->addAttribute(HIT, _("% Accuracy"), false);
+ statusWindow->addAttribute(FLEE, _("% Evade"), false);
+ statusWindow->addAttribute(CRIT, _("% Critical"), false);
}
void GeneralHandler::guiWindowsUnloaded()
diff --git a/src/net/ea/generalhandler.h b/src/net/ea/generalhandler.h
index ebbc84ca..98364e5d 100644
--- a/src/net/ea/generalhandler.h
+++ b/src/net/ea/generalhandler.h
@@ -66,7 +66,7 @@ class GeneralHandler : public MessageHandler, public Net::GeneralHandler
MessageHandlerPtr mNpcHandler;
MessageHandlerPtr mPartyHandler;
MessageHandlerPtr mPlayerHandler;
- MessageHandlerPtr mSkillHandler;
+ MessageHandlerPtr mSpecialHandler;
MessageHandlerPtr mTradeHandler;
};
diff --git a/src/net/ea/inventoryhandler.cpp b/src/net/ea/inventoryhandler.cpp
index c1f04661..b6e91609 100644
--- a/src/net/ea/inventoryhandler.cpp
+++ b/src/net/ea/inventoryhandler.cpp
@@ -21,6 +21,7 @@
#include "net/ea/inventoryhandler.h"
+#include "net/ea/equipmenthandler.h"
#include "net/ea/protocol.h"
#include "net/messagein.h"
@@ -86,6 +87,7 @@ void InventoryHandler::handleMessage(MessageIn &msg)
if (msg.getId() == SMSG_PLAYER_INVENTORY)
{
// Clear inventory - this will be a complete refresh
+ clearEquipment();
inventory->clear();
}
else
@@ -178,42 +180,25 @@ void InventoryHandler::handleMessage(MessageIn &msg)
equipType = msg.readInt16();
itemType = msg.readInt8();
- if (msg.readInt8() > 0)
- {
- if (config.getValue("showpickupchat", 1))
- {
- localChatTab->chatLog(_("Unable to pick up item."),
- BY_SERVER);
- }
- }
- else
{
const ItemInfo &itemInfo = ItemDB::get(itemId);
- const std::string amountStr =
- // TRANSLATORS: Used as in "You picked up a ...", when
- // picking up only one item.
- (amount > 1) ? toString(amount) : _("a");
- if (config.getValue("showpickupchat", 1))
+ if (msg.readInt8() > 0)
{
- localChatTab->chatLog(strprintf(_("You picked up %s [@@%d|%s@@]."),
- amountStr.c_str(), itemInfo.getId(), itemInfo.getName().c_str()),
- BY_SERVER);
+ player_node->pickedUp(itemInfo, 0);
}
-
- if (config.getValue("showpickupparticle", 0))
+ else
{
- player_node->pickedUp(itemInfo.getName());
- }
+ player_node->pickedUp(itemInfo, amount);
+
+ Item *item = inventory->getItem(index);
+
+ if (item && item->getId() == itemId)
+ amount += inventory->getItem(index)->getQuantity();
- if (Item *item = inventory->getItem(index)) {
- item->setId(itemId);
- item->increaseQuantity(amount);
- } else {
inventory->setItem(index, itemId, amount, equipType != 0);
}
- }
- break;
+ } break;
case SMSG_PLAYER_INVENTORY_REMOVE:
index = msg.readInt16() - INVENTORY_OFFSET;
@@ -319,11 +304,13 @@ void InventoryHandler::equipItem(const Item *item)
void InventoryHandler::unequipItem(const Item *item)
{
- if (!item)
+ const Item *real_item = item->isEquipped() ? item : getRealEquipedItem(item);
+
+ if (!real_item)
return;
MessageOut outMsg(CMSG_PLAYER_UNEQUIP);
- outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET);
+ outMsg.writeInt16(real_item->getInvIndex() + INVENTORY_OFFSET);
}
void InventoryHandler::useItem(const Item *item)
diff --git a/src/net/ea/loginhandler.cpp b/src/net/ea/loginhandler.cpp
index 54e31cf3..8e7187c0 100644
--- a/src/net/ea/loginhandler.cpp
+++ b/src/net/ea/loginhandler.cpp
@@ -76,13 +76,13 @@ void LoginHandler::handleMessage(MessageIn &msg)
errorMessage = _("Account was not found. Please re-login.");
break;
case 2:
- errorMessage = _("Old password incorrect");
+ errorMessage = _("Old password incorrect.");
break;
case 3:
- errorMessage = _("New password too short");
+ errorMessage = _("New password too short.");
break;
default:
- errorMessage = _("Unknown error");
+ errorMessage = _("Unknown error.");
break;
}
state = STATE_ACCOUNTCHANGE_ERROR;
@@ -96,7 +96,7 @@ void LoginHandler::handleMessage(MessageIn &msg)
len = msg.readInt16() - 4;
mUpdateHost = msg.readString(len);
- logger->log("Received update host \"%s\" from login server",
+ logger->log("Received update host \"%s\" from login server.",
mUpdateHost.c_str());
break;
@@ -139,21 +139,21 @@ void LoginHandler::handleMessage(MessageIn &msg)
switch (code) {
case 0:
- errorMessage = _("Unregistered ID");
+ errorMessage = _("Unregistered ID.");
break;
case 1:
- errorMessage = _("Wrong password");
+ errorMessage = _("Wrong password.");
break;
case 2:
- errorMessage = _("Account expired");
+ errorMessage = _("Account expired.");
break;
case 3:
- errorMessage = _("Rejected from server");
+ errorMessage = _("Rejected from server.");
break;
case 4:
errorMessage = _("You have been permanently banned from "
- "the game. Please contact the GM Team.");
+ "the game. Please contact the GM team.");
break;
case 6:
errorMessage = strprintf(_("You have been temporarily "
@@ -163,10 +163,10 @@ void LoginHandler::handleMessage(MessageIn &msg)
msg.readString(20).c_str());
break;
case 9:
- errorMessage = _("This user name is already taken");
+ errorMessage = _("This user name is already taken.");
break;
default:
- errorMessage = _("Unknown error");
+ errorMessage = _("Unknown error.");
break;
}
state = STATE_ERROR;
diff --git a/src/net/ea/maphandler.cpp b/src/net/ea/maphandler.cpp
index 6f8a9827..c3c9437c 100644
--- a/src/net/ea/maphandler.cpp
+++ b/src/net/ea/maphandler.cpp
@@ -61,14 +61,17 @@ void MapHandler::handleMessage(MessageIn &msg)
switch (msg.getId())
{
case SMSG_MAP_LOGIN_SUCCESS:
+ {
+ Uint16 x, y;
msg.readInt32(); // server tick
- msg.readCoordinates(player_node->mX, player_node->mY, direction);
+ msg.readCoordinates(x, y, direction);
msg.skip(2); // unknown
logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
- player_node->mX, player_node->mY, direction);
+ x, y, direction);
state = STATE_GAME;
+ player_node->setTileCoords(x, y);
game = new Game;
- break;
+ } break;
case SMSG_SERVER_PING:
// We ignore this for now
@@ -76,22 +79,27 @@ void MapHandler::handleMessage(MessageIn &msg)
break;
case SMSG_WHO_ANSWER:
- localChatTab->chatLog("Online users: " + toString(msg.readInt32()),
- BY_SERVER);
+ localChatTab->chatLog(strprintf(_("Online users: %d"),
+ msg.readInt32()), BY_SERVER);
break;
}
}
+#include <fstream>
+
void MapHandler::connect(LoginData *loginData)
{
// Send login infos
MessageOut outMsg(CMSG_MAP_SERVER_CONNECT);
outMsg.writeInt32(loginData->account_ID);
- outMsg.writeInt32(player_node->mCharId);
+ outMsg.writeInt32(player_node->getId());
outMsg.writeInt32(loginData->session_ID1);
outMsg.writeInt32(loginData->session_ID2);
outMsg.writeInt8((loginData->sex == GENDER_MALE) ? 1 : 0);
+ // Change the player's ID to the account ID to match what eAthena uses
+ player_node->setId(loginData->account_ID);
+
// We get 4 useless bytes before the real answer comes in (what are these?)
mNetwork->skip(4);
}
diff --git a/src/net/ea/network.cpp b/src/net/ea/network.cpp
index 956d7877..c6bc712c 100644
--- a/src/net/ea/network.cpp
+++ b/src/net/ea/network.cpp
@@ -318,9 +318,9 @@ bool Network::realConnect()
if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
{
- std::string error = "Unable to resolve host \"" + mAddress + "\"";
- setError(error);
- logger->log("SDLNet_ResolveHost: %s", error.c_str());
+ std::string errorMessage = "Unable to resolve host \"" + mAddress + "\"";
+ setError(errorMessage);
+ logger->log("SDLNet_ResolveHost: %s", errorMessage.c_str());
return false;
}
diff --git a/src/net/ea/partyhandler.cpp b/src/net/ea/partyhandler.cpp
index 5e7f43c4..a4a84b07 100644
--- a/src/net/ea/partyhandler.cpp
+++ b/src/net/ea/partyhandler.cpp
@@ -230,6 +230,7 @@ void PartyHandler::handleMessage(MessageIn &msg)
if (id == player_node->getId())
{
partyWindow->clearMembers();
+ partyWindow->clearPartyName();
partyWindow->setVisible(false);
partyTab->chatLog(_("You have left the party."), BY_SERVER);
}
diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp
index 58167339..3e379d82 100644
--- a/src/net/ea/playerhandler.cpp
+++ b/src/net/ea/playerhandler.cpp
@@ -37,7 +37,7 @@
#include "gui/gui.h"
#include "gui/okdialog.h"
#include "gui/sell.h"
-#include "gui/skill.h"
+#include "gui/statuswindow.h"
#include "gui/storagewindow.h"
#include "gui/viewport.h"
@@ -54,6 +54,9 @@ OkDialog *deathNotice = NULL;
// everything beyond will reset the port hard.
static const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
+#define ATTR_BONUS(atr) \
+(player_node->getAttributeEffective(atr) - player_node->getAttributeBase(atr))
+
// TODO Move somewhere else
namespace {
@@ -197,17 +200,16 @@ void PlayerHandler::handleMessage(MessageIn &msg)
/* Scroll if neccessary */
if (!nearby
- || (abs(x - player_node->mX) > MAP_TELEPORT_SCROLL_DISTANCE)
- || (abs(y - player_node->mY) > MAP_TELEPORT_SCROLL_DISTANCE))
+ || (abs(x - player_node->getTileX()) > MAP_TELEPORT_SCROLL_DISTANCE)
+ || (abs(y - player_node->getTileY()) > MAP_TELEPORT_SCROLL_DISTANCE))
{
- scrollOffsetX = (x - player_node->mX) * 32;
- scrollOffsetY = (y - player_node->mY) * 32;
+ scrollOffsetX = (x - player_node->getTileX()) * 32;
+ scrollOffsetY = (y - player_node->getTileY()) * 32;
}
player_node->setAction(Being::STAND);
player_node->mFrame = 0;
- player_node->mX = x;
- player_node->mY = y;
+ player_node->setTileCoords(x, y);
logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX,
(int) scrollOffsetY);
@@ -224,18 +226,14 @@ void PlayerHandler::handleMessage(MessageIn &msg)
switch (type)
{
case 0x0000: player_node->setWalkSpeed(value); break;
+ case 0x0004: break; // manner
case 0x0005: player_node->setHp(value); break;
case 0x0006: player_node->setMaxHp(value); break;
- case 0x0007: player_node->mMp = value; break;
- case 0x0008: player_node->mMaxMp = value; break;
- case 0x0009:
- player_node->mStatsPointsToAttribute = value;
- break;
+ case 0x0007: player_node->setMP(value); break;
+ case 0x0008: player_node->setMaxMP(value); break;
+ case 0x0009: player_node->setCharacterPoints(value); break;
case 0x000b: player_node->setLevel(value); break;
- case 0x000c:
- player_node->mSkillPoint = value;
- skillDialog->update();
- break;
+ case 0x000c: player_node->setSkillPoints(value); break;
case 0x0018:
if (value >= player_node->getMaxWeight() / 2 &&
player_node->getTotalWeight() <
@@ -251,15 +249,48 @@ void PlayerHandler::handleMessage(MessageIn &msg)
player_node->setTotalWeight(value);
break;
case 0x0019: player_node->setMaxWeight(value); break;
- case 0x0029: player_node->ATK = value; break;
- case 0x002b: player_node->MATK = value; break;
- case 0x002d: player_node->DEF = value; break;
- case 0x002e: player_node->DEF_BONUS = value; break;
- case 0x002f: player_node->MDEF = value; break;
- case 0x0031: player_node->HIT = value; break;
- case 0x0032: player_node->FLEE = value; break;
+
+ case 0x0029: player_node->setAttributeEffective(ATK, value
+ + ATTR_BONUS(ATK));
+ player_node->setAttributeBase(ATK, value);
+ break;
+ case 0x002a: value += player_node->getAttributeBase(ATK);
+ player_node->setAttributeEffective(ATK, value); break;
+
+ case 0x002b: player_node->setAttributeEffective(MATK, value
+ + ATTR_BONUS(MATK));
+ player_node->setAttributeBase(MATK, value);
+ statusWindow->update(StatusWindow::MP); break;
+ case 0x002c: value += player_node->getAttributeBase(MATK);
+ player_node->setAttributeEffective(MATK, value);
+ statusWindow->update(StatusWindow::MP); break;
+ case 0x002d: player_node->setAttributeEffective(DEF, value
+ + ATTR_BONUS(DEF));
+ player_node->setAttributeBase(DEF, value); break;
+ case 0x002e: value += player_node->getAttributeBase(DEF);
+ player_node->setAttributeEffective(DEF, value); break;
+
+ case 0x002f: player_node->setAttributeEffective(MDEF, value
+ + ATTR_BONUS(MDEF));
+ player_node->setAttributeBase(MDEF, value); break;
+ case 0x0030: value += player_node->getAttributeBase(MDEF);
+ player_node->setAttributeEffective(MDEF, value); break;
+
+ case 0x0031: player_node->setAttributeBase(HIT, value);
+ player_node->setAttributeEffective(HIT, value); break;
+
+ case 0x0032: player_node->setAttributeEffective(FLEE, value
+ + ATTR_BONUS(FLEE));
+ player_node->setAttributeBase(FLEE, value); break;
+ case 0x0033: value += player_node->getAttributeBase(FLEE);
+ player_node->setAttributeEffective(FLEE, value); break;
+
+ case 0x0034: player_node->setAttributeBase(CRIT, value);
+ player_node->setAttributeEffective(CRIT, value); break;
+
case 0x0035: player_node->mAttackSpeed = value; break;
- case 0x0037: player_node->mJobLevel = value; break;
+ case 0x0037: player_node->setAttributeBase(JOB, value);
+ player_node->setAttributeEffective(JOB, value); break;
case 500: player_node->setGMLevel(value); break;
}
@@ -276,54 +307,45 @@ void PlayerHandler::handleMessage(MessageIn &msg)
case SMSG_PLAYER_STAT_UPDATE_2:
switch (msg.readInt16()) {
case 0x0001:
- player_node->setXp(msg.readInt32());
+ player_node->setExp(msg.readInt32());
break;
case 0x0002:
- player_node->mJobXp = msg.readInt32();
+ player_node->setExperience(JOB, msg.readInt32(),
+ player_node->getExperience(JOB).second);
break;
case 0x0014: {
int curGp = player_node->getMoney();
player_node->setMoney(msg.readInt32());
if (player_node->getMoney() > curGp)
- localChatTab->chatLog(_("You picked up ") +
+ localChatTab->chatLog(strprintf(_("You picked up "
+ "%s."),
Units::formatCurrency(player_node->getMoney()
- - curGp), BY_SERVER);
+ - curGp).c_str()), BY_SERVER);
}
break;
case 0x0016:
- player_node->mXpForNextLevel = msg.readInt32();
+ player_node->setExpNeeded(msg.readInt32());
break;
case 0x0017:
- player_node->mJobXpForNextLevel = msg.readInt32();
+ player_node->setExperience(JOB,
+ player_node->getExperience(JOB).first,
+ msg.readInt32());
break;
}
break;
- case SMSG_PLAYER_STAT_UPDATE_3:
+ case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute
{
int type = msg.readInt32();
int base = msg.readInt32();
int bonus = msg.readInt32();
- int total = base + bonus;
- switch (type) {
- case 0x000d: player_node->mAttr[LocalPlayer::STR] = total;
- break;
- case 0x000e: player_node->mAttr[LocalPlayer::AGI] = total;
- break;
- case 0x000f: player_node->mAttr[LocalPlayer::VIT] = total;
- break;
- case 0x0010: player_node->mAttr[LocalPlayer::INT] = total;
- break;
- case 0x0011: player_node->mAttr[LocalPlayer::DEX] = total;
- break;
- case 0x0012: player_node->mAttr[LocalPlayer::LUK] = total;
- break;
- }
+ player_node->setAttributeBase(type, base);
+ player_node->setAttributeEffective(type, base + bonus);
}
break;
- case SMSG_PLAYER_STAT_UPDATE_4:
+ case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack
{
int type = msg.readInt16();
int fail = msg.readInt8();
@@ -332,72 +354,105 @@ void PlayerHandler::handleMessage(MessageIn &msg)
if (fail != 1)
break;
- switch (type) {
- case 0x000d: player_node->mAttr[LocalPlayer::STR] = value;
- break;
- case 0x000e: player_node->mAttr[LocalPlayer::AGI] = value;
- break;
- case 0x000f: player_node->mAttr[LocalPlayer::VIT] = value;
- break;
- case 0x0010: player_node->mAttr[LocalPlayer::INT] = value;
- break;
- case 0x0011: player_node->mAttr[LocalPlayer::DEX] = value;
- break;
- case 0x0012: player_node->mAttr[LocalPlayer::LUK] = value;
- break;
- }
+ int bonus = ATTR_BONUS(type);
+
+ player_node->setAttributeBase(type, value);
+ player_node->setAttributeEffective(type, value + bonus);
}
break;
// Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
- player_node->mStatsPointsToAttribute = msg.readInt16();
- player_node->mAttr[LocalPlayer::STR] = msg.readInt8();
- player_node->mAttrUp[LocalPlayer::STR] = msg.readInt8();
- player_node->mAttr[LocalPlayer::AGI] = msg.readInt8();
- player_node->mAttrUp[LocalPlayer::AGI] = msg.readInt8();
- player_node->mAttr[LocalPlayer::VIT] = msg.readInt8();
- player_node->mAttrUp[LocalPlayer::VIT] = msg.readInt8();
- player_node->mAttr[LocalPlayer::INT] = msg.readInt8();
- player_node->mAttrUp[LocalPlayer::INT] = msg.readInt8();
- player_node->mAttr[LocalPlayer::DEX] = msg.readInt8();
- player_node->mAttrUp[LocalPlayer::DEX] = msg.readInt8();
- player_node->mAttr[LocalPlayer::LUK] = msg.readInt8();
- player_node->mAttrUp[LocalPlayer::LUK] = msg.readInt8();
- player_node->ATK = msg.readInt16(); // ATK
- player_node->ATK_BONUS = msg.readInt16(); // ATK bonus
- player_node->MATK = msg.readInt16(); // MATK max
- player_node->MATK_BONUS = msg.readInt16(); // MATK min
- player_node->DEF = msg.readInt16(); // DEF
- player_node->DEF_BONUS = msg.readInt16(); // DEF bonus
- player_node->MDEF = msg.readInt16(); // MDEF
- player_node->MDEF_BONUS = msg.readInt16(); // MDEF bonus
- player_node->HIT = msg.readInt16(); // HIT
- player_node->FLEE = msg.readInt16(); // FLEE
- player_node->FLEE_BONUS = msg.readInt16(); // FLEE bonus
- msg.readInt16(); // critical
- msg.readInt16(); // unknown
+ player_node->setCharacterPoints(msg.readInt16());
+
+ {
+ int val = msg.readInt8();
+ player_node->setAttributeEffective(STR, val + ATTR_BONUS(STR));
+ player_node->setAttributeBase(STR, val);
+ statusWindow->setPointsNeeded(STR, msg.readInt8());
+
+ val = msg.readInt8();
+ player_node->setAttributeEffective(AGI, val + ATTR_BONUS(AGI));
+ player_node->setAttributeBase(AGI, val);
+ statusWindow->setPointsNeeded(AGI, msg.readInt8());
+
+ val = msg.readInt8();
+ player_node->setAttributeEffective(VIT, val + ATTR_BONUS(VIT));
+ player_node->setAttributeBase(VIT, val);
+ statusWindow->setPointsNeeded(VIT, msg.readInt8());
+
+ val = msg.readInt8();
+ player_node->setAttributeEffective(INT, val + ATTR_BONUS(INT));
+ player_node->setAttributeBase(INT, val);
+ statusWindow->setPointsNeeded(INT, msg.readInt8());
+
+ val = msg.readInt8();
+ player_node->setAttributeEffective(DEX, val + ATTR_BONUS(DEX));
+ player_node->setAttributeBase(DEX, val);
+ statusWindow->setPointsNeeded(DEX, msg.readInt8());
+
+ val = msg.readInt8();
+ player_node->setAttributeEffective(LUK, val + ATTR_BONUS(LUK));
+ player_node->setAttributeBase(LUK, val);
+ statusWindow->setPointsNeeded(LUK, msg.readInt8());
+
+ val = msg.readInt16(); // ATK
+ player_node->setAttributeBase(ATK, val);
+ val += msg.readInt16(); // ATK bonus
+ player_node->setAttributeEffective(ATK, val);
+
+ val = msg.readInt16(); // MATK
+ player_node->setAttributeBase(MATK, val);
+ val += msg.readInt16(); // MATK bonus
+ player_node->setAttributeEffective(MATK, val);
+ statusWindow->update(StatusWindow::MP);
+
+ val = msg.readInt16(); // DEF
+ player_node->setAttributeBase(DEF, val);
+ val += msg.readInt16(); // DEF bonus
+ player_node->setAttributeEffective(DEF, val);
+
+ val = msg.readInt16(); // MDEF
+ player_node->setAttributeBase(MDEF, val);
+ val += msg.readInt16(); // MDEF bonus
+ player_node->setAttributeEffective(MDEF, val);
+
+ val = msg.readInt16(); // HIT
+ player_node->setAttributeBase(ATK, val);
+ player_node->setAttributeEffective(ATK, val);
+
+ val = msg.readInt16(); // FLEE
+ player_node->setAttributeBase(FLEE, val);
+ val += msg.readInt16(); // FLEE bonus
+ player_node->setAttributeEffective(FLEE, val);
+
+ val = msg.readInt16();
+ player_node->setAttributeBase(CRIT, val);
+ player_node->setAttributeEffective(CRIT, val);
+ }
+
+ msg.readInt16(); // manner
break;
case SMSG_PLAYER_STAT_UPDATE_6:
switch (msg.readInt16()) {
case 0x0020:
- player_node->mAttrUp[LocalPlayer::STR] = msg.readInt8();
+ statusWindow->setPointsNeeded(STR, msg.readInt8());
break;
case 0x0021:
- player_node->mAttrUp[LocalPlayer::AGI] = msg.readInt8();
+ statusWindow->setPointsNeeded(AGI, msg.readInt8());
break;
case 0x0022:
- player_node->mAttrUp[LocalPlayer::VIT] = msg.readInt8();
+ statusWindow->setPointsNeeded(VIT, msg.readInt8());
break;
case 0x0023:
- player_node->mAttrUp[LocalPlayer::INT] = msg.readInt8();
+ statusWindow->setPointsNeeded(INT, msg.readInt8());
break;
case 0x0024:
- player_node->mAttrUp[LocalPlayer::DEX] = msg.readInt8();
+ statusWindow->setPointsNeeded(DEX, msg.readInt8());
break;
case 0x0025:
- player_node->mAttrUp[LocalPlayer::LUK] = msg.readInt8();
+ statusWindow->setPointsNeeded(LUK, msg.readInt8());
break;
}
break;
@@ -433,44 +488,30 @@ void PlayerHandler::emote(int emoteId)
outMsg.writeInt8(emoteId);
}
-void PlayerHandler::increaseStat(LocalPlayer::Attribute attr)
+void PlayerHandler::increaseAttribute(size_t attr)
{
- MessageOut outMsg(CMSG_STAT_UPDATE_REQUEST);
-
- switch (attr)
+ if (attr >= STR && attr <= LUK)
{
- case LocalPlayer::STR:
- outMsg.writeInt16(0x000d);
- break;
-
- case LocalPlayer::AGI:
- outMsg.writeInt16(0x000e);
- break;
-
- case LocalPlayer::VIT:
- outMsg.writeInt16(0x000f);
- break;
-
- case LocalPlayer::INT:
- outMsg.writeInt16(0x0010);
- break;
-
- case LocalPlayer::DEX:
- outMsg.writeInt16(0x0011);
- break;
-
- case LocalPlayer::LUK:
- outMsg.writeInt16(0x0012);
- break;
+ MessageOut outMsg(CMSG_STAT_UPDATE_REQUEST);
+ outMsg.writeInt16(attr);
+ outMsg.writeInt8(1);
}
- outMsg.writeInt8(1);
}
-void PlayerHandler::decreaseStat(LocalPlayer::Attribute attr)
+void PlayerHandler::decreaseAttribute(size_t attr)
{
// Supported by eA?
}
+void PlayerHandler::increaseSkill(int skillId)
+{
+ if (player_node->getSkillPoints() <= 0)
+ return;
+
+ MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST);
+ outMsg.writeInt16(skillId);
+}
+
void PlayerHandler::pickUp(FloorItem *floorItem)
{
MessageOut outMsg(CMSG_ITEM_PICKUP);
@@ -521,4 +562,9 @@ void PlayerHandler::ignoreAll(bool ignore)
// TODO
}
+bool PlayerHandler::canUseMagic()
+{
+ return player_node->getAttributeEffective(MATK) > 0;
+}
+
} // namespace EAthena
diff --git a/src/net/ea/playerhandler.h b/src/net/ea/playerhandler.h
index 5dbc171b..78e64a88 100644
--- a/src/net/ea/playerhandler.h
+++ b/src/net/ea/playerhandler.h
@@ -39,9 +39,11 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler
void emote(int emoteId);
- void increaseStat(LocalPlayer::Attribute attr);
+ void increaseAttribute(size_t attr);
- void decreaseStat(LocalPlayer::Attribute attr);
+ void decreaseAttribute(size_t attr);
+
+ void increaseSkill(int skillId);
void pickUp(FloorItem *floorItem);
@@ -56,6 +58,8 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler
void ignorePlayer(const std::string &player, bool ignore);
void ignoreAll(bool ignore);
+
+ bool canUseMagic();
};
} // namespace EAthena
diff --git a/src/net/ea/protocol.h b/src/net/ea/protocol.h
index b3759946..279e4c2f 100644
--- a/src/net/ea/protocol.h
+++ b/src/net/ea/protocol.h
@@ -22,6 +22,25 @@
#ifndef EA_PROTOCOL_H
#define EA_PROTOCOL_H
+enum {
+ JOB = 0xa,
+
+ STR = 0xd,
+ AGI,
+ VIT,
+ INT,
+ DEX,
+ LUK,
+
+ ATK,
+ DEF,
+ MATK,
+ MDEF,
+ HIT,
+ FLEE,
+ CRIT
+};
+
static const int INVENTORY_OFFSET = 2;
static const int STORAGE_OFFSET = 1;
@@ -69,6 +88,7 @@ static const int STORAGE_OFFSET = 1;
#define SMSG_PLAYER_ARROW_EQUIP 0x013c
#define SMSG_PLAYER_ARROW_MESSAGE 0x013b
#define SMSG_PLAYER_SKILLS 0x010f
+#define SMSG_PLAYER_SKILL_UP 0x010e
#define SMSG_SKILL_FAILED 0x0110
#define SMSG_ITEM_USE_RESPONSE 0x00a8
#define SMSG_ITEM_VISIBLE 0x009d /**< An item is on the floor */
@@ -160,6 +180,11 @@ static const int STORAGE_OFFSET = 1;
#define CMSG_SKILL_LEVELUP_REQUEST 0x0112
#define CMSG_STAT_UPDATE_REQUEST 0x00bb
+#define CMSG_SKILL_USE_BEING 0x0113
+#define CMSG_SKILL_USE_POSITION 0x0116
+// Variant of 0x116 with 80 char string at end (unsure of use)
+#define CMSG_SKILL_USE_POSITION_MORE 0x0190
+#define CMSG_SKILL_USE_MAP 0x011b
#define CMSG_PLAYER_INVENTORY_USE 0x00a7
#define CMSG_PLAYER_INVENTORY_DROP 0x00a2
diff --git a/src/net/ea/skillhandler.cpp b/src/net/ea/specialhandler.cpp
index 69b0fd65..528f531e 100644
--- a/src/net/ea/skillhandler.cpp
+++ b/src/net/ea/specialhandler.cpp
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "net/ea/skillhandler.h"
+#include "net/ea/specialhandler.h"
#include "net/ea/protocol.h"
@@ -29,7 +29,7 @@
#include "localplayer.h"
#include "log.h"
-#include "gui/skill.h"
+#include "gui/skilldialog.h"
#include "gui/widgets/chattab.h"
@@ -67,60 +67,68 @@
/** should always be zero if failed */
#define SKILL_FAILED 0x00
-Net::SkillHandler *skillHandler;
+Net::SpecialHandler *specialHandler;
namespace EAthena {
-SkillHandler::SkillHandler()
+SpecialHandler::SpecialHandler()
{
static const Uint16 _messages[] = {
SMSG_PLAYER_SKILLS,
SMSG_SKILL_FAILED,
+ SMSG_PLAYER_SKILL_UP,
0
};
handledMessages = _messages;
- skillHandler = this;
+ specialHandler = this;
}
-void SkillHandler::handleMessage(MessageIn &msg)
+void SpecialHandler::handleMessage(MessageIn &msg)
{
int skillCount;
+ int skillId;
switch (msg.getId())
{
case SMSG_PLAYER_SKILLS:
msg.readInt16(); // length
skillCount = (msg.getLength() - 4) / 37;
- skillDialog->cleanList();
for (int k = 0; k < skillCount; k++)
{
- int skillId = msg.readInt16();
+ skillId = msg.readInt16();
msg.readInt16(); // target type
- msg.readInt16(); // unknown
+ msg.skip(2); // unused
int level = msg.readInt16();
- int sp = msg.readInt16();
- msg.readInt16(); // range
- std::string skillName = msg.readString(24);
+ msg.readInt16(); // sp
+ msg.readInt16(); // range
+ msg.skip(24); // unused
int up = msg.readInt8();
- if (level != 0 || up != 0)
- {
- if (skillDialog->hasSkill(skillId)) {
- skillDialog->setSkill(skillId, level, sp);
- }
- else {
- skillDialog->addSkill(skillId, level, sp);
- }
- }
+ player_node->setAttributeBase(skillId, level);
+ player_node->setAttributeEffective(skillId, level);
+ skillDialog->setModifiable(skillId, up);
+ }
+ break;
+
+ case SMSG_PLAYER_SKILL_UP:
+ {
+ skillId = msg.readInt16();
+ int level = msg.readInt16();
+ msg.readInt16(); // sp
+ msg.readInt16(); // range
+ int up = msg.readInt8();
+
+ player_node->setAttributeBase(skillId, level);
+ player_node->setAttributeEffective(skillId, level);
+ skillDialog->setModifiable(skillId, up);
}
- skillDialog->update();
break;
case SMSG_SKILL_FAILED:
// Action failed (ex. sit because you have not reached the
// right level)
- short skill = msg.readInt16();
+ skillId = msg.readInt16();
short bskill = msg.readInt16();
msg.readInt16(); // unknown
char success = msg.readInt8();
@@ -131,7 +139,7 @@ void SkillHandler::handleMessage(MessageIn &msg)
}
std::string msg;
- if (success == SKILL_FAILED && skill == SKILL_BASIC)
+ if (success == SKILL_FAILED && skillId == SKILL_BASIC)
{
switch (bskill)
{
@@ -196,7 +204,7 @@ void SkillHandler::handleMessage(MessageIn &msg)
}
else
{
- switch (skill)
+ switch (skillId)
{
case SKILL_WARP :
msg = _("Warp failed...");
@@ -215,28 +223,33 @@ void SkillHandler::handleMessage(MessageIn &msg)
}
}
-void SkillHandler::up(int skillId)
+void SpecialHandler::use(int id)
{
- if (player_node->mSkillPoint <= 0)
- return;
-
- MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST);
- outMsg.writeInt16(skillId);
+ // TODO
}
-void SkillHandler::use(int skillId, int level, int beingId)
+void SpecialHandler::use(int id, int level, int beingId)
{
- // TODO
+ MessageOut outMsg(CMSG_SKILL_USE_BEING);
+ outMsg.writeInt16(level);
+ outMsg.writeInt16(id);
+ outMsg.writeInt16(beingId);
}
-void SkillHandler::use(int skillId, int level, int x, int y)
+void SpecialHandler::use(int id, int level, int x, int y)
{
- // TODO
+ MessageOut outMsg(CMSG_SKILL_USE_POSITION);
+ outMsg.writeInt16(level);
+ outMsg.writeInt16(id);
+ outMsg.writeInt16(x);
+ outMsg.writeInt16(y);
}
-void SkillHandler::use(int skillId, const std::string &map)
+void SpecialHandler::use(int id, const std::string &map)
{
- // TODO
+ MessageOut outMsg(CMSG_SKILL_USE_MAP);
+ outMsg.writeInt16(id);
+ outMsg.writeString(map, 16);
}
} // namespace EAthena
diff --git a/src/net/ea/skillhandler.h b/src/net/ea/specialhandler.h
index c1965213..eac53569 100644
--- a/src/net/ea/skillhandler.h
+++ b/src/net/ea/specialhandler.h
@@ -24,24 +24,24 @@
#include "net/messagehandler.h"
#include "net/net.h"
-#include "net/skillhandler.h"
+#include "net/specialhandler.h"
namespace EAthena {
-class SkillHandler : public MessageHandler, public Net::SkillHandler
+class SpecialHandler : public MessageHandler, public Net::SpecialHandler
{
public:
- SkillHandler();
+ SpecialHandler();
void handleMessage(MessageIn &msg);
- void up(int skillId);
+ void use(int id);
- void use(int skillId, int level, int beingId);
+ void use(int id, int level, int beingId);
- void use(int skillId, int level, int x, int y);
+ void use(int id, int level, int x, int y);
- void use(int skillId, const std::string &map);
+ void use(int id, const std::string &map);
};
} // namespace EAthena