summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/beinghandler.cpp104
-rw-r--r--src/net/beinghandler.h2
-rw-r--r--src/net/buysellhandler.cpp5
-rw-r--r--src/net/charserverhandler.cpp19
-rw-r--r--src/net/chathandler.cpp3
-rw-r--r--src/net/equipmenthandler.cpp44
-rw-r--r--src/net/inventoryhandler.cpp126
-rw-r--r--src/net/itemhandler.cpp1
-rw-r--r--src/net/loginhandler.cpp5
-rw-r--r--src/net/loginhandler.h2
-rw-r--r--src/net/maploginhandler.cpp1
-rw-r--r--src/net/messagehandler.cpp3
-rw-r--r--src/net/messagein.cpp5
-rw-r--r--src/net/messagein.h2
-rw-r--r--src/net/messageout.cpp5
-rw-r--r--src/net/network.cpp5
-rw-r--r--src/net/npchandler.cpp11
-rw-r--r--src/net/partyhandler.cpp124
-rw-r--r--src/net/partyhandler.h39
-rw-r--r--src/net/playerhandler.cpp79
-rw-r--r--src/net/protocol.h43
-rw-r--r--src/net/skillhandler.cpp3
-rw-r--r--src/net/tradehandler.cpp13
23 files changed, 470 insertions, 174 deletions
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index 086b4280..3c022af6 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -19,24 +19,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "beinghandler.h"
-
+#include <iostream>
#include <SDL_types.h>
+#include "beinghandler.h"
#include "messagein.h"
#include "protocol.h"
#include "../being.h"
#include "../beingmanager.h"
+#include "../effectmanager.h"
#include "../game.h"
#include "../localplayer.h"
#include "../log.h"
#include "../main.h"
+#include "../npc.h"
#include "../particle.h"
-#include "../sound.h"
-#include <iostream>
#include "../player_relations.h"
-#include "../npc.h"
+#include "../sound.h"
const int EMOTION_TIME = 150; /**< Duration of emotion icon */
@@ -72,6 +72,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
Uint16 headTop, headMid, headBottom;
Uint16 shoes, gloves, cape, misc1, misc2;
Uint16 weapon, shield;
+ Uint16 gmstatus;
Sint16 param1;
Sint8 type;
Being *srcBeing, *dstBeing;
@@ -128,8 +129,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
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
+ shoes = msg->readInt16();
+ gloves = msg->readInt16();
msg->readInt16(); // guild
msg->readInt16(); // unknown
msg->readInt16(); // unknown
@@ -201,22 +202,17 @@ void BeingHandler::handleMessage(MessageIn *msg)
if (!dstBeing)
break;
+ // If this is player's current target, clear it.
if (dstBeing == player_node->getTarget())
- {
player_node->stopAttack();
- }
if (dstBeing == current_npc)
current_npc = NULL;
if (msg->readInt8() == 1)
- {
dstBeing->setAction(Being::DEAD);
- }
else
- {
beingManager->destroyBeing(dstBeing);
- }
break;
@@ -234,28 +230,26 @@ void BeingHandler::handleMessage(MessageIn *msg)
switch (type)
{
case 0x0a: // Critical Damage
- if (dstBeing) {
- dstBeing->controlParticle(particleEngine->addEffect(
- "graphics/particles/crit.particle.xml", 0, 0));
- }
+ if (dstBeing)
+ dstBeing->showCrit();
case 0x00: // Damage
- if (dstBeing) {
+ if (dstBeing)
dstBeing->takeDamage(param1);
- }
- if (srcBeing) {
+ if (srcBeing)
srcBeing->handleAttack(dstBeing, param1);
- }
break;
case 0x02: // Sit
- if (srcBeing) {
+ if (srcBeing)
+ {
srcBeing->mFrame = 0;
srcBeing->setAction(Being::SIT);
}
break;
case 0x03: // Stand up
- if (srcBeing) {
+ if (srcBeing)
+ {
srcBeing->mFrame = 0;
srcBeing->setAction(Being::STAND);
}
@@ -269,8 +263,10 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
int effectType = msg->readInt32();
+ Being* being = beingManager->findBeing(id);
- beingManager->findBeing(id)->triggerEffect(effectType);
+ effectManager->trigger(effectType, (int) being->getPixelX(),
+ (int) being->getPixelY());
break;
}
@@ -403,8 +399,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
headTop = msg->readInt16();
headMid = msg->readInt16();
hairColor = msg->readInt16();
- msg->readInt16(); // clothes color - Aethyra-"abused" as shoes, we ignore it
- msg->readInt16(); // head dir - Aethyra-"abused" as gloves, we ignore it
+ shoes = msg->readInt16();
+ gloves = msg->readInt16();
msg->readInt32(); // guild
msg->readInt32(); // emblem
msg->readInt16(); // manner
@@ -417,6 +413,10 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom);
dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, headMid);
dstBeing->setSprite(Being::HAT_SPRITE, headTop);
+ dstBeing->setSprite(Being::SHOE_SPRITE, shoes);
+ // Compensation for the unpatched TMW server
+ if (gloves > 10)
+ dstBeing->setSprite(Being::GLOVES_SPRITE, gloves);
dstBeing->setSprite(Being::CAPE_SPRITE, cape);
dstBeing->setSprite(Being::MISC1_SPRITE, misc1);
dstBeing->setSprite(Being::MISC2_SPRITE, misc2);
@@ -437,18 +437,22 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setDirection(dir);
}
- msg->readInt16(); // GM status
+ gmstatus = msg->readInt16();
+ if (gmstatus & 0x80)
+ dstBeing->setGM();
if (msg->getId() == SMSG_PLAYER_UPDATE_1)
{
- switch (msg->readInt8()) {
-
- case 1: dstBeing->setAction(Being::DEAD);
- break;
-
- case 2: dstBeing->setAction(Being::SIT);
- break;
-
+ switch (msg->readInt8())
+ {
+ case 1:
+ if (dstBeing->getType() != Being::NPC)
+ dstBeing->setAction(Being::DEAD);
+ break;
+
+ case 2:
+ dstBeing->setAction(Being::SIT);
+ break;
}
}
else if (msg->getId() == SMSG_PLAYER_MOVE)
@@ -465,16 +469,16 @@ void BeingHandler::handleMessage(MessageIn *msg)
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.
- */
+ * 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()) {
@@ -492,11 +496,11 @@ void BeingHandler::handleMessage(MessageIn *msg)
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...
- */
+ * This is an *advisory* message, telling the client that
+ * it needs to move the character before attacking
+ * a target (out of range, obstruction in line of fire).
+ * We can safely ignore this...
+ */
break;
case 0x0119:
diff --git a/src/net/beinghandler.h b/src/net/beinghandler.h
index 5e22a670..9e736751 100644
--- a/src/net/beinghandler.h
+++ b/src/net/beinghandler.h
@@ -27,7 +27,7 @@
class BeingHandler : public MessageHandler
{
public:
- BeingHandler(bool);
+ BeingHandler(bool enableSync);
void handleMessage(MessageIn *msg);
diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp
index 16cfdc06..b2fe99b9 100644
--- a/src/net/buysellhandler.cpp
+++ b/src/net/buysellhandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "buysellhandler.h"
-
#include <SDL_types.h>
+#include "buysellhandler.h"
#include "messagein.h"
#include "protocol.h"
@@ -37,8 +36,8 @@
#include "../gui/sell.h"
extern BuyDialog *buyDialog;
-extern SellDialog *sellDialog;
extern Window *buySellDialog;
+extern SellDialog *sellDialog;
BuySellHandler::BuySellHandler()
{
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
index 9fb67ea5..281923f8 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/charserverhandler.cpp
@@ -20,19 +20,24 @@
*/
#include "charserverhandler.h"
-
#include "messagein.h"
#include "network.h"
#include "protocol.h"
+#include "../extensions.h"
#include "../game.h"
#include "../localplayer.h"
#include "../log.h"
#include "../logindata.h"
#include "../main.h"
-#include "../gui/ok_dialog.h"
#include "../gui/char_select.h"
+#include "../gui/ok_dialog.h"
+
+/*
+ * Yeah, this is a global. Get over it.
+ */
+struct EXTENSIONS extensions;
CharServerHandler::CharServerHandler():
mCharCreateDialog(0)
@@ -54,6 +59,7 @@ CharServerHandler::CharServerHandler():
void CharServerHandler::handleMessage(MessageIn *msg)
{
int slot;
+ int flags;
LocalPlayer *tempPlayer;
logger->log("CharServerHandler: Packet ID: %x, Length: %d",
@@ -61,8 +67,13 @@ void CharServerHandler::handleMessage(MessageIn *msg)
switch (msg->getId())
{
case 0x006b:
- // Skip length word and an additional mysterious 20 bytes
- msg->skip(2 + 20);
+ msg->skip(2); // Length word
+ flags = msg->readInt32(); // Aethyra extensions flags
+ logger->log("Server flags are: %x", flags);
+ extensions.aethyra_inventory = (bool)(flags & 0x01);
+ extensions.aethyra_spells = (bool)(flags & 0x02);
+ extensions.aethyra_misc = (bool)(flags & 0x04);
+ msg->skip(16); // Unused
// Derive number of characters from message length
n_character = (msg->getLength() - 24) / 106;
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
index d852798d..b73b86b4 100644
--- a/src/net/chathandler.cpp
+++ b/src/net/chathandler.cpp
@@ -19,11 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "chathandler.h"
-
#include <SDL_types.h>
#include <string>
+#include "chathandler.h"
#include "messagein.h"
#include "protocol.h"
diff --git a/src/net/equipmenthandler.cpp b/src/net/equipmenthandler.cpp
index 580cef6b..2e0cc562 100644
--- a/src/net/equipmenthandler.cpp
+++ b/src/net/equipmenthandler.cpp
@@ -20,7 +20,6 @@
*/
#include "equipmenthandler.h"
-
#include "messagein.h"
#include "protocol.h"
@@ -107,7 +106,10 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
}
- // Unequip any existing equipped item in this position
+ /*
+ * 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)) {
@@ -115,7 +117,10 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
position++;
}
logger->log("Position %i", position);
- item = player_node->getInventory()->getItem(player_node->mEquipment->getEquipment(position));
+
+ item = player_node->getInventory()->getItem(player_node->mEquipment->getEquipment(position));
+
+ // Unequip any existing equipped item in this position
if (item) {
item->setEquipped(false);
}
@@ -152,24 +157,11 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
item->setEquipped(false);
- switch (item->getId()) {
- case 529:
- case 1199:
- player_node->mEquipment->setArrows(0);
- break;
- case 521:
- case 522:
- case 530:
- case 536:
- case 1200:
- case 1201:
- player_node->setSprite(Being::WEAPON_SPRITE, 0);
- // TODO: Why this break? Shouldn't a weapon be
- // unequipped in inventory too?
- break;
- default:
- player_node->mEquipment->removeEquipment(position);
- break;
+ if (equipPoint & 0x8000) { // Arrows
+ player_node->mEquipment->setArrows(0);
+ }
+ else {
+ player_node->mEquipment->removeEquipment(position);
}
logger->log("Unequipping: %i %i(%i) %i",
index, equipPoint, type, position);
@@ -186,12 +178,12 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
item = inventory->getItem(index);
- if (!item)
- break;
- item->setEquipped(true);
- player_node->mEquipment->setArrows(index);
- logger->log("Arrows equipped: %i", index);
+ if (item) {
+ item->setEquipped(true);
+ player_node->mEquipment->setArrows(index);
+ logger->log("Arrows equipped: %i", index);
+ }
break;
}
}
diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp
index 9ddbd62f..12b7d5ef 100644
--- a/src/net/inventoryhandler.cpp
+++ b/src/net/inventoryhandler.cpp
@@ -19,22 +19,22 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "inventoryhandler.h"
-
#include <SDL_types.h>
+#include "inventoryhandler.h"
#include "messagein.h"
#include "protocol.h"
-#include "../resources/iteminfo.h"
+#include "../inventory.h"
#include "../item.h"
#include "../itemshortcut.h"
#include "../localplayer.h"
#include "../log.h"
-#include "../inventory.h"
#include "../gui/chat.h"
+#include "../resources/iteminfo.h"
+
#include "../utils/tostring.h"
InventoryHandler::InventoryHandler()
@@ -45,6 +45,12 @@ InventoryHandler::InventoryHandler()
SMSG_PLAYER_INVENTORY_REMOVE,
SMSG_PLAYER_INVENTORY_USE,
SMSG_ITEM_USE_RESPONSE,
+ SMSG_PLAYER_STORAGE_ITEMS,
+ SMSG_PLAYER_STORAGE_EQUIP,
+ SMSG_PLAYER_STORAGE_STATUS,
+ SMSG_PLAYER_STORAGE_ADD,
+ SMSG_PLAYER_STORAGE_REMOVE,
+ SMSG_PLAYER_STORAGE_CLOSE,
0
};
handledMessages = _messages;
@@ -53,35 +59,69 @@ InventoryHandler::InventoryHandler()
void InventoryHandler::handleMessage(MessageIn *msg)
{
Sint32 number;
- Sint16 index, amount, itemId, equipType;
+ Sint16 index, amount, itemId, equipType, arrow;
+ Sint16 identified, cards[4], itemType;
Inventory *inventory = player_node->getInventory();
+ Inventory *storage = player_node->getStorage();
switch (msg->getId())
{
case SMSG_PLAYER_INVENTORY:
- // Only called on map load / warp. First reset all items
- // to not load them twice on map change.
- inventory->clear();
+ case SMSG_PLAYER_STORAGE_ITEMS:
+ case SMSG_PLAYER_STORAGE_EQUIP:
+ switch (msg->getId()) {
+ case SMSG_PLAYER_INVENTORY:
+ // Clear inventory - this will be a complete refresh
+ inventory->clear();
+ break;
+ case SMSG_PLAYER_STORAGE_ITEMS:
+ /*
+ * This packet will always be followed by a
+ * SMSG_PLAYER_STORAGE_EQUIP packet. The two packets
+ * together comprise a complete refresh of storage, so
+ * clear storage here
+ */
+ storage->clear();
+ logger->log("Received SMSG_PLAYER_STORAGE_ITEMS");
+ break;
+ default:
+ logger->log("Received SMSG_PLAYER_STORAGE_EQUIP");
+ break;
+ }
msg->readInt16(); // length
number = (msg->getLength() - 4) / 18;
- for (int loop = 0; loop < number; loop++)
- {
+ for (int loop = 0; loop < number; loop++) {
index = msg->readInt16();
itemId = msg->readInt16();
- msg->readInt8(); // type
- msg->readInt8(); // identify flag
- amount = msg->readInt16();
- msg->skip(2); // unknown
- msg->skip(8); // card (4 shorts)
-
- inventory->setItem(index, itemId, amount, false);
-
- // Trick because arrows are not considered equipment
- if (itemId == 1199 || itemId == 529)
- {
- if (Item *item = inventory->getItem(index))
- item->setEquipment(true);
+ itemType = msg->readInt8();
+ identified = msg->readInt8();
+ if (msg->getId() == SMSG_PLAYER_STORAGE_EQUIP) {
+ amount = 1;
+ msg->readInt16(); // Equip Point?
+ } else {
+ amount = msg->readInt16();
+ }
+ arrow = msg->readInt16();
+ if (msg->getId() == SMSG_PLAYER_STORAGE_EQUIP) {
+ msg->readInt8(); // Attribute (broken)
+ msg->readInt8(); // Refine level
+ }
+ for (int i = 0; i < 4; i++)
+ cards[i] = msg->readInt16();
+
+ if (msg->getId() == SMSG_PLAYER_INVENTORY) {
+ inventory->setItem(index, itemId, amount, false);
+
+ // Trick because arrows are not considered equipment
+ if (arrow & 0x8000) {
+ if (Item *item = inventory->getItem(index))
+ item->setEquipment(true);
+ }
+ } else {
+ logger->log("Index:%d, ID:%d, Type:%d, Identified:%d, Qty:%d, Cards:%d, %d, %d, %d",
+ index, itemId, itemType, identified, amount, cards[0], cards[1], cards[2], cards[3]);
+ storage->setItem(index, itemId, amount, false);
}
}
break;
@@ -90,12 +130,13 @@ void InventoryHandler::handleMessage(MessageIn *msg)
index = msg->readInt16();
amount = msg->readInt16();
itemId = msg->readInt16();
- msg->readInt8(); // identify flag
+ identified = msg->readInt8();
msg->readInt8(); // attribute
msg->readInt8(); // refine
- msg->skip(8); // card
+ for (int i = 0; i < 4; i++)
+ cards[i] = msg->readInt16();
equipType = msg->readInt16();
- msg->readInt8(); // type
+ itemType = msg->readInt8();
if (msg->readInt8() > 0) {
chatWindow->chatLog("Unable to pick up item", BY_SERVER);
@@ -147,5 +188,38 @@ void InventoryHandler::handleMessage(MessageIn *msg)
item->setQuantity(amount);
}
break;
+
+ case SMSG_PLAYER_STORAGE_STATUS:
+ /*
+ * Basic slots used vs total slots info
+ * We don't really need this information, but this is
+ * the closest we get to an "Open Storage" packet
+ * from the server. It always comes after the two
+ * SMSG_PLAYER_STORAGE_... packets that update
+ * storage contents.
+ */
+ logger->log("Received SMSG_PLAYER_STORAGE_STATUS");
+ player_node->setInStorage(true);
+ break;
+
+ case SMSG_PLAYER_STORAGE_ADD:
+ /*
+ * Move an item into storage
+ */
+ break;
+
+ case SMSG_PLAYER_STORAGE_REMOVE:
+ /*
+ * Move an item out of storage
+ */
+ break;
+
+ case SMSG_PLAYER_STORAGE_CLOSE:
+ /*
+ * Storage access has been closed
+ */
+ player_node->setInStorage(false);
+ logger->log("Received SMSG_PLAYER_STORAGE_CLOSE");
+ break;
}
}
diff --git a/src/net/itemhandler.cpp b/src/net/itemhandler.cpp
index 487b98bf..9cf85ce7 100644
--- a/src/net/itemhandler.cpp
+++ b/src/net/itemhandler.cpp
@@ -20,7 +20,6 @@
*/
#include "itemhandler.h"
-
#include "messagein.h"
#include "protocol.h"
diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp
index 169503da..2b98e4e4 100644
--- a/src/net/loginhandler.cpp
+++ b/src/net/loginhandler.cpp
@@ -20,7 +20,6 @@
*/
#include "loginhandler.h"
-
#include "messagein.h"
#include "network.h"
#include "protocol.h"
@@ -35,7 +34,7 @@ extern SERVER_INFO **server_info;
LoginHandler::LoginHandler()
{
static const Uint16 _messages[] = {
- SMSG_UPDATE_HOST,
+ 0x0063,
0x0069,
0x006a,
0
@@ -87,7 +86,7 @@ void LoginHandler::handleMessage(MessageIn *msg)
iptostring(server_info[i]->address),
server_info[i]->port);
}
- state = CHAR_SERVER_STATE;
+ state = CHAR_SERVER_STATE;
break;
case 0x006a:
diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h
index 8a952cd5..047434b4 100644
--- a/src/net/loginhandler.h
+++ b/src/net/loginhandler.h
@@ -22,6 +22,8 @@
#ifndef _TMW_NET_LOGINHANDLER_H
#define _TMW_NET_LOGINHANDLER_H
+#include <string>
+
#include "messagehandler.h"
#include <string>
diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp
index b1000c12..bc08d5d6 100644
--- a/src/net/maploginhandler.cpp
+++ b/src/net/maploginhandler.cpp
@@ -20,7 +20,6 @@
*/
#include "maploginhandler.h"
-
#include "messagein.h"
#include "protocol.h"
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
index 29e34a29..7a41e1ad 100644
--- a/src/net/messagehandler.cpp
+++ b/src/net/messagehandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "messagehandler.h"
-
#include <cassert>
+#include "messagehandler.h"
#include "network.h"
MessageHandler::MessageHandler():
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
index 8e31fded..345e02fc 100644
--- a/src/net/messagein.cpp
+++ b/src/net/messagein.cpp
@@ -19,17 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "messagein.h"
-
#include <cassert>
#include <SDL.h>
#include <SDL_endian.h>
+#include "messagein.h"
+
#define MAKEWORD(low,high) \
((unsigned short)(((unsigned char)(low)) | \
((unsigned short)((unsigned char)(high))) << 8))
-
MessageIn::MessageIn(const char *data, unsigned int length):
mData(data),
mLength(length),
diff --git a/src/net/messagein.h b/src/net/messagein.h
index da80df9e..81db6cdc 100644
--- a/src/net/messagein.h
+++ b/src/net/messagein.h
@@ -22,8 +22,8 @@
#ifndef _TMW_MESSAGEIN_
#define _TMW_MESSAGEIN_
-#include <string>
#include <SDL_types.h>
+#include <string>
/**
* Used for parsing an incoming message.
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
index 96678f19..6aa25411 100644
--- a/src/net/messageout.cpp
+++ b/src/net/messageout.cpp
@@ -20,13 +20,12 @@
*/
#include <cstring>
-#include <string>
#include <SDL.h>
#include <SDL_endian.h>
-
-#include "network.h"
+#include <string>
#include "messageout.h"
+#include "network.h"
MessageOut::MessageOut(Network *network):
mNetwork(network),
diff --git a/src/net/network.cpp b/src/net/network.cpp
index e8b5e949..c9f8d1bd 100644
--- a/src/net/network.cpp
+++ b/src/net/network.cpp
@@ -19,15 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "network.h"
+#include <sstream>
#include "messagehandler.h"
#include "messagein.h"
+#include "network.h"
#include "../log.h"
-#include <sstream>
-
/** Warning: buffers and other variables are shared,
so there can be only one connection active at a time */
diff --git a/src/net/npchandler.cpp b/src/net/npchandler.cpp
index b633835c..4f3c4354 100644
--- a/src/net/npchandler.cpp
+++ b/src/net/npchandler.cpp
@@ -19,16 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npchandler.h"
-
#include "messagein.h"
+#include "npchandler.h"
#include "protocol.h"
#include "../beingmanager.h"
+#include "../localplayer.h"
#include "../npc.h"
-#include "../gui/npclistdialog.h"
#include "../gui/npc_text.h"
+#include "../gui/npclistdialog.h"
extern NpcListDialog *npcListDialog;
extern NpcTextDialog *npcTextDialog;
@@ -54,6 +54,7 @@ void NPCHandler::handleMessage(MessageIn *msg)
case SMSG_NPC_CHOICE:
msg->readInt16(); // length
id = msg->readInt32();
+ player_node->setAction(LocalPlayer::STAND);
current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
npcListDialog->parseItems(msg->readString(msg->getLength() - 8));
npcListDialog->setVisible(true);
@@ -62,15 +63,15 @@ void NPCHandler::handleMessage(MessageIn *msg)
case SMSG_NPC_MESSAGE:
msg->readInt16(); // length
id = msg->readInt32();
+ player_node->setAction(LocalPlayer::STAND);
current_npc = dynamic_cast<NPC*>(beingManager->findBeing(id));
npcTextDialog->addText(msg->readString(msg->getLength() - 8));
npcListDialog->setVisible(false);
npcTextDialog->setVisible(true);
break;
- case SMSG_NPC_CLOSE:
+ case SMSG_NPC_CLOSE:
id = msg->readInt32();
- dynamic_cast<NPC*>(beingManager->findBeing(id));
if (current_npc == dynamic_cast<NPC*>(beingManager->findBeing(id)))
current_npc = NULL;
break;
diff --git a/src/net/partyhandler.cpp b/src/net/partyhandler.cpp
new file mode 100644
index 00000000..9b5f3080
--- /dev/null
+++ b/src/net/partyhandler.cpp
@@ -0,0 +1,124 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <guichan/actionlistener.hpp>
+
+#include "partyhandler.h"
+#include "protocol.h"
+#include "messagein.h"
+
+#include "../gui/chat.h"
+#include "../gui/confirm_dialog.h"
+
+#include "../beingmanager.h"
+#include "../game.h"
+#include "../party.h"
+
+PartyHandler::PartyHandler(Party *party) : mParty(party)
+{
+ static const Uint16 _messages[] = {
+ SMSG_PARTY_CREATE,
+ SMSG_PARTY_INFO,
+ SMSG_PARTY_INVITE,
+ SMSG_PARTY_INVITED,
+ SMSG_PARTY_SETTINGS,
+ SMSG_PARTY_MEMBER_INFO,
+ SMSG_PARTY_LEAVE,
+ SMSG_PARTY_UPDATE_HP,
+ SMSG_PARTY_UPDATE_COORDS,
+ SMSG_PARTY_MESSAGE,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void
+PartyHandler::handleMessage(MessageIn *msg)
+{
+ switch (msg->getId())
+ {
+ case SMSG_PARTY_CREATE:
+ mParty->createResponse(msg->readInt8());
+ break;
+ case SMSG_PARTY_INFO:
+ break;
+ case SMSG_PARTY_INVITE:
+ {
+ std::string nick = msg->readString(24);
+ int status = msg->readInt8();
+ mParty->inviteResponse(nick, status);
+ break;
+ }
+ case SMSG_PARTY_INVITED:
+ {
+ int id = msg->readInt32();
+ Being *being = beingManager->findBeing(id);
+ if (being == NULL)
+ {
+ break;
+ }
+ std::string nick;
+ int gender = 0;
+ std::string partyName = "";
+ if (being->getType() != Being::PLAYER)
+ {
+ nick = "";
+ }
+ else
+ {
+ nick = being->getName();
+ gender = being->getGender();
+ partyName = msg->readString(24);
+ }
+ mParty->invitedAsk(nick, gender, partyName);
+ break;
+ }
+ case SMSG_PARTY_SETTINGS:
+ break;
+ case SMSG_PARTY_MEMBER_INFO:
+ break;
+ case SMSG_PARTY_LEAVE:
+ {
+ /*int id = */msg->readInt32();
+ std::string nick = msg->readString(24);
+ /*int fail = */msg->readInt8();
+ mParty->leftResponse(nick);
+ break;
+ }
+ case SMSG_PARTY_UPDATE_HP:
+ break;
+ case SMSG_PARTY_UPDATE_COORDS:
+ break;
+ case SMSG_PARTY_MESSAGE:
+ { // new block to enable local variables
+ int msgLength = msg->readInt16() - 8;
+ if (msgLength <= 0)
+ {
+ return;
+ }
+ int id = msg->readInt32();
+ Being *being = beingManager->findBeing(id);
+ std::string chatMsg = msg->readString(msgLength);
+ mParty->receiveChat(being, chatMsg);
+ }
+ break;
+ }
+}
diff --git a/src/net/partyhandler.h b/src/net/partyhandler.h
new file mode 100644
index 00000000..daabc52f
--- /dev/null
+++ b/src/net/partyhandler.h
@@ -0,0 +1,39 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TMW_NET_PARTYHANDLER_H
+#define _TMW_NET_PARTYHANDLER_H
+
+#include "messagehandler.h"
+
+class Party;
+
+class PartyHandler : public MessageHandler
+{
+ public:
+ PartyHandler(Party *party);
+
+ void handleMessage(MessageIn *msg);
+ private:
+ Party *mParty;
+};
+
+#endif
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index 50546b1e..a4a2dcc9 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -19,16 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "playerhandler.h"
-
#include "messagein.h"
+#include "playerhandler.h"
#include "protocol.h"
#include "../engine.h"
#include "../localplayer.h"
#include "../log.h"
#include "../npc.h"
-#include "../utils/tostring.h"
#include "../gui/buy.h"
#include "../gui/chat.h"
@@ -40,6 +38,8 @@
#include "../gui/skill.h"
#include "../gui/viewport.h"
+#include "../utils/tostring.h"
+
// TODO Move somewhere else
OkDialog *weightNotice = NULL;
OkDialog *deathNotice = NULL;
@@ -51,7 +51,7 @@ extern SellDialog *sellDialog;
extern Window *buySellDialog;
static const int MAP_TELEPORT_SCROLL_DISTANCE = 8; /* Max. distance we are willing to scroll after a teleport;
- ** everything beyond will reset the port hard. */
+ * everything beyond will reset the port hard. */
/**
* Listener used for handling the overweigth message.
@@ -110,10 +110,11 @@ void PlayerHandler::handleMessage(MessageIn *msg)
switch (msg->getId())
{
case SMSG_WALK_RESPONSE:
- // It is assumed by the client any request to walk actually
- // succeeds on the server. The plan is to have a correction
- // message when the server senses the client has the wrong
- // idea.
+ /*
+ * This client assumes that all walk messages succeed,
+ * and that the server will send a correction notice
+ * otherwise.
+ */
break;
case SMSG_PLAYER_WARP:
@@ -132,6 +133,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
player_node->stopAttack();
nearby = (engine->getCurrentMapName() == mapPath);
+
// Switch the actual map, deleting the previous one if necessary
engine->changeMap(mapPath);
@@ -143,7 +145,8 @@ 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(y - player_node->mY) > MAP_TELEPORT_SCROLL_DISTANCE))
+ {
scrollOffsetX = (x - player_node->mX) * 32;
scrollOffsetY = (y - player_node->mY) * 32;
}
@@ -173,6 +176,9 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case 0x0006: player_node->mMaxHp = value; break;
case 0x0007: player_node->mMp = value; break;
case 0x0008: player_node->mMaxMp = value; break;
+ case 0x0009:
+ player_node->mStatsPointsToAttribute = value;
+ break;
case 0x000b: player_node->mLevel = value; break;
case 0x000c:
player_node->mSkillPoint = value;
@@ -193,10 +199,6 @@ void PlayerHandler::handleMessage(MessageIn *msg)
player_node->mTotalWeight = value;
break;
case 0x0019: player_node->mMaxWeight = value; break;
- case 0x0037: player_node->mJobLevel = value; break;
- case 0x0009:
- player_node->mStatsPointsToAttribute = value;
- break;
case 0x0029: player_node->ATK = value; break;
case 0x002b: player_node->MATK = value; break;
case 0x002d: player_node->DEF = value; break;
@@ -205,12 +207,44 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case 0x0031: player_node->HIT = value; break;
case 0x0032: player_node->FLEE = value; break;
case 0x0035: player_node->mAttackSpeed = value; break;
+ case 0x0037: player_node->mJobLevel = value; break;
}
if (player_node->mHp == 0 && deathNotice == NULL)
{
- deathNotice = new OkDialog("Message",
- "You're now dead, press ok to restart");
+ static char const *const deadMsg[] =
+ {
+ "You are dead.",
+ "We regret to inform you that your character was killed in battle.",
+ "You are not that alive anymore.",
+ "The cold hands of the grim reaper are grabbing for your soul.",
+ "Game Over!",
+ "Insert coin to continue",
+ "No, kids. Your character did not really die. It... err... went to a better place.",
+ "Your plan of breaking your enemies weapon by bashing it with your throat failed.",
+ "I guess this did not run too well.",
+ "Do you want your possessions identified?", // Nethack reference
+ "Sadly, no trace of you was ever found...", // Secret of Mana reference
+ "Annihilated.", // Final Fantasy VI reference
+ "Looks like you got your head handed to you.", //Earthbound reference
+ "You screwed up again, dump your body down the tubes and get you another one.", // Leisure Suit Larry 1 Reference
+ "You're not dead yet. You're just resting.", // Monty Python reference from a couple of skits
+ "You are no more.", // Monty Python reference from the dead parrot sketch starting now
+ "You have ceased to be.",
+ "You've expired and gone to meet your maker.",
+ "You're a stiff.",
+ "Bereft of life, you rest in peace.",
+ "If you weren't so animated, you'd be pushing up the daisies.",
+ "Your metabolic processes are now history.",
+ "You're off the twig.",
+ "You've kicked the bucket.",
+ "You've shuffled off your mortal coil, run down the curtain and joined the bleedin' choir invisibile.",
+ "You are an ex-player.",
+ "You're pining for the fjords." // Monty Python reference from the dead parrot sketch
+ };
+ std::string message(deadMsg[rand()%27]);
+
+ deathNotice = new OkDialog("Message", message);
deathNotice->addActionListener(&deathListener);
player_node->setAction(Being::DEAD);
}
@@ -293,7 +327,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
}
break;
- // Updates stats and status points
+ // Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
player_node->mStatsPointsToAttribute = msg->readInt16();
player_node->mAttr[LocalPlayer::STR] = msg->readInt8();
@@ -361,18 +395,5 @@ void PlayerHandler::handleMessage(MessageIn *msg)
}
}
break;
-
- //Stop walking
- //case 0x0088: // Disabled because giving some problems
- //if (being = beingManager->findBeing(readInt32(2))) {
- // if (being->getId() != player_node->getId()) {
- // being->action = STAND;
- // being->mFrame = 0;
- // set_coordinates(being->coordinates,
- // readWord(6), readWord(8),
- // get_direction(being->coordinates));
- // }
- //}
- //break;
}
}
diff --git a/src/net/protocol.h b/src/net/protocol.h
index d7bdd041..783283ba 100644
--- a/src/net/protocol.h
+++ b/src/net/protocol.h
@@ -22,8 +22,11 @@
#ifndef _TMW_PROTOCOL_
#define _TMW_PROTOCOL_
-// Packets from server to client
+/*********************************
+ * Packets from server to client *
+ *********************************/
#define SMSG_LOGIN_SUCCESS 0x0073 /**< Contains starting location */
+#define SMSG_SERVER_PING 0x007f /**< Contains server tick */
#define SMSG_UPDATE_HOST 0x0063 /**< Custom update host packet */
#define SMSG_PLAYER_UPDATE_1 0x01d8
#define SMSG_PLAYER_UPDATE_2 0x01d9
@@ -66,6 +69,7 @@
#define SMSG_BEING_ACTION 0x008a /**< Attack, sit, stand up, ... */
#define SMSG_BEING_CHAT 0x008d /**< A being talks */
#define SMSG_BEING_NAME_RESPONSE 0x0095 /**< Has to be requested */
+
#define SMSG_NPC_MESSAGE 0x00b4
#define SMSG_NPC_NEXT 0x00b5
#define SMSG_NPC_CLOSE 0x00b6
@@ -75,11 +79,13 @@
#define SMSG_NPC_SELL 0x00c7
#define SMSG_NPC_BUY_RESPONSE 0x00ca
#define SMSG_NPC_SELL_RESPONSE 0x00cb
+
#define SMSG_PLAYER_CHAT 0x008e /**< Player talks */
#define SMSG_WHISPER 0x0097 /**< Whisper Recieved */
#define SMSG_WHISPER_RESPONSE 0x0098
#define SMSG_GM_CHAT 0x009a /**< GM announce */
#define SMSG_WALK_RESPONSE 0x0087
+
#define SMSG_TRADE_REQUEST 0x00e5 /**< Receiving a request to trade */
#define SMSG_TRADE_RESPONSE 0x00e7
#define SMSG_TRADE_ITEM_ADD 0x00e9
@@ -88,7 +94,27 @@
#define SMSG_TRADE_CANCEL 0x00ee
#define SMSG_TRADE_COMPLETE 0x00f0
-// Packets from client to server
+#define SMSG_PARTY_CREATE 0x00fa
+#define SMSG_PARTY_INFO 0x00fb
+#define SMSG_PARTY_INVITE 0x00fd
+#define SMSG_PARTY_INVITED 0x00fe
+#define SMSG_PARTY_SETTINGS 0x0102
+#define SMSG_PARTY_MEMBER_INFO 0x0104
+#define SMSG_PARTY_LEAVE 0x0105
+#define SMSG_PARTY_UPDATE_HP 0x0106
+#define SMSG_PARTY_UPDATE_COORDS 0x0107
+#define SMSG_PARTY_MESSAGE 0x0109
+
+#define SMSG_PLAYER_STORAGE_ITEMS 0x01f0 /**< Item list for storage */
+#define SMSG_PLAYER_STORAGE_EQUIP 0x00a6 /**< Equipment list for storage */
+#define SMSG_PLAYER_STORAGE_STATUS 0x00f2 /**< Slots used and total slots */
+#define SMSG_PLAYER_STORAGE_ADD 0x00f4 /**< Add item/equip to storage */
+#define SMSG_PLAYER_STORAGE_REMOVE 0x00f6 /**< Remove item/equip from storage */
+#define SMSG_PLAYER_STORAGE_CLOSE 0x00f8 /**< Storage access closed */
+
+/**********************************
+ * Packets from client to server *
+ **********************************/
#define CMSG_CLIENT_PING 0x007e /**< Send to server with tick */
#define CMSG_TRADE_RESPONSE 0x00e6
#define CMSG_ITEM_PICKUP 0x009f
@@ -97,6 +123,8 @@
#define CMSG_NPC_BUY_SELL_REQUEST 0x00c5
#define CMSG_CHAT_MESSAGE 0x008c
#define CMSG_CHAT_WHISPER 0x0096
+#define CMSG_CHAT_ANNOUNCE 0x0099
+#define CMSG_CHAT_WHO 0x00c1
#define CMSG_NPC_LIST_CHOICE 0x00b8
#define CMSG_NPC_NEXT_REQUEST 0x00b9
#define CMSG_NPC_SELL_REQUEST 0x00c9
@@ -113,6 +141,17 @@
#define CMSG_PLAYER_EQUIP 0x00a9
#define CMSG_PLAYER_UNEQUIP 0x00ab
+#define CMSG_PARTY_CREATE 0x00f9
+#define CMSG_PARTY_INVITE 0x00fc
+#define CMSG_PARTY_INVITED 0x00ff
+#define CMSG_PARTY_LEAVE 0x0100 /** Undocumented */
+#define CMSG_PARTY_SETTINGS 0x0101
+#define CMSG_PARTY_MESSAGE 0x0108
+
+#define CMSG_MOVE_TO_STORAGE 0x00f3 /** Move item to storage */
+#define CSMG_MOVE_FROM_STORAGE 0x00f5 /** Remove item from storage */
+#define CMSG_CLOSE_STORAGE 0x00f7 /** Request storage close */
+
/** Encodes coords and direction in 3 bytes data */
void set_coordinates(char *data, unsigned short x, unsigned short y, unsigned char direction);
diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp
index 2bb5d9dc..b9a232fb 100644
--- a/src/net/skillhandler.cpp
+++ b/src/net/skillhandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "skillhandler.h"
-
#include "messagein.h"
#include "protocol.h"
+#include "skillhandler.h"
#include "../log.h"
diff --git a/src/net/tradehandler.cpp b/src/net/tradehandler.cpp
index 955aeff1..746e1d06 100644
--- a/src/net/tradehandler.cpp
+++ b/src/net/tradehandler.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "tradehandler.h"
-
#include "messagein.h"
#include "protocol.h"
+#include "tradehandler.h"
#include "../inventory.h"
#include "../item.h"
@@ -188,11 +187,11 @@ void TradeHandler::handleMessage(MessageIn *msg)
BY_SERVER);
break;
case 2:
- // Add item failed - player has no free slot
- chatWindow->chatLog("Failed adding item. Trade "
- "partner has no free slot.",
- BY_SERVER);
- break;
+ // Add item failed - player has no free slot
+ chatWindow->chatLog("Failed adding item. Trade "
+ "partner has no free slot.",
+ BY_SERVER);
+ break;
default:
chatWindow->chatLog("Failed adding item for "
"unknown reason.", BY_SERVER);