00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "net/ea/inventoryhandler.h"
00023
00024 #include "net/ea/protocol.h"
00025
00026 #include "net/messagein.h"
00027 #include "net/messageout.h"
00028
00029 #include "configuration.h"
00030 #include "inventory.h"
00031 #include "item.h"
00032 #include "itemshortcut.h"
00033 #include "localplayer.h"
00034 #include "log.h"
00035
00036 #include "gui/storagewindow.h"
00037
00038 #include "gui/widgets/chattab.h"
00039
00040 #include "resources/iteminfo.h"
00041
00042 #include "utils/gettext.h"
00043 #include "utils/strprintf.h"
00044 #include "utils/stringutils.h"
00045
00046 #include <SDL_types.h>
00047
00048 Net::InventoryHandler *inventoryHandler;
00049
00050 namespace EAthena {
00051
00052 enum { debugInventory = 1 };
00053
00054 InventoryHandler::InventoryHandler()
00055 {
00056 static const Uint16 _messages[] = {
00057 SMSG_PLAYER_INVENTORY,
00058 SMSG_PLAYER_INVENTORY_ADD,
00059 SMSG_PLAYER_INVENTORY_REMOVE,
00060 SMSG_PLAYER_INVENTORY_USE,
00061 SMSG_ITEM_USE_RESPONSE,
00062 SMSG_PLAYER_STORAGE_ITEMS,
00063 SMSG_PLAYER_STORAGE_EQUIP,
00064 SMSG_PLAYER_STORAGE_STATUS,
00065 SMSG_PLAYER_STORAGE_ADD,
00066 SMSG_PLAYER_STORAGE_REMOVE,
00067 SMSG_PLAYER_STORAGE_CLOSE,
00068 0
00069 };
00070 handledMessages = _messages;
00071 inventoryHandler = this;
00072 }
00073
00074 void InventoryHandler::handleMessage(MessageIn &msg)
00075 {
00076 int number;
00077 int index, amount, itemId, equipType, arrow;
00078 int identified, cards[4], itemType;
00079 Inventory *inventory = player_node->getInventory();
00080 Inventory *storage = player_node->getStorage();
00081
00082 switch (msg.getId())
00083 {
00084 case SMSG_PLAYER_INVENTORY:
00085 case SMSG_PLAYER_STORAGE_ITEMS:
00086 if (msg.getId() == SMSG_PLAYER_INVENTORY)
00087 {
00088
00089 inventory->clear();
00090 }
00091 else
00092 {
00093
00094
00095
00096
00097
00098
00099 storage->clear();
00100 }
00101 msg.readInt16();
00102 number = (msg.getLength() - 4) / 18;
00103
00104 for (int loop = 0; loop < number; loop++)
00105 {
00106 index = msg.readInt16();
00107 itemId = msg.readInt16();
00108 itemType = msg.readInt8();
00109 identified = msg.readInt8();
00110 amount = msg.readInt16();
00111 arrow = msg.readInt16();
00112 for (int i = 0; i < 4; i++)
00113 cards[i] = msg.readInt16();
00114
00115 index -= (msg.getId() == SMSG_PLAYER_INVENTORY) ?
00116 INVENTORY_OFFSET : STORAGE_OFFSET;
00117
00118 if (debugInventory)
00119 {
00120 logger->log("Index: %d, ID: %d, Type: %d, Identified: %d, "
00121 "Qty: %d, Cards: %d, %d, %d, %d",
00122 index, itemId, itemType, identified, amount,
00123 cards[0], cards[1], cards[2], cards[3]);
00124 }
00125
00126 if (msg.getId() == SMSG_PLAYER_INVENTORY) {
00127 inventory->setItem(index, itemId, amount, false);
00128
00129
00130 if (arrow & 0x8000) {
00131 if (Item *item = inventory->getItem(index))
00132 item->setEquipment(true);
00133 }
00134 } else {
00135 storage->setItem(index, itemId, amount, false);
00136 }
00137 }
00138 break;
00139
00140 case SMSG_PLAYER_STORAGE_EQUIP:
00141 msg.readInt16();
00142 number = (msg.getLength() - 4) / 20;
00143
00144 for (int loop = 0; loop < number; loop++) {
00145 index = msg.readInt16() - STORAGE_OFFSET;
00146 itemId = msg.readInt16();
00147 itemType = msg.readInt8();
00148 identified = msg.readInt8();
00149 amount = 1;
00150 msg.readInt16();
00151 msg.readInt16();
00152 msg.readInt8();
00153 msg.readInt8();
00154 for (int i = 0; i < 4; i++)
00155 cards[i] = msg.readInt16();
00156
00157 if (debugInventory)
00158 {
00159 logger->log("Index: %d, ID: %d, Type: %d, Identified: %d, "
00160 "Qty: %d, Cards: %d, %d, %d, %d",
00161 index, itemId, itemType, identified, amount,
00162 cards[0], cards[1], cards[2], cards[3]);
00163 }
00164
00165 storage->setItem(index, itemId, amount, false);
00166 }
00167 break;
00168
00169 case SMSG_PLAYER_INVENTORY_ADD:
00170 index = msg.readInt16() - INVENTORY_OFFSET;
00171 amount = msg.readInt16();
00172 itemId = msg.readInt16();
00173 identified = msg.readInt8();
00174 msg.readInt8();
00175 msg.readInt8();
00176 for (int i = 0; i < 4; i++)
00177 cards[i] = msg.readInt16();
00178 equipType = msg.readInt16();
00179 itemType = msg.readInt8();
00180
00181 if (msg.readInt8() > 0)
00182 {
00183 if (config.getValue("showpickupchat", 1))
00184 localChatTab->chatLog(_("Unable to pick up item"), BY_SERVER);
00185 }
00186 else
00187 {
00188 const ItemInfo &itemInfo = ItemDB::get(itemId);
00189 const std::string amountStr =
00190 (amount > 1) ? toString(amount) : "a";
00191
00192 if (config.getValue("showpickupchat", 1))
00193 {
00194 localChatTab->chatLog(strprintf(_("You picked up %s [%s]"),
00195 amountStr.c_str(), itemInfo.getName().c_str()),
00196 BY_SERVER);
00197 }
00198
00199 if (config.getValue("showpickupparticle", 0))
00200 {
00201 player_node->pickedUp(itemInfo.getName());
00202 }
00203
00204 if (Item *item = inventory->getItem(index)) {
00205 item->setId(itemId);
00206 item->increaseQuantity(amount);
00207 } else {
00208 inventory->setItem(index, itemId, amount, equipType != 0);
00209 }
00210 }
00211 break;
00212
00213 case SMSG_PLAYER_INVENTORY_REMOVE:
00214 index = msg.readInt16() - INVENTORY_OFFSET;
00215 amount = msg.readInt16();
00216 if (Item *item = inventory->getItem(index))
00217 {
00218 item->increaseQuantity(-amount);
00219 if (item->getQuantity() == 0)
00220 inventory->removeItemAt(index);
00221 }
00222 break;
00223
00224 case SMSG_PLAYER_INVENTORY_USE:
00225 index = msg.readInt16() - INVENTORY_OFFSET;
00226 msg.readInt16();
00227 msg.readInt32();
00228 amount = msg.readInt16();
00229 msg.readInt8();
00230
00231 if (Item *item = inventory->getItem(index))
00232 item->setQuantity(amount);
00233 break;
00234
00235 case SMSG_ITEM_USE_RESPONSE:
00236 index = msg.readInt16() - INVENTORY_OFFSET;
00237 amount = msg.readInt16();
00238
00239 if (msg.readInt8() == 0) {
00240 localChatTab->chatLog(_("Failed to use item"), BY_SERVER);
00241 } else {
00242 if (Item *item = inventory->getItem(index))
00243 item->setQuantity(amount);
00244 }
00245 break;
00246
00247 case SMSG_PLAYER_STORAGE_STATUS:
00248
00249
00250
00251
00252
00253 player_node->setInStorage(true);
00254 msg.readInt16();
00255 msg.readInt16();
00256 break;
00257
00258 case SMSG_PLAYER_STORAGE_ADD:
00259
00260
00261
00262 index = msg.readInt16() - STORAGE_OFFSET;
00263 amount = msg.readInt32();
00264 itemId = msg.readInt16();
00265 identified = msg.readInt8();
00266 msg.readInt8();
00267 msg.readInt8();
00268 for (int i = 0; i < 4; i++)
00269 cards[i] = msg.readInt16();
00270
00271 if (Item *item = storage->getItem(index))
00272 {
00273 item->setId(itemId);
00274 item->increaseQuantity(amount);
00275 }
00276 else
00277 {
00278 storage->setItem(index, itemId, amount, false);
00279 }
00280 break;
00281
00282 case SMSG_PLAYER_STORAGE_REMOVE:
00283
00284
00285
00286 index = msg.readInt16() - STORAGE_OFFSET;
00287 amount = msg.readInt16();
00288 if (Item *item = storage->getItem(index))
00289 {
00290 item->increaseQuantity(-amount);
00291 if (item->getQuantity() == 0)
00292 storage->removeItemAt(index);
00293 }
00294 break;
00295
00296 case SMSG_PLAYER_STORAGE_CLOSE:
00297
00298
00299
00300 player_node->setInStorage(false);
00301 break;
00302 }
00303 }
00304
00305 void InventoryHandler::equipItem(Item *item)
00306 {
00307 if (!item)
00308 return;
00309
00310 MessageOut outMsg(CMSG_PLAYER_EQUIP);
00311 outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET);
00312 outMsg.writeInt16(0);
00313 }
00314
00315 void InventoryHandler::unequipItem(Item *item)
00316 {
00317 if (!item)
00318 return;
00319
00320 MessageOut outMsg(CMSG_PLAYER_UNEQUIP);
00321 outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET);
00322 }
00323
00324 void InventoryHandler::useItem(Item *item)
00325 {
00326 if (!item)
00327 return;
00328
00329 MessageOut outMsg(CMSG_PLAYER_INVENTORY_USE);
00330 outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET);
00331 outMsg.writeInt32(item->getId());
00332 }
00333
00334 void InventoryHandler::dropItem(Item *item, int amount)
00335 {
00336
00337 MessageOut outMsg(CMSG_PLAYER_INVENTORY_DROP);
00338 outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET);
00339 outMsg.writeInt16(amount);
00340 }
00341
00342 void InventoryHandler::splitItem(Item *item, int amount)
00343 {
00344
00345 }
00346
00347 void InventoryHandler::openStorage()
00348 {
00349
00350 }
00351
00352 void InventoryHandler::closeStorage()
00353 {
00354 MessageOut outMsg(CMSG_CLOSE_STORAGE);
00355 }
00356
00357 void InventoryHandler::moveItem(StorageType source, int slot, int amount,
00358 StorageType destination)
00359 {
00360 if (source == INVENTORY && destination == STORAGE)
00361 {
00362 MessageOut outMsg(CMSG_MOVE_TO_STORAGE);
00363 outMsg.writeInt16(slot + INVENTORY_OFFSET);
00364 outMsg.writeInt32(amount);
00365 }
00366 else if (source == STORAGE && destination == INVENTORY)
00367 {
00368 MessageOut outMsg(CSMG_MOVE_FROM_STORAGE);
00369 outMsg.writeInt16(slot + STORAGE_OFFSET);
00370 outMsg.writeInt32(amount);
00371 }
00372 }
00373
00374 }