Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
ItemHandler.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Chat.h"
7#include "Common.h"
8#include "DB2Stores.h"
9#include "Item.h"
10#include "Log.h"
11#include "ObjectAccessor.h"
12#include "ObjectMgr.h"
13#include "Opcodes.h"
14#include "Player.h"
15#include "SpellInfo.h"
16#include "UpdateData.h"
17#include "WorldPacket.h"
18#include "WorldSession.h"
19#include <vector>
20
22{
23 //SF_LOG_DEBUG("network", "WORLD: CMSG_SPLIT_ITEM");
24 uint8 srcBag, srcSlot, dstBag, dstSlot;
25 uint32 count;
26
27 recvData >> srcBag;
28 recvData >> count;
29 recvData >> dstBag >> srcSlot >> dstSlot;
30 recvData.rfinish();
31
32 //SF_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count);
33
34 uint16 src = ((srcBag << 8) | srcSlot);
35 uint16 dst = ((dstBag << 8) | dstSlot);
36
37 if (src == dst)
38 return;
39
40 if (count == 0)
41 return; //check count - if zero it's fake packet
42
43 if (!_player->IsValidPos(srcBag, srcSlot, true))
44 {
45 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
46 return;
47 }
48
49 if (!_player->IsValidPos(dstBag, dstSlot, false)) // can be autostore pos
50 {
51 _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
52 return;
53 }
54
55 _player->SplitItem(src, dst, count);
56}
57
59{
60 //SF_LOG_DEBUG("network", "WORLD: CMSG_SWAP_INV_ITEM");
61 uint8 srcSlot, dstSlot;
62
63 recvData >> srcSlot >> dstSlot;
64 //SF_LOG_DEBUG("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
65
66 // prevent attempt swap same item to current position generated by client at special cheating sequence
67 if (srcSlot == dstSlot)
68 return;
69
70 if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, srcSlot, true))
71 {
72 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
73 return;
74 }
75
76 if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, dstSlot, true))
77 {
78 _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
79 return;
80 }
81
82 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcSlot);
83 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstSlot);
84
85 _player->SwapItem(src, dst);
86}
87
89{
90 uint8 slot = recvData.read<uint8>();
91 ObjectGuid itemGuid;
92 recvData.ReadGuidMask(itemGuid, 6, 3, 0);
93 uint32 length = recvData.ReadBits(2);
94 recvData.ReadGuidMask(itemGuid, 7);
95
96 struct Unk14
97 {
98 uint8 Unk0;
99 uint8 Unk1;
100 };
101
102 std::vector<Unk14> unk14;
103 for (uint32 i = 0; i < length; ++i)
104 {
105 Unk14 u;
106 u.Unk1 = recvData.ReadBit();
107 u.Unk0 = recvData.ReadBit();
108 unk14.push_back(u);
109 }
110 recvData.ReadGuidMask(itemGuid, 5, 2, 1, 4);
111 recvData.ReadGuidBytes(itemGuid, 6, 3, 1, 7, 2, 0, 4, 5);
112
113 for (auto&& itr : unk14)
114 {
115 if (itr.Unk1)
116 itr.Unk1 = recvData.read<uint8>();
117 if (itr.Unk0)
118 itr.Unk0 = recvData.read<uint8>();
119 }
120
121 Item* item = GetPlayer()->GetItemByGuid(itemGuid);
122 if (!item)
123 {
125 return;
126 }
127
128 if (slot >= EQUIPMENT_SLOT_END)
129 {
131 return;
132 }
133
134 uint16 dstpos = slot | (INVENTORY_SLOT_BAG_0 << 8);
135
136 if (item->GetPos() == dstpos)
137 return;
138
139 GetPlayer()->SwapItem(item->GetPos(), dstpos);
140}
141
143{
144 //SF_LOG_DEBUG("network", "WORLD: CMSG_SWAP_ITEM");
145 bool hasSlot[2];
146 bool hasBag[2];
147 uint8 dstBag, dstSlot, srcBag, srcSlot;
148 uint8 srcSlotAlt, srcBagAlt, dstSlotAlt, dstBagAlt;
149
150 recvData >> srcSlotAlt >> srcBagAlt >> dstBagAlt >> dstSlotAlt;
151
152 uint32 count = recvData.ReadBits(2);
153
154 if (count != 2)
155 return;
156
157 for (uint8 i = 0; i < count; i++)
158 {
159 hasSlot[i] = !recvData.ReadBit();
160 hasBag[i] = !recvData.ReadBit();
161 }
162
163 dstBag = hasBag[0] ? recvData.read<uint8>() : dstBagAlt;
164 dstSlot = hasSlot[0] ? recvData.read<uint8>() : dstSlotAlt;
165 srcBag = hasBag[1] ? recvData.read<uint8>() : srcBagAlt;
166 srcSlot = hasSlot[1] ? recvData.read<uint8>() : srcSlotAlt;
167
168 //SF_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot);
169
170 uint16 src = ((srcBag << 8) | srcSlot);
171 uint16 dst = ((dstBag << 8) | dstSlot);
172
173 // prevent attempt swap same item to current position generated by client at special checting sequence
174 if (src == dst)
175 return;
176
177 if (!_player->IsValidPos(srcBag, srcSlot, true))
178 {
179 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
180 return;
181 }
182
183 if (!_player->IsValidPos(dstBag, dstSlot, true))
184 {
185 _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
186 return;
187 }
188
189 _player->SwapItem(src, dst);
190}
191
193{
194 //SF_LOG_DEBUG("network", "WORLD: CMSG_AUTOEQUIP_ITEM");
195 uint8 srcbag, srcslot;
196
197 recvData >> srcslot >> srcbag;
198 recvData.rfinish();
199 //SF_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
200
201 Item* pSrcItem = _player->GetItemByPos(srcbag, srcslot);
202 if (!pSrcItem)
203 return; // only at cheat
204
205 uint16 dest;
206 InventoryResult msg = _player->CanEquipItem(NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag());
207 if (msg != EQUIP_ERR_OK)
208 {
209 _player->SendEquipError(msg, pSrcItem, NULL);
210 return;
211 }
212
213 uint16 src = pSrcItem->GetPos();
214 if (dest == src) // prevent equip in same slot, only at cheat
215 return;
216
217 Item* pDstItem = _player->GetItemByPos(dest);
218 if (!pDstItem) // empty slot, simple case
219 {
220 _player->RemoveItem(srcbag, srcslot, true);
221 _player->EquipItem(dest, pSrcItem, true);
222 _player->AutoUnequipOffhandIfNeed();
223 }
224 else // have currently equipped item, not simple case
225 {
226 uint8 dstbag = pDstItem->GetBagSlot();
227 uint8 dstslot = pDstItem->GetSlot();
228
229 msg = _player->CanUnequipItem(dest, !pSrcItem->IsBag());
230 if (msg != EQUIP_ERR_OK)
231 {
232 _player->SendEquipError(msg, pDstItem, NULL);
233 return;
234 }
235
236 // check dest->src move possibility
237 ItemPosCountVec sSrc;
238 uint16 eSrc = 0;
239 if (_player->IsInventoryPos(src))
240 {
241 msg = _player->CanStoreItem(srcbag, srcslot, sSrc, pDstItem, true);
242 if (msg != EQUIP_ERR_OK)
243 msg = _player->CanStoreItem(srcbag, NULL_SLOT, sSrc, pDstItem, true);
244 if (msg != EQUIP_ERR_OK)
245 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true);
246 }
247 else if (_player->IsBankPos(src))
248 {
249 msg = _player->CanBankItem(srcbag, srcslot, sSrc, pDstItem, true);
250 if (msg != EQUIP_ERR_OK)
251 msg = _player->CanBankItem(srcbag, NULL_SLOT, sSrc, pDstItem, true);
252 if (msg != EQUIP_ERR_OK)
253 msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true);
254 }
255 else if (_player->IsEquipmentPos(src))
256 {
257 msg = _player->CanEquipItem(srcslot, eSrc, pDstItem, true);
258 if (msg == EQUIP_ERR_OK)
259 msg = _player->CanUnequipItem(eSrc, true);
260 }
261
262 if (msg != EQUIP_ERR_OK)
263 {
264 _player->SendEquipError(msg, pDstItem, pSrcItem);
265 return;
266 }
267
268 // now do moves, remove...
269 _player->RemoveItem(dstbag, dstslot, false);
270 _player->RemoveItem(srcbag, srcslot, false);
271
272 // add to dest
273 _player->EquipItem(dest, pSrcItem, true);
274
275 // add to src
276 if (_player->IsInventoryPos(src))
277 _player->StoreItem(sSrc, pDstItem, true);
278 else if (_player->IsBankPos(src))
279 _player->BankItem(sSrc, pDstItem, true);
280 else if (_player->IsEquipmentPos(src))
281 _player->EquipItem(eSrc, pDstItem, true);
282
283 _player->AutoUnequipOffhandIfNeed();
284 }
285}
286
288{
289 //SF_LOG_DEBUG("network", "WORLD: CMSG_DESTROY_ITEM");
290 int32 count;
291 int8 bag, slot;
292
293 recvData >> count;
294 recvData >> slot >> bag;
295 //SF_LOG_DEBUG("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count);
296
297 uint16 pos = (bag << 8) | slot;
298
299 // prevent drop unequipable items (in combat, for example) and non-empty bags
300 if (_player->IsEquipmentPos(pos) || _player->IsBagPos(pos))
301 {
302 InventoryResult msg = _player->CanUnequipItem(pos, false);
303 if (msg != EQUIP_ERR_OK)
304 {
305 _player->SendEquipError(msg, _player->GetItemByPos(pos), NULL);
306 return;
307 }
308 }
309
310 Item* pItem = _player->GetItemByPos(bag, slot);
311 if (!pItem)
312 {
313 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
314 return;
315 }
316
318 {
319 _player->SendEquipError(EQUIP_ERR_DROP_BOUND_ITEM, NULL, NULL);
320 return;
321 }
322
323 if (count)
324 {
325 uint32 i_count = count;
326 _player->DestroyItemCount(pItem, i_count, true);
327 }
328 else
329 _player->DestroyItem(bag, slot, true);
330}
331
333{
334 uint8 bag, slot;
335 recvData >> bag >> slot;
336
337 Item* pItem = _player->GetItemByPos(bag, slot);
338
339 if (pItem && pItem->GetTemplate()->PageText)
340 {
341 WorldPacket data;
342
343 InventoryResult msg = _player->CanUseItem(pItem);
344 if (msg == EQUIP_ERR_OK)
345 {
347 SF_LOG_INFO("network", "STORAGE: Item page sent");
348 }
349 else
350 {
352 SF_LOG_INFO("network", "STORAGE: Unable to read item");
353 _player->SendEquipError(msg, pItem, NULL);
354 }
355 data << pItem->GetGUID();
356 SendPacket(&data);
357 }
358 else
359 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
360}
361
363{
364 SF_LOG_DEBUG("network", "WORLD: Received CMSG_SELL_ITEM");
365
366 ObjectGuid VendorGUID, ItemGUID;
367 uint32 count;
368
369 recvData >> count;
370
371 recvData.ReadGuidMask(ItemGUID, 4, 3, 7);
372 recvData.ReadGuidMask(VendorGUID, 6, 5, 1);
373 recvData.ReadGuidMask(ItemGUID, 5, 2, 1);
374 recvData.ReadGuidMask(VendorGUID, 2);
375 recvData.ReadGuidMask(ItemGUID, 6);
376 recvData.ReadGuidMask(VendorGUID, 4, 0, 7, 3);
377 recvData.ReadGuidMask(ItemGUID, 0);
378
379 recvData.ReadGuidBytes(VendorGUID, 6, 3, 1);
380 recvData.ReadGuidBytes(ItemGUID, 1);
381 recvData.ReadGuidBytes(VendorGUID, 2);
382 recvData.ReadGuidBytes(ItemGUID, 7, 5);
383 recvData.ReadGuidBytes(VendorGUID, 7);
384 recvData.ReadGuidBytes(ItemGUID, 2);
385 recvData.ReadGuidBytes(VendorGUID, 0, 5);
386 recvData.ReadGuidBytes(ItemGUID, 3, 6);
387 recvData.ReadGuidBytes(VendorGUID, 4);
388 recvData.ReadGuidBytes(ItemGUID, 4, 0);
389
390 if (!ItemGUID)
391 return;
392
394 if (!creature)
395 {
396 SF_LOG_DEBUG("network", "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(VendorGUID)));
397 _player->SendSellResponse(SellResult::SELL_ERR_CANT_FIND_VENDOR, 0, ItemGUID);
398 return;
399 }
400
401 // remove fake death
402 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
404
405 Item* pItem = _player->GetItemByGuid(ItemGUID);
406 if (pItem)
407 {
408 // prevent sell not owner item
409 if (_player->GetGUID() != pItem->GetOwnerGUID())
410 {
411 _player->SendSellResponse(SellResult::SELL_ERR_CANT_SELL_ITEM, VendorGUID, ItemGUID);
412 return;
413 }
414
415 // prevent sell non empty bag by drag-and-drop at vendor's item list
416 if (pItem->IsNotEmptyBag())
417 {
418 _player->SendSellResponse(SellResult::SELL_ERR_CANT_SELL_ITEM, VendorGUID, ItemGUID);
419 return;
420 }
421
422 // prevent sell currently looted item
423 if (_player->GetLootGUID() == pItem->GetGUID())
424 {
425 _player->SendSellResponse(SellResult::SELL_ERR_CANT_SELL_ITEM, VendorGUID, ItemGUID);
426 return;
427 }
428
429 // prevent selling item for sellprice when the item is still refundable
430 // this probably happens when right clicking a refundable item, the client sends both
431 // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified)
433 return; // Therefore, no feedback to client
434
435 // special case at auto sell (sell all)
436 if (count == 0)
437 count = pItem->GetCount();
438 else
439 {
440 // prevent sell more items that exist in stack (possible only not from client)
441 if (count > pItem->GetCount())
442 {
443 _player->SendSellResponse(SellResult::SELL_ERR_CANT_SELL_ITEM, VendorGUID, ItemGUID);
444 return;
445 }
446 }
447
448 ItemTemplate const* pProto = pItem->GetTemplate();
449 if (pProto)
450 {
451 if (pProto->SellPrice > 0)
452 {
453 if (count < pItem->GetCount()) // need split items
454 {
455 Item* pNewItem = pItem->CloneItem(count, _player);
456 if (!pNewItem)
457 {
458 SF_LOG_ERROR("network", "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count);
459 _player->SendSellResponse(SellResult::SELL_ERR_CANT_SELL_ITEM, VendorGUID, ItemGUID);
460 return;
461 }
462
463 pItem->SetCount(pItem->GetCount() - count);
464 _player->ItemRemovedQuestCheck(pItem->GetEntry(), count);
465 if (_player->IsInWorld())
468
469 _player->AddItemToBuyBackSlot(pNewItem);
470 if (_player->IsInWorld())
471 pNewItem->SendUpdateToPlayer(_player);
472 }
473 else
474 {
475 _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
476 _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
478 _player->AddItemToBuyBackSlot(pItem);
479 }
480
481 uint32 money = pProto->SellPrice * count;
482 _player->ModifyMoney(money);
483 _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
484 }
485 else
486 _player->SendSellResponse(SellResult::SELL_ERR_CANT_SELL_ITEM, VendorGUID, ItemGUID);
487 return;
488 }
489 }
490 _player->SendSellResponse(SellResult::SELL_ERR_CANT_FIND_ITEM, VendorGUID, ItemGUID);
491 return;
492}
493
495{
496 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BUYBACK_ITEM");
497
498 ObjectGuid VendorGUID;
499 uint32 slot;
500
501 recvData >> slot;
502 recvData.ReadGuidMask(VendorGUID, 2, 3, 0, 4, 1, 7, 5, 6);
503 recvData.ReadGuidBytes(VendorGUID, 0, 6, 1, 7, 5, 2, 3, 4);
504
506 if (!creature)
507 {
508 SF_LOG_DEBUG("network", "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(VendorGUID)));
509 _player->SendSellResponse(SellResult::SELL_ERR_CANT_FIND_VENDOR, 0, 0);
510 return;
511 }
512
513 // remove fake death
514 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
516
517 Item* pItem = _player->GetItemFromBuyBackSlot(slot);
518 if (pItem)
519 {
520 uint32 price = _player->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE + slot - BUYBACK_SLOT_START);
521 if (!_player->HasEnoughMoney(uint64(price)))
522 {
523 _player->SendBuyFailed(BuyResult::BUY_ERR_NOT_ENOUGHT_MONEY, VendorGUID, pItem->GetEntry());
524 return;
525 }
526
527 ItemPosCountVec dest;
528 InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false);
529 if (msg == EQUIP_ERR_OK)
530 {
531 _player->ModifyMoney(-(int32)price);
532 _player->RemoveItemFromBuyBackSlot(slot, false);
533 _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount());
534 _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount());
535 _player->StoreItem(dest, pItem, true);
536 }
537 else
538 _player->SendEquipError(msg, pItem, NULL);
539 return;
540 }
541 else
542 _player->SendBuyFailed(BuyResult::BUY_ERR_CANT_FIND_ITEM, VendorGUID, 0);
543}
544
546{
547 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BUY_ITEM_IN_SLOT");
548 uint64 vendorguid, bagguid;
549 uint32 item, slot, count;
550 uint8 bagslot;
551
552 recvData >> vendorguid >> item >> slot >> bagguid >> bagslot >> count;
553
554 // client expects count starting at 1, and we send vendorslot+1 to client already
555 if (slot > 0)
556 --slot;
557 else
558 return; // cheating
559
560 uint8 bag = NULL_BAG; // init for case invalid bagGUID
561 Item* bagItem = NULL;
562 // find bag slot by bag guid
563 if (bagguid == _player->GetGUID())
565 else
566 bagItem = _player->GetItemByGuid(bagguid);
567
568 if (bagItem && bagItem->IsBag())
569 bag = bagItem->GetSlot();
570
571 // bag not found, cheating?
572 if (bag == NULL_BAG)
573 return;
574
575 GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagslot);
576}
577
579{
580 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BUY_ITEM");
581
582 ObjectGuid vendorGuid, bagGuid;
583 uint32 item, slot, count, bagSlot;
584 uint8 itemType; // 1 = item, 2 = currency
585
586 recvData >> bagSlot >> count >> item >> slot;
587
588 vendorGuid[6] = recvData.ReadBit();
589 bagGuid[6] = recvData.ReadBit();
590 bagGuid[4] = recvData.ReadBit();
591 vendorGuid[4] = recvData.ReadBit();
592 itemType = recvData.ReadBits(2);
593 vendorGuid[0] = recvData.ReadBit();
594 vendorGuid[3] = recvData.ReadBit();
595 bagGuid[3] = recvData.ReadBit();
596 vendorGuid[7] = recvData.ReadBit();
597 vendorGuid[5] = recvData.ReadBit();
598 bagGuid[2] = recvData.ReadBit();
599 vendorGuid[1] = recvData.ReadBit();
600 bagGuid[7] = recvData.ReadBit();
601 vendorGuid[2] = recvData.ReadBit();
602 bagGuid[1] = recvData.ReadBit();
603 bagGuid[0] = recvData.ReadBit();
604 bagGuid[5] = recvData.ReadBit();
605 recvData.FlushBits();
606
607 recvData.ReadByteSeq(vendorGuid[5]);
608 recvData.ReadByteSeq(vendorGuid[0]);
609 recvData.ReadByteSeq(bagGuid[3]);
610 recvData.ReadByteSeq(bagGuid[1]);
611 recvData.ReadByteSeq(bagGuid[6]);
612 recvData.ReadByteSeq(vendorGuid[2]);
613 recvData.ReadByteSeq(vendorGuid[7]);
614 recvData.ReadByteSeq(vendorGuid[6]);
615 recvData.ReadByteSeq(bagGuid[0]);
616 recvData.ReadByteSeq(bagGuid[5]);
617 recvData.ReadByteSeq(vendorGuid[4]);
618 recvData.ReadByteSeq(bagGuid[2]);
619 recvData.ReadByteSeq(vendorGuid[3]);
620 recvData.ReadByteSeq(bagGuid[7]);
621 recvData.ReadByteSeq(vendorGuid[1]);
622 recvData.ReadByteSeq(bagGuid[4]);
623
624 // client expects count starting at 1, and we send vendorslot+1 to client already
625 if (slot > 0)
626 --slot;
627 else
628 return; // cheating
629
630 if (itemType == ITEM_VENDOR_TYPE_ITEM)
631 {
632 Item* bagItem = _player->GetItemByGuid(bagGuid);
633
634 uint8 bag = NULL_BAG;
635 if (bagItem && bagItem->IsBag())
636 bag = bagItem->GetSlot();
637 else if (bagGuid == GetPlayer()->GetGUID()) // The client sends the player guid when trying to store an item in the default backpack
639
640 GetPlayer()->BuyItemFromVendorSlot(vendorGuid, slot, item, count, bag, bagSlot);
641 }
642 else if (itemType == ITEM_VENDOR_TYPE_CURRENCY)
643 GetPlayer()->BuyCurrencyFromVendorSlot(vendorGuid, slot, item, count);
644 else
645 SF_LOG_DEBUG("network", "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode", itemType);
646}
647
649{
650 ObjectGuid guid;
651
652 recvData.ReadGuidMask(guid, 6, 7, 3, 1, 2, 0, 4, 5);
653 recvData.ReadGuidBytes(guid, 0, 7, 1, 6, 4, 3, 5, 2);
654
655 if (!GetPlayer()->IsAlive())
656 return;
657
658 SF_LOG_DEBUG("network", "WORLD: Recvd CMSG_LIST_INVENTORY");
659
660 SendListInventory(guid);
661}
662
664{
665 SF_LOG_DEBUG("network", "WORLD: Sent SMSG_LIST_INVENTORY");
666
668 if (!vendor)
669 {
670 SF_LOG_DEBUG("network", "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorGuid)));
671 _player->SendSellResponse(SellResult::SELL_ERR_CANT_FIND_VENDOR, 0, 0);
672 return;
673 }
674
675 // remove fake death
676 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
678
679 // Stop the npc if moving
680 if (vendor->HasUnitState(UNIT_STATE_MOVING))
681 vendor->StopMoving();
682
683 VendorItemData const* vendorItems = vendor->GetVendorItems();
684 uint32 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0;
685
686 //if (rawItemCount > 300),
687 // rawItemCount = 300; // client cap but uint8 max value is 255
688
689 ByteBuffer itemsData(32 * rawItemCount);
690
691 bool hasExtendedCost[MAX_VENDOR_ITEMS];
692
693 const float discountMod = _player->GetReputationPriceDiscount(vendor);
694 uint8 count = 0;
695
696 for (uint32 slot = 0; slot < rawItemCount; ++slot)
697 {
698 VendorItem const* vendorItem = vendorItems->GetItem(slot);
699 if (!vendorItem)
700 continue;
701
702 if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM)
703 {
704 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItem->item);
705 if (!itemTemplate)
706 continue;
707
708 uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem);
709 if (!_player->IsGameMaster()) // ignore conditions if GM on
710 {
711 // Respect allowed class
712 if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP)
713 continue;
714
715 // Only display items in vendor lists for the team the player is on
716 if ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) ||
717 (itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE))
718 continue;
719
720 // Items sold out are not displayed in list
721 if (leftInStock == 0)
722 continue;
723 }
724
725 ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), vendorItem->item);
726 if (!sConditionMgr->IsObjectMeetToConditions(_player, vendor, conditions))
727 {
728 SF_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), vendorItem->item);
729 continue;
730 }
731
732 int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
733
734 if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES))
735 price -= CalculatePct(price, priceMod);
736
737 itemsData << int32(leftInStock);
738 itemsData << uint32(price);
739 itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency
740 itemsData << int32(-1);
741 itemsData << uint32(itemTemplate->DisplayInfoID);
742 itemsData << uint32(itemTemplate->BuyCount);
743 itemsData << uint32(vendorItem->item);
744
745 if (vendorItem->ExtendedCost)
746 {
747 hasExtendedCost[count] = true;
748 itemsData << uint32(vendorItem->ExtendedCost);
749 }
750 else
751 hasExtendedCost[count] = false;
752
753 itemsData << uint32(0);
754 itemsData << uint32(slot + 1); // client expects counting to start at 1
755
756 if (++count >= MAX_VENDOR_ITEMS)
757 break;
758 }
759
760 else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY)
761 {
762 CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item);
763 if (!currencyTemplate)
764 continue;
765
766 if (!vendorItem->ExtendedCost)
767 continue; // there's no price defined for currencies, only extendedcost is used
768
769 itemsData << int32(-1); // left in stock
770 itemsData << uint32(0); // price, only seen currency types that have Extended cost
771 itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency
772 itemsData << int32(-1);
773 itemsData << uint32(0); // displayId
774 itemsData << uint32(0); // buy count
775 itemsData << uint32(vendorItem->item);
776
777 hasExtendedCost[count] = true;
778 itemsData << uint32(vendorItem->ExtendedCost);
779
780 itemsData << uint32(0);
781 itemsData << uint32(slot + 1); // client expects counting to start at 1
782
783 if (++count >= MAX_VENDOR_ITEMS)
784 break;
785 }
786 // else error
787 }
788
789 ObjectGuid guid = vendorGuid;
790
791 WorldPacket data(SMSG_LIST_INVENTORY, 12 + itemsData.size());
792 data.WriteBit(guid[5]);
793 data.WriteBit(guid[7]);
794 data.WriteBit(guid[1]);
795 data.WriteBit(guid[3]);
796 data.WriteBit(guid[6]);
797 data.WriteBits(count, 18); // item count
798
799 for (uint32 i = 0; i < count; i++)
800 {
801 data.WriteBit(0); // unknown
802 data.WriteBit(!hasExtendedCost[i]); // has extended cost
803 data.WriteBit(1); // has unknown
804 }
805
806 data.WriteBit(guid[4]);
807 data.WriteBit(guid[0]);
808 data.WriteBit(guid[2]);
809
810 /* It doesn't matter what value is used here (PROBABLY its full vendor size)
811 * What matters is that if count of items we can see is 0 and this field is 1
812 * then client will open the vendor list, otherwise it won't
813 */
814 if (rawItemCount)
815 data << uint8(rawItemCount);
816 else
817 data << uint8(vendor->IsArmorer());
818
819 data.append(itemsData);
820
821 data.WriteByteSeq(guid[3]);
822 data.WriteByteSeq(guid[7]);
823 data.WriteByteSeq(guid[0]);
824 data.WriteByteSeq(guid[6]);
825 data.WriteByteSeq(guid[2]);
826 data.WriteByteSeq(guid[1]);
827 data.WriteByteSeq(guid[4]);
828 data.WriteByteSeq(guid[5]);
829
830 SendPacket(&data);
831}
832
834{
835 //SF_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_BAG_ITEM");
836 uint8 srcBag, srcSlot, dstBag;
837
838 recvData >> srcSlot >> srcBag >> dstBag;
839 recvData.rfinish();
840
841 //SF_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag);
842
843 Item* pItem = _player->GetItemByPos(srcBag, srcSlot);
844 if (!pItem)
845 return;
846
847 if (!_player->IsValidPos(dstBag, NULL_SLOT, false)) // can be autostore pos
848 {
849 _player->SendEquipError(EQUIP_ERR_WRONG_SLOT, NULL, NULL);
850 return;
851 }
852
853 uint16 src = pItem->GetPos();
854
855 // check unequip potability for equipped items and bank bags
856 if (_player->IsEquipmentPos(src) || _player->IsBagPos(src))
857 {
858 InventoryResult msg = _player->CanUnequipItem(src, !_player->IsBagPos(src));
859 if (msg != EQUIP_ERR_OK)
860 {
861 _player->SendEquipError(msg, pItem, NULL);
862 return;
863 }
864 }
865
866 ItemPosCountVec dest;
867 InventoryResult msg = _player->CanStoreItem(dstBag, NULL_SLOT, dest, pItem, false);
868 if (msg != EQUIP_ERR_OK)
869 {
870 _player->SendEquipError(msg, pItem, NULL);
871 return;
872 }
873
874 // no-op: placed in same slot
875 if (dest.size() == 1 && dest[0].pos == src)
876 {
877 // just remove grey item state
878 _player->SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, pItem, NULL);
879 return;
880 }
881
882 _player->RemoveItem(srcBag, srcSlot, true);
883 _player->StoreItem(dest, pItem, true);
884}
885
887{
888 SF_LOG_DEBUG("network", "WORLD: CMSG_BUY_BANK_SLOT");
889
890 ObjectGuid guid;
891
892 recvData.ReadGuidMask(guid, 7, 6, 1, 3, 2, 0, 4, 5);
893 recvData.ReadGuidBytes(guid, 3, 5, 1, 6, 7, 2, 0, 4);
894
895 // cheating protection
896 /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command.
897 Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER);
898 if (!creature)
899 {
900 SF_LOG_DEBUG("WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
901 return;
902 }
903 */
904
905 uint32 slot = _player->GetBankBagSlotCount();
906
907 // next slot
908 ++slot;
909
910 SF_LOG_INFO("network", "PLAYER: Buy bank bag slot, slot number = %u", slot);
911
912 BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot);
913
915
916 if (!slotEntry)
917 {
919 SendPacket(&data);
920 return;
921 }
922
923 uint32 price = slotEntry->price;
924
925 if (!_player->HasEnoughMoney(uint64(price)))
926 {
928 SendPacket(&data);
929 return;
930 }
931
932 _player->SetBankBagSlotCount(slot);
933 _player->ModifyMoney(-int64(price));
934
935 data << uint32(ERR_BANKSLOT_OK);
936 SendPacket(&data);
937
938 _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT);
939}
940
942{
943 SF_LOG_DEBUG("network", "WORLD: CMSG_AUTOBANK_ITEM");
944 uint8 srcBag, srcSlot;
945
946 recvPacket >> srcSlot >> srcBag;
947 recvPacket.rfinish();
948
949 SF_LOG_DEBUG("network", "STORAGE: receive srcbag = %u, srcslot = %u", srcBag, srcSlot);
950
951 Item* pItem = _player->GetItemByPos(srcBag, srcSlot);
952 if (!pItem)
953 return;
954
955 ItemPosCountVec dest;
956 InventoryResult msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false);
957 if (msg != EQUIP_ERR_OK)
958 {
959 _player->SendEquipError(msg, pItem, NULL);
960 return;
961 }
962
963 if (dest.size() == 1 && dest[0].pos == pItem->GetPos())
964 {
965 _player->SendEquipError(EQUIP_ERR_CANT_SWAP, pItem, NULL);
966 return;
967 }
968
969 _player->RemoveItem(srcBag, srcSlot, true);
970 _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
971 _player->BankItem(dest, pItem, true);
972}
973
975{
976 SF_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_BANK_ITEM");
977 uint8 srcBag, srcSlot;
978
979 recvPacket >> srcSlot >> srcBag;
980 SF_LOG_DEBUG("network", "STORAGE: receive srcbag = %u, srcslot = %u", srcBag, srcSlot);
981
982 Item* pItem = _player->GetItemByPos(srcBag, srcSlot);
983 if (!pItem)
984 return;
985
986 if (_player->IsBankPos(srcBag, srcSlot)) // moving from bank to inventory
987 {
988 ItemPosCountVec dest;
989 InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false);
990 if (msg != EQUIP_ERR_OK)
991 {
992 _player->SendEquipError(msg, pItem, NULL);
993 return;
994 }
995
996 _player->RemoveItem(srcBag, srcSlot, true);
997 if (Item const* storedItem = _player->StoreItem(dest, pItem, true))
998 _player->ItemAddedQuestCheck(storedItem->GetEntry(), storedItem->GetCount());
999 }
1000 else // moving from inventory to bank
1001 {
1002 ItemPosCountVec dest;
1003 InventoryResult msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false);
1004 if (msg != EQUIP_ERR_OK)
1005 {
1006 _player->SendEquipError(msg, pItem, NULL);
1007 return;
1008 }
1009
1010 _player->RemoveItem(srcBag, srcSlot, true);
1011 _player->BankItem(dest, pItem, true);
1012 }
1013}
1014
1015void WorldSession::SendEnchantmentLog(uint64 target, uint64 caster, uint64 itemGuid, uint32 itemId, uint32 enchantId, uint32 enchantmentSlot)
1016{
1017 ObjectGuid TargetGUID = target;
1018 ObjectGuid CasterGUID = caster;
1019 ObjectGuid ItemGUID = itemGuid;
1020
1021 WorldPacket data(SMSG_ENCHANTMENT_LOG, (8 + 8 + 8 + 4 + 4 + 4 + 1));
1022 data << uint32(itemId);
1023 data << uint32(enchantmentSlot);
1024 data << uint32(enchantId);
1025
1026 data.WriteGuidMask(CasterGUID, 6, 7);
1027 data.WriteGuidMask(TargetGUID, 6, 4);
1028 data.WriteGuidMask(CasterGUID, 5);
1029 data.WriteGuidMask(ItemGUID, 7, 2, 3);
1030 data.WriteGuidMask(CasterGUID, 4, 3);
1031 data.WriteGuidMask(ItemGUID, 6);
1032 data.WriteGuidMask(TargetGUID, 1);
1033 data.WriteGuidMask(CasterGUID, 2);
1034 data.WriteGuidMask(TargetGUID, 5);
1035 data.WriteGuidMask(ItemGUID, 4);
1036 data.WriteGuidMask(TargetGUID, 0);
1037 data.WriteGuidMask(ItemGUID, 1);
1038 data.WriteGuidMask(CasterGUID, 0);
1039 data.WriteGuidMask(TargetGUID, 3, 7);
1040 data.WriteGuidMask(ItemGUID, 5, 0);
1041 data.WriteGuidMask(TargetGUID, 2);
1042 data.WriteGuidMask(CasterGUID, 1);
1043
1044 data.WriteGuidBytes(CasterGUID, 0);
1045 data.WriteGuidBytes(TargetGUID, 2);
1046 data.WriteGuidBytes(ItemGUID, 7);
1047 data.WriteGuidBytes(CasterGUID, 1);
1048 data.WriteGuidBytes(TargetGUID, 4);
1049 data.WriteGuidBytes(ItemGUID, 5);
1050 data.WriteGuidBytes(CasterGUID, 4);
1051 data.WriteGuidBytes(ItemGUID, 2);
1052 data.WriteGuidBytes(TargetGUID, 6, 0);
1053 data.WriteGuidBytes(ItemGUID, 0, 4);
1054 data.WriteGuidBytes(CasterGUID, 3);
1055 data.WriteGuidBytes(TargetGUID, 5);
1056 data.WriteGuidBytes(ItemGUID, 1);
1057 data.WriteGuidBytes(CasterGUID, 3);
1058 data.WriteGuidBytes(TargetGUID, 7);
1059 data.WriteGuidBytes(CasterGUID, 7);
1060 data.WriteGuidBytes(ItemGUID, 3);
1061 data.WriteGuidBytes(CasterGUID, 6, 2, 5);
1062 data.WriteGuidBytes(ItemGUID, 6);
1063 data.WriteGuidBytes(TargetGUID, 1);
1064
1065 GetPlayer()->SendMessageToSet(&data, true);
1066}
1067
1069{
1070 WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, 8 + 8 + 4 + 4);
1071
1072 data.WriteBit(Itemguid[4]);
1073 data.WriteBit(Itemguid[0]);
1074 data.WriteBit(Playerguid[3]);
1075 data.WriteBit(Itemguid[3]);
1076 data.WriteBit(Playerguid[2]);
1077 data.WriteBit(Playerguid[6]);
1078 data.WriteBit(Playerguid[7]);
1079 data.WriteBit(Itemguid[1]);
1080 data.WriteBit(Playerguid[4]);
1081 data.WriteBit(Itemguid[6]);
1082 data.WriteBit(Itemguid[5]);
1083 data.WriteBit(Playerguid[0]);
1084 data.WriteBit(Itemguid[2]);
1085 data.WriteBit(Playerguid[5]);
1086 data.WriteBit(Playerguid[1]);
1087 data.WriteBit(Itemguid[7]);
1088
1089 data.FlushBits();
1090
1091 data << uint32(slot);
1092 data.WriteByteSeq(Playerguid[4]);
1093 data.WriteByteSeq(Playerguid[2]);
1094 data.WriteByteSeq(Itemguid[5]);
1095 data.WriteByteSeq(Itemguid[4]);
1096 data.WriteByteSeq(Playerguid[6]);
1097 data.WriteByteSeq(Itemguid[1]);
1098 data.WriteByteSeq(Playerguid[0]);
1099 data.WriteByteSeq(Playerguid[1]);
1100 data.WriteByteSeq(Itemguid[6]);
1101 data.WriteByteSeq(Itemguid[2]);
1102 data.WriteByteSeq(Playerguid[7]);
1103 data.WriteByteSeq(Itemguid[0]);
1104 data.WriteByteSeq(Itemguid[3]);
1105 data.WriteByteSeq(Itemguid[7]);
1106 data.WriteByteSeq(Playerguid[3]);
1107 data.WriteByteSeq(Playerguid[5]);
1108 data << uint32(Duration);
1109
1110 SendPacket(&data);
1111}
1112
1114{
1115 SF_LOG_DEBUG("network", "Received opcode CMSG_WRAP_ITEM");
1116
1117 uint8 gift_bag, gift_slot, item_bag, item_slot;
1118
1119 recvData >> gift_bag >> gift_slot; // paper
1120 recvData >> item_bag >> item_slot; // item
1121
1122 SF_LOG_DEBUG("network", "WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot);
1123
1124 Item* gift = _player->GetItemByPos(gift_bag, gift_slot);
1125 if (!gift)
1126 {
1127 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL);
1128 return;
1129 }
1130
1131 if (!(gift->GetTemplate()->Flags & ITEM_PROTO_FLAG_WRAPPER)) // cheating: non-wrapper wrapper
1132 {
1133 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL);
1134 return;
1135 }
1136
1137 Item* item = _player->GetItemByPos(item_bag, item_slot);
1138
1139 if (!item)
1140 {
1141 _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL);
1142 return;
1143 }
1144
1145 if (item == gift) // not possable with pacjket from real client
1146 {
1147 _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL);
1148 return;
1149 }
1150
1151 if (item->IsEquipped())
1152 {
1153 _player->SendEquipError(EQUIP_ERR_CANT_WRAP_EQUIPPED, item, NULL);
1154 return;
1155 }
1156
1157 if (item->GetUInt64Value(ITEM_FIELD_GIFT_CREATOR)) // HasFlag(ITEM_FIELD_DYNAMIC_FLAGS, ITEM_FLAGS_WRAPPED);
1158 {
1159 _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL);
1160 return;
1161 }
1162
1163 if (item->IsBag())
1164 {
1165 _player->SendEquipError(EQUIP_ERR_CANT_WRAP_BAGS, item, NULL);
1166 return;
1167 }
1168
1169 if (item->IsSoulBound())
1170 {
1171 _player->SendEquipError(EQUIP_ERR_CANT_WRAP_BOUND, item, NULL);
1172 return;
1173 }
1174
1175 if (item->GetMaxStackCount() != 1)
1176 {
1177 _player->SendEquipError(EQUIP_ERR_CANT_WRAP_STACKABLE, item, NULL);
1178 return;
1179 }
1180
1181 // maybe not correct check (it is better than nothing)
1182 if (item->GetTemplate()->MaxCount > 0)
1183 {
1184 _player->SendEquipError(EQUIP_ERR_CANT_WRAP_UNIQUE, item, NULL);
1185 return;
1186 }
1187
1188 SQLTransaction trans = CharacterDatabase.BeginTransaction();
1189
1190 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GIFT);
1191 stmt->setUInt32(0, GUID_LOPART(item->GetOwnerGUID()));
1192 stmt->setUInt32(1, item->GetGUIDLow());
1193 stmt->setUInt32(2, item->GetEntry());
1195 trans->Append(stmt);
1196
1197 item->SetEntry(gift->GetEntry());
1198
1199 switch (item->GetEntry())
1200 {
1201 case 5042: item->SetEntry(5043); break;
1202 case 5048: item->SetEntry(5044); break;
1203 case 17303: item->SetEntry(17302); break;
1204 case 17304: item->SetEntry(17305); break;
1205 case 17307: item->SetEntry(17308); break;
1206 case 21830: item->SetEntry(21831); break;
1207 }
1211
1212 if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance`
1213 {
1214 // after save it will be impossible to remove the item from the queue
1216 item->SaveToDB(trans); // item gave inventory record unchanged and can be save standalone
1217 }
1218 CharacterDatabase.CommitTransaction(trans);
1219
1220 uint32 count = 1;
1221 _player->DestroyItemCount(gift, count, true);
1222}
1223
1225{
1226 SF_LOG_DEBUG("network", "WORLD: CMSG_SOCKET_GEMS");
1227
1228 ObjectGuid item_guid;
1229 ObjectGuid gem_guids[MAX_GEM_SOCKETS];
1230
1231 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1232 gem_guids[i][4] = recvData.ReadBit();
1233 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1234 gem_guids[i][0] = recvData.ReadBit();
1235 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1236 gem_guids[i][6] = recvData.ReadBit();
1237 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1238 gem_guids[i][2] = recvData.ReadBit();
1239 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1240 gem_guids[i][1] = recvData.ReadBit();
1241 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1242 gem_guids[i][7] = recvData.ReadBit();
1243 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1244 gem_guids[i][3] = recvData.ReadBit();
1245 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1246 gem_guids[i][5] = recvData.ReadBit();
1247
1248 recvData.ReadGuidMask(item_guid, 5, 0, 6, 2, 3, 4, 7, 1);
1249
1250 recvData.ReadGuidBytes(item_guid, 7, 2, 6);
1251
1252 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1253 recvData.ReadByteSeq(gem_guids[i][6]);
1254 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1255 recvData.ReadByteSeq(gem_guids[i][4]);
1256 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1257 recvData.ReadByteSeq(gem_guids[i][3]);
1258 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1259 recvData.ReadByteSeq(gem_guids[i][2]);
1260 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1261 recvData.ReadByteSeq(gem_guids[i][0]);
1262 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1263 recvData.ReadByteSeq(gem_guids[i][1]);
1264 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1265 recvData.ReadByteSeq(gem_guids[i][7]);
1266 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1267 recvData.ReadByteSeq(gem_guids[i][5]);
1268
1269 recvData.ReadGuidBytes(item_guid, 4, 3, 1, 5, 0);
1270
1271 if (!item_guid)
1272 return;
1273
1274 //cheat -> tried to socket same gem multiple times
1275 if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) ||
1276 (gem_guids[1] && (gem_guids[1] == gem_guids[2])))
1277 return;
1278
1279 Item* itemTarget = _player->GetItemByGuid(item_guid);
1280 if (!itemTarget) //missing item to socket
1281 return;
1282
1283 ItemTemplate const* itemProto = itemTarget->GetTemplate();
1284 if (!itemProto)
1285 return;
1286
1287 //this slot is excepted when applying / removing meta gem bonus
1288 uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT);
1289
1290 Item* Gems[MAX_GEM_SOCKETS];
1291 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1292 Gems[i] = gem_guids[i] ? _player->GetItemByGuid(gem_guids[i]) : NULL;
1293
1294 GemPropertiesEntry const* GemProps[MAX_GEM_SOCKETS];
1295 for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get geminfo from dbc storage
1296 GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetTemplate()->GemProperties) : NULL;
1297
1298 for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe
1299 {
1300 if (!GemProps[i])
1301 continue;
1302
1303 // tried to put gem in socket where no socket exists (take care about prismatic sockets)
1304 if (!itemProto->Socket[i].Color)
1305 {
1306 // no prismatic socket
1308 return;
1309
1310 // not first not-colored (not normaly used) socket
1311 if (i != 0 && !itemProto->Socket[i - 1].Color && (i + 1 >= MAX_GEM_SOCKETS || itemProto->Socket[i + 1].Color))
1312 return;
1313
1314 // ok, this is first not colored socket for item with prismatic socket
1315 }
1316
1317 // tried to put normal gem in meta socket
1318 if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META)
1319 return;
1320
1321 // tried to put meta gem in normal socket
1322 if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META)
1323 return;
1324
1325 // tried to put normal gem in cogwheel socket
1326 if (itemProto->Socket[i].Color == SOCKET_COLOR_COGWHEEL && GemProps[i]->color != SOCKET_COLOR_COGWHEEL)
1327 return;
1328
1329 // tried to put cogwheel gem in normal socket
1330 if (itemProto->Socket[i].Color != SOCKET_COLOR_COGWHEEL && GemProps[i]->color == SOCKET_COLOR_COGWHEEL)
1331 return;
1332 }
1333
1334 uint32 GemEnchants[MAX_GEM_SOCKETS];
1335 uint32 OldEnchants[MAX_GEM_SOCKETS];
1336 for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get new and old enchantments
1337 {
1338 GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
1339 OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + i));
1340 }
1341
1342 // check unique-equipped conditions
1343 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1344 {
1345 if (!Gems[i])
1346 continue;
1347
1348 // continue check for case when attempt add 2 similar unique equipped gems in one item.
1349 ItemTemplate const* iGemProto = Gems[i]->GetTemplate();
1350
1351 // unique item (for new and already placed bit removed enchantments
1352 if (iGemProto->Flags & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED)
1353 {
1354 for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
1355 {
1356 if (i == j) // skip self
1357 continue;
1358
1359 if (Gems[j])
1360 {
1361 if (iGemProto->ItemId == Gems[j]->GetEntry())
1362 {
1363 _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
1364 return;
1365 }
1366 }
1367 else if (OldEnchants[j])
1368 {
1369 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
1370 {
1371 if (iGemProto->ItemId == enchantEntry->GemID)
1372 {
1373 _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
1374 return;
1375 }
1376 }
1377 }
1378 }
1379 }
1380
1381 // unique limit type item
1382 int32 limit_newcount = 0;
1383 if (iGemProto->ItemLimitCategory)
1384 {
1385 if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->ItemLimitCategory))
1386 {
1387 // NOTE: limitEntry->mode is not checked because if item has limit then it is applied in equip case
1388 for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
1389 {
1390 if (Gems[j])
1391 {
1392 // new gem
1393 if (iGemProto->ItemLimitCategory == Gems[j]->GetTemplate()->ItemLimitCategory)
1394 ++limit_newcount;
1395 }
1396 else if (OldEnchants[j])
1397 {
1398 // existing gem
1399 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
1400 if (ItemTemplate const* jProto = sObjectMgr->GetItemTemplate(enchantEntry->GemID))
1401 if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory)
1402 ++limit_newcount;
1403 }
1404 }
1405
1406 if (limit_newcount > 0 && uint32(limit_newcount) > limitEntry->maxCount)
1407 {
1408 _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL);
1409 return;
1410 }
1411 }
1412 }
1413
1414 // for equipped item check all equipment for duplicate equipped gems
1415 if (itemTarget->IsEquipped())
1416 {
1417 if (InventoryResult res = _player->CanEquipUniqueItem(Gems[i], slot, std::max(limit_newcount, 0)))
1418 {
1419 _player->SendEquipError(res, itemTarget, NULL);
1420 return;
1421 }
1422 }
1423 }
1424
1425 bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus
1426 _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item)
1427
1428 //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met
1429
1430 //remove ALL enchants
1431 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
1432 _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), false);
1433
1434 for (int i = 0; i < MAX_GEM_SOCKETS; ++i)
1435 {
1436 if (GemEnchants[i])
1437 {
1438 itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + i), GemEnchants[i], 0, 0, _player->GetGUID());
1439 if (Item* guidItem = _player->GetItemByGuid(gem_guids[i]))
1440 {
1441 uint32 gemCount = 1;
1442 _player->DestroyItemCount(guidItem, gemCount, true);
1443 }
1444 }
1445 }
1446
1447 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
1448 _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), true);
1449
1450 bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
1451 if (SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change...
1452 {
1453 _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false);
1454 itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->socketBonus : 0), 0, 0, _player->GetGUID());
1455 _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, true);
1456 //it is not displayed, client has an inbuilt system to determine if the bonus is activated
1457 }
1458
1459 _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item)
1460
1461 _player->RemoveTradeableItem(itemTarget);
1462 itemTarget->ClearSoulboundTradeable(_player); // clear tradeable flag
1463
1464 SendUpdateSockets(itemTarget->GetGUID(), itemTarget);
1465}
1466
1468{
1469 WorldPacket data(SMSG_SOCKET_GEMS_RESULT, 8 + 4 + 4 + 4 + 4);
1470 data.WriteGuidMask(ItemGUID, 2, 5, 7, 6, 0, 1, 3, 4);
1471 data.WriteGuidBytes(ItemGUID, 2);
1473 data.WriteGuidBytes(ItemGUID, 3, 7, 4);
1474
1476 data << uint32(item->GetEnchantmentId(EnchantmentSlot(i)));
1477
1478 data.WriteGuidBytes(5, 0, 1, 6);
1479 SendPacket(&data);
1480}
1481
1483{
1484 SF_LOG_DEBUG("network", "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");
1485
1486 uint32 slot;
1487
1488 recvData >> slot;
1489
1490 // apply only to equipped item
1492 return;
1493
1495
1496 if (!item)
1497 return;
1498
1500 return;
1501
1504}
1505
1507{
1508 SF_LOG_DEBUG("network", "WORLD: CMSG_GET_ITEM_PURCHASE_DATA");
1509
1510 ObjectGuid guid;
1511
1512 recvData.ReadGuidMask(guid, 1, 0, 3, 2, 7, 4, 5, 6);
1513 recvData.ReadGuidBytes(guid, 3, 7, 5, 1, 0, 6, 4, 2);
1514
1515 Item* item = _player->GetItemByGuid(guid);
1516 if (!item)
1517 {
1518 SF_LOG_DEBUG("network", "Item refund: item not found!");
1519 return;
1520 }
1521
1522 GetPlayer()->SendRefundInfo(item);
1523}
1524
1526{
1527 SF_LOG_DEBUG("network", "WORLD: CMSG_ITEM_REFUND");
1528 ObjectGuid guid;
1529 recvData.ReadGuidMask(guid, 2, 4, 1, 6, 3, 0, 5, 7);
1530 recvData.ReadGuidBytes(guid, 3, 5, 6, 2, 7, 0, 1, 4);
1531
1532 Item* item = _player->GetItemByGuid(guid);
1533 if (!item)
1534 {
1535 SF_LOG_DEBUG("network", "Item refund: item not found!");
1536 return;
1537 }
1538
1539 GetPlayer()->RefundItem(item);
1540}
1541
1548{
1549 uint64 itemGuid;
1550 recvData >> itemGuid;
1551
1552 SF_LOG_DEBUG("network", "CMSG_ITEM_TEXT_QUERY item guid: %u", GUID_LOPART(itemGuid));
1553
1554 WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, 14); // guess size
1555
1556 if (Item* item = _player->GetItemByGuid(itemGuid))
1557 {
1558 data << uint8(0); // has text
1559 data << uint64(itemGuid); // item guid
1560 data << item->GetText();
1561 }
1562 else
1563 {
1564 data << uint8(1); // no text
1565 }
1566
1567 SendPacket(&data);
1568}
1569
1571{
1572 SF_LOG_DEBUG("network", "WORLD: Received CMSG_TRANSMOGRIFY_ITEMS");
1573 Player* player = GetPlayer();
1574
1575 // Read data
1576 uint32 count;
1577 ObjectGuid npcGuid;
1578
1579 npcGuid[5] = recvData.ReadBit();
1580 npcGuid[6] = recvData.ReadBit();
1581 npcGuid[1] = recvData.ReadBit();
1582 npcGuid[2] = recvData.ReadBit();
1583 npcGuid[3] = recvData.ReadBit();
1584 npcGuid[4] = recvData.ReadBit();
1585 count = recvData.ReadBits(21);
1586
1587 std::vector<ObjectGuid>itemGuids(count, ObjectGuid(0));
1588 std::vector<uint32>newEntries(count, 0);
1589 std::vector<uint32>slots(count, 0);
1590 std::vector<bool>HasItemBonus(count, false);
1591 std::vector<bool>HasModifications(count, false);
1592
1593 for (uint8 i = 0; i < count; ++i)
1594 {
1595 HasItemBonus[i] = recvData.ReadBit();
1596 HasModifications[i] = recvData.ReadBit();
1597 }
1598
1599 if (count >= EQUIPMENT_SLOT_END)
1600 {
1601 SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) sent a wrong count (%u) when transmogrifying items.", player->GetGUIDLow(), player->GetName().c_str(), count);
1602 recvData.rfinish();
1603 return;
1604 }
1605
1606 npcGuid[0] = recvData.ReadBit();
1607 npcGuid[7] = recvData.ReadBit();
1608
1609 for (uint8 i = 0; i < count; ++i)
1610 {
1611 if (HasModifications[i])
1612 {
1613 itemGuids[i][5] = recvData.ReadBit();
1614 itemGuids[i][6] = recvData.ReadBit();
1615 itemGuids[i][1] = recvData.ReadBit();
1616 itemGuids[i][3] = recvData.ReadBit();
1617 itemGuids[i][0] = recvData.ReadBit();
1618 itemGuids[i][4] = recvData.ReadBit();
1619 itemGuids[i][7] = recvData.ReadBit();
1620 itemGuids[i][2] = recvData.ReadBit();
1621 }
1622
1623 if (HasItemBonus[i])
1624 {
1625 itemGuids[i][4] = recvData.ReadBit();
1626 itemGuids[i][1] = recvData.ReadBit();
1627 itemGuids[i][0] = recvData.ReadBit();
1628 itemGuids[i][6] = recvData.ReadBit();
1629 itemGuids[i][5] = recvData.ReadBit();
1630 itemGuids[i][2] = recvData.ReadBit();
1631 itemGuids[i][7] = recvData.ReadBit();
1632 itemGuids[i][3] = recvData.ReadBit();
1633 }
1634 }
1635
1636 for (uint8 i = 0; i < count; ++i)
1637 {
1638 recvData >> slots[i];
1639 recvData >> newEntries[i];
1640 }
1641
1642 recvData.ReadByteSeq(npcGuid[5]);
1643 recvData.ReadByteSeq(npcGuid[0]);
1644 recvData.ReadByteSeq(npcGuid[1]);
1645 recvData.ReadByteSeq(npcGuid[2]);
1646 recvData.ReadByteSeq(npcGuid[3]);
1647 recvData.ReadByteSeq(npcGuid[4]);
1648 recvData.ReadByteSeq(npcGuid[6]);
1649 recvData.ReadByteSeq(npcGuid[7]);
1650
1651 for (uint8 i = 0; i < count; ++i)
1652 {
1653 if (HasModifications[i])
1654 {
1655 recvData.ReadByteSeq(itemGuids[i][2]);
1656 recvData.ReadByteSeq(itemGuids[i][5]);
1657 recvData.ReadByteSeq(itemGuids[i][4]);
1658 recvData.ReadByteSeq(itemGuids[i][3]);
1659 recvData.ReadByteSeq(itemGuids[i][6]);
1660 recvData.ReadByteSeq(itemGuids[i][0]);
1661 recvData.ReadByteSeq(itemGuids[i][7]);
1662 recvData.ReadByteSeq(itemGuids[i][1]);
1663 }
1664
1665 if (HasItemBonus[i])
1666 {
1667 recvData.ReadByteSeq(itemGuids[i][7]);
1668 recvData.ReadByteSeq(itemGuids[i][1]);
1669 recvData.ReadByteSeq(itemGuids[i][6]);
1670 recvData.ReadByteSeq(itemGuids[i][5]);
1671 recvData.ReadByteSeq(itemGuids[i][4]);
1672 recvData.ReadByteSeq(itemGuids[i][3]);
1673 recvData.ReadByteSeq(itemGuids[i][0]);
1674 recvData.ReadByteSeq(itemGuids[i][2]);
1675 }
1676 }
1677
1679 {
1680 SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid));
1681 return;
1682 }
1683
1684 int32 cost = 0;
1685 for (uint8 i = 0; i < count; ++i)
1686 {
1687 // slot of the transmogrified item
1688 if (slots[i] >= EQUIPMENT_SLOT_END)
1689 {
1690 SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an item (lowguid: %u) with a wrong slot (%u) when transmogrifying items.", player->GetGUIDLow(), player->GetName().c_str(), GUID_LOPART(itemGuids[i]), slots[i]);
1691 return;
1692 }
1693
1694 // entry of the transmogrifier item, if it's not 0
1695 if (newEntries[i])
1696 {
1697 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(newEntries[i]);
1698 if (!proto)
1699 {
1700 SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify to an invalid item (entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), newEntries[i]);
1701 return;
1702 }
1703 }
1704
1705 Item* itemTransmogrifier = NULL;
1706 // guid of the transmogrifier item, if it's not 0
1707 if (itemGuids[i])
1708 {
1709 itemTransmogrifier = player->GetItemByGuid(itemGuids[i]);
1710 if (!itemTransmogrifier)
1711 {
1712 SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid item (lowguid: %u).", player->GetGUIDLow(), player->GetName().c_str(), GUID_LOPART(itemGuids[i]));
1713 return;
1714 }
1715 }
1716
1717 // transmogrified item
1718 Item* itemTransmogrified = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slots[i]);
1719 if (!itemTransmogrified)
1720 {
1721 SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i]);
1722 return;
1723 }
1724
1725 // uint16 tempDest;
1727 //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrified, true, true))
1728 //{
1729 // SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the item to be transmogrified (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i], itemTransmogrified->GetEntry());
1730 // return;
1731 //}
1732 //
1734 //if (!player->CanEquipItem(slots[i], tempDest, itemTransmogrifier, true, true))
1735 //{
1736 // SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) can't equip the transmogrifier item (slot: %u, entry: %u).", player->GetGUIDLow(), player->GetName().c_str(), slots[i], itemTransmogrifier->GetEntry());
1737 // return;
1738 //}
1739
1740 if (!newEntries[i]) // reset look
1741 {
1742 itemTransmogrified->SetDynamicUInt32Value(ITEM_DYNAMIC_MODIFIERS, 1, 0);
1743 itemTransmogrified->RemoveFlag(ITEM_FIELD_MODIFIERS_MASK, 3);
1744 itemTransmogrified->SetState(ITEM_CHANGED, player);
1745 player->SetVisibleItemSlot(slots[i], itemTransmogrified);
1746 }
1747 else
1748 {
1749 if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, itemTransmogrifier))
1750 {
1751 SF_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUIDLow(), player->GetName().c_str(), itemTransmogrified->GetEntry(), itemTransmogrifier->GetEntry());
1752 return;
1753 }
1754
1755 // All okay, proceed
1756 itemTransmogrified->SetDynamicUInt32Value(ITEM_DYNAMIC_MODIFIERS, 1, newEntries[i]);
1757 itemTransmogrified->SetFlag(ITEM_FIELD_MODIFIERS_MASK, 3);
1758 player->SetVisibleItemSlot(slots[i], itemTransmogrified);
1759
1760 itemTransmogrified->UpdatePlayedTime(player);
1761
1762 itemTransmogrified->SetOwnerGUID(player->GetGUID());
1763 itemTransmogrified->SetNotRefundable(player);
1764 itemTransmogrified->ClearSoulboundTradeable(player);
1765
1766 if (itemTransmogrifier->GetTemplate()->Bonding == BIND_WHEN_EQUIPED || itemTransmogrifier->GetTemplate()->Bonding == BIND_WHEN_USE)
1767 itemTransmogrifier->SetBinding(true);
1768
1769 itemTransmogrifier->SetOwnerGUID(player->GetGUID());
1770 itemTransmogrifier->SetNotRefundable(player);
1771 itemTransmogrifier->ClearSoulboundTradeable(player);
1772
1773 itemTransmogrified->SetState(ITEM_CHANGED, player);
1774
1775 cost += itemTransmogrified->GetSpecialPrice();
1776 }
1777 }
1778
1779 // trusting the client, if it got here it has to have enough money
1780 // ... unless client was modified
1781 if (cost) // 0 cost if reverting look
1782 player->ModifyMoney(-cost);
1783}
1784
1786{
1787 uint32 slot, reforgeEntry;
1788 ObjectGuid guid;
1789 uint32 bag;
1790 Player* player = GetPlayer();
1791
1792 recvData >> reforgeEntry >> bag >> slot;
1793
1794 recvData.ReadGuidMask(guid, 1, 0, 5, 3, 4, 2, 7, 6);
1795 recvData.ReadGuidBytes(guid, 4, 6, 3, 1, 2, 7, 0, 5);
1796
1798 {
1799 SF_LOG_INFO("network", "WORLD: HandleReforgeItemOpcode - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(guid));
1800 SendReforgeResult(false);
1801 return;
1802 }
1803
1804 Item* item = player->GetItemByPos(bag, slot);
1805
1806 if (!item)
1807 {
1808 SF_LOG_INFO("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an invalid/non-existant item.", player->GetGUIDLow(), player->GetName().c_str());
1809 SendReforgeResult(false);
1810 return;
1811 }
1812
1813 if (!reforgeEntry)
1814 {
1815 // Reset the item
1816 if (item->IsEquipped())
1817 player->ApplyReforgeEnchantment(item, false);
1819 if (!item->GetDynamicUInt32Value(ITEM_DYNAMIC_MODIFIERS, 1)) // check transmog on item before remove
1821 item->SetState(ITEM_CHANGED, player);
1822 SendReforgeResult(true);
1823 return;
1824 }
1825
1826 ItemReforgeEntry const* stats = sItemReforgeStore.LookupEntry(reforgeEntry);
1827 if (!stats)
1828 {
1829 SF_LOG_INFO("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an item with invalid reforge entry (%u).", player->GetGUIDLow(), player->GetName().c_str(), reforgeEntry);
1830 SendReforgeResult(false);
1831 return;
1832 }
1833
1834 if (!item->GetReforgableStat(ItemModType(stats->SourceStat)) || item->GetReforgableStat(ItemModType(stats->FinalStat))) // Cheating, you cant reforge to a stat that the item already has, nor reforge from a stat that the item does not have
1835 {
1836 SendReforgeResult(false);
1837 return;
1838 }
1839
1840 if (!player->HasEnoughMoney(uint64(item->GetSpecialPrice()))) // cheating
1841 {
1842 SendReforgeResult(false);
1843 return;
1844 }
1845
1846 player->ModifyMoney(-int64(item->GetSpecialPrice()));
1847
1848 item->SetDynamicUInt32Value(ITEM_DYNAMIC_MODIFIERS, 0, reforgeEntry);
1850 item->SetState(ITEM_CHANGED, player);
1851
1852 SendReforgeResult(true);
1853
1854 if (item->IsEquipped())
1855 player->ApplyReforgeEnchantment(item, true);
1856}
1857
1859{
1861 data.WriteBit(success);
1862 data.FlushBits();
1863 SendPacket(&data);
1864}
1865
1866
1868{
1870
1871 data.WriteGuidMask(itemGuid, 7, 4, 2, 6, 5, 3, 1, 0);
1872 data.WriteGuidBytes(itemGuid, 4, 0, 6, 7, 1, 2, 3, 5);
1873
1874 SendPacket(&data);
1875}
1876
1878{
1879 SF_LOG_DEBUG("network", "WORLD: Received CMSG_SET_LOOT_SPECIALIZATION");
1880
1881 uint32 lootSpecialization;
1882 recvData >> lootSpecialization;
1883
1884 // If client sends 0 when setting to current specialization.
1885 if (lootSpecialization)
1886 {
1887 auto specializationEntry = sChrSpecializationStore.LookupEntry(lootSpecialization);
1888 if (!specializationEntry)
1889 {
1890 SF_LOG_DEBUG("network", "Player tried to set their loot specialization to %u which doesn't exist!", lootSpecialization);
1891 return;
1892 }
1893
1894 if (GetPlayer()->getClass() != specializationEntry->classId)
1895 {
1896 SF_LOG_DEBUG("network", "Player tried to set their loot specialization to %u which isn't valid for their class!", lootSpecialization);
1897 return;
1898 }
1899 }
1900
1901 GetPlayer()->SetLootSpecialization(lootSpecialization);
1902}
@ CHAR_INS_CHAR_GIFT
#define sConditionMgr
std::list< Condition * > ConditionList
#define MAX_VENDOR_ITEMS
Definition Creature.h:424
@ ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT
Definition DBCEnums.h:210
@ ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS
Definition DBCEnums.h:223
@ ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM
Definition DBCEnums.h:252
DBCStorage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore(SpellItemEnchantmentfmt)
DBCStorage< ItemLimitCategoryEntry > sItemLimitCategoryStore(ItemLimitCategoryEntryfmt)
DBCStorage< BankBagSlotPricesEntry > sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt)
DBCStorage< GemPropertiesEntry > sGemPropertiesStore(GemPropertiesEntryfmt)
DBCStorage< ItemReforgeEntry > sItemReforgeStore(ItemReforgefmt)
DBCStorage< ChrSpecializationEntry > sChrSpecializationStore(ChrSpecializationfmt)
DBCStorage< CurrencyTypesEntry > sCurrencyTypesStore(CurrencyTypesfmt)
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
std::uint64_t uint64
Definition Define.h:76
std::int64_t int64
Definition Define.h:72
std::uint16_t uint16
Definition Define.h:78
@ BUY_ERR_NOT_ENOUGHT_MONEY
Definition Item.h:128
@ BUY_ERR_CANT_FIND_ITEM
Definition Item.h:126
#define MAX_GEM_SOCKETS
Definition Item.h:170
EnchantmentSlot
Definition Item.h:149
@ SOCK_ENCHANTMENT_SLOT_3
Definition Item.h:154
@ TEMP_ENCHANTMENT_SLOT
Definition Item.h:151
@ PRISMATIC_ENCHANTMENT_SLOT
Definition Item.h:156
@ SOCK_ENCHANTMENT_SLOT
Definition Item.h:152
@ BONUS_ENCHANTMENT_SLOT
Definition Item.h:155
InventoryResult
Definition Item.h:27
@ EQUIP_ERR_CANT_WRAP_BAGS
Definition Item.h:76
@ EQUIP_ERR_WRONG_SLOT
Definition Item.h:31
@ EQUIP_ERR_DROP_BOUND_ITEM
Definition Item.h:52
@ EQUIP_ERR_ITEM_NOT_FOUND
Definition Item.h:51
@ EQUIP_ERR_CANT_WRAP_BOUND
Definition Item.h:74
@ EQUIP_ERR_OK
Definition Item.h:28
@ EQUIP_ERR_CANT_SWAP
Definition Item.h:49
@ EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED
Definition Item.h:104
@ EQUIP_ERR_INTERNAL_BAG_ERROR
Definition Item.h:68
@ EQUIP_ERR_CANT_WRAP_EQUIPPED
Definition Item.h:72
@ EQUIP_ERR_CANT_WRAP_STACKABLE
Definition Item.h:71
@ EQUIP_ERR_CANT_WRAP_WRAPPED
Definition Item.h:73
@ EQUIP_ERR_CANT_WRAP_UNIQUE
Definition Item.h:75
@ ITEM_CHANGED
Definition Item.h:192
@ ITEM_NEW
Definition Item.h:193
@ SELL_ERR_CANT_FIND_ITEM
Definition Item.h:139
@ SELL_ERR_CANT_SELL_ITEM
Definition Item.h:140
@ SELL_ERR_CANT_FIND_VENDOR
Definition Item.h:141
@ ITEM_PROTO_FLAG_WRAPPER
@ ITEM_PROTO_FLAG_INDESTRUCTIBLE
@ ITEM_PROTO_FLAG_UNIQUE_EQUIPPED
ItemModType
@ ITEM_FLAGS_EXTRA_ALLIANCE_ONLY
@ ITEM_FLAGS_EXTRA_HORDE_ONLY
@ SOCKET_COLOR_META
@ SOCKET_COLOR_COGWHEEL
@ BIND_WHEN_EQUIPED
@ BIND_WHEN_USE
@ BIND_WHEN_PICKED_UP
@ ITEM_VENDOR_TYPE_ITEM
@ ITEM_VENDOR_TYPE_CURRENCY
@ ITEM_FLAG_WRAPPED
@ ITEM_FLAG_REFUNDABLE
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
uint32 GUID_LOPART(uint64 x)
#define sObjectMgr
Definition ObjectMgr.h:1617
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:777
@ BUYBACK_SLOT_START
Definition Player.h:738
@ ERR_BANKSLOT_FAILED_TOO_MANY
Definition Player.h:84
@ ERR_BANKSLOT_OK
Definition Player.h:87
@ ERR_BANKSLOT_INSUFFICIENT_FUNDS
Definition Player.h:85
@ EQUIPMENT_SLOT_END
Definition Player.h:708
#define INVENTORY_SLOT_BAG_0
Definition Player.h:684
@ ALLIANCE
@ HORDE
@ SPELL_AURA_MOD_VENDOR_ITEMS_PRICES
@ SPELL_AURA_FEIGN_DEATH
Skyfire::AutoPtr< Transaction, Skyfire::Mutex > SQLTransaction
Definition Transaction.h:42
@ UNIT_NPC_FLAG_REFORGER
Definition Unit.h:713
@ UNIT_NPC_FLAG_VENDOR
Definition Unit.h:694
@ UNIT_NPC_FLAG_TRANSMOGRIFIER
Definition Unit.h:714
@ NULL_BAG
Definition Unit.h:336
@ NULL_SLOT
Definition Unit.h:337
@ UNIT_STATE_DIED
Definition Unit.h:512
@ UNIT_STATE_MOVING
Definition Unit.h:542
@ ITEM_FIELD_MODIFIERS_MASK
@ ITEM_FIELD_GIFT_CREATOR
@ ITEM_FIELD_DYNAMIC_FLAGS
@ ITEM_DYNAMIC_MODIFIERS
@ PLAYER_FIELD_BUYBACK_PRICE
T CalculatePct(T base, U pct)
Definition Util.h:103
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
uint32 ReadBits(size_t bits)
Definition ByteBuffer.h:198
void ReadGuidBytes(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:256
void ReadByteSeq(uint8 &b)
Definition ByteBuffer.h:215
void append(T value)
Definition ByteBuffer.h:147
void rfinish()
Definition ByteBuffer.h:478
void ReadGuidMask(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:240
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
size_t size() const
Definition ByteBuffer.h:609
void WriteByteSeq(uint8 b)
Definition ByteBuffer.h:227
void FlushBits()
Definition ByteBuffer.h:154
bool ReadBit()
Definition ByteBuffer.h:180
VendorItemData const * GetVendorItems() const
uint32 GetVendorItemCurrentCount(VendorItem const *vItem)
Definition Item.h:202
uint8 GetSlot() const
Definition Item.h:265
int32 GetReforgableStat(ItemModType statType) const
Definition Item.cpp:1459
void SetNotRefundable(Player *owner, bool changestate=true, SQLTransaction *trans=NULL)
Definition Item.cpp:1111
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, uint64 caster=0)
Definition Item.cpp:856
void SetBinding(bool val)
Definition Item.h:217
void SetState(ItemUpdateState state, Player *forplayer=NULL)
Definition Item.cpp:667
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition Item.h:287
void SetOwnerGUID(uint64 guid)
Definition Item.h:214
void RemoveFromUpdateQueueOf(Player *player)
Definition Item.cpp:714
Item * CloneItem(uint32 count, Player const *player=NULL) const
Definition Item.cpp:1039
virtual void SaveToDB(SQLTransaction &trans)
Definition Item.cpp:305
void SetCount(uint32 value)
Definition Item.h:259
ItemTemplate const * GetTemplate() const
Definition Item.cpp:528
bool IsSoulBound() const
Definition Item.h:218
ItemUpdateState GetState() const
Definition Item.h:305
static uint32 GetSpecialPrice(ItemTemplate const *proto, uint32 minimumPrice=10000)
Definition Item.cpp:1425
bool IsEquipped() const
Definition Item.cpp:739
void UpdatePlayedTime(Player *owner)
Definition Item.cpp:1129
static bool CanTransmogrifyItemWithItem(Item const *transmogrified, Item const *transmogrifier)
Definition Item.cpp:1255
uint16 GetPos() const
Definition Item.h:269
bool GemsFitSockets() const
Definition Item.cpp:907
bool IsBag() const
Definition Item.h:244
void ClearEnchantment(EnchantmentSlot slot)
Definition Item.cpp:897
uint64 GetOwnerGUID() const
Definition Item.h:213
void ClearSoulboundTradeable(Player *currentOwner)
Definition Item.cpp:1175
bool IsNotEmptyBag() const
Definition Item.cpp:280
uint32 GetCount() const
Definition Item.h:258
uint8 GetBagSlot() const
Definition Item.cpp:734
uint32 GetMaxStackCount() const
Definition Item.h:260
uint64 GetGUID() const
Definition Object.h:119
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:325
uint32 GetGUIDLow() const
Definition Object.h:120
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:1280
uint32 GetDynamicUInt32Value(uint32 tab, uint16 index) const
Definition Object.cpp:357
uint32 GetEntry() const
Definition Object.h:125
uint64 GetUInt64Value(uint16 index) const
Definition Object.cpp:331
void SetDynamicUInt32Value(uint32 tab, uint16 index, uint32 value)
Definition Object.cpp:1055
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
void SetEntry(uint32 entry)
Definition Object.h:126
void SendUpdateToPlayer(Player *player)
Definition Object.cpp:259
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
void SetUInt64Value(uint16 index, uint64 value)
Definition Object.cpp:1079
bool BuyCurrencyFromVendorSlot(ObjectGuid VendorGUID, uint32 vendorSlot, uint32 currency, uint32 count)
Definition Player.cpp:17023
void SendEquipError(InventoryResult msg, Item *pItem, Item *pItem2=NULL, uint32 itemid=0)
static bool IsEquipmentPos(uint16 pos)
Definition Player.h:1536
bool ModifyMoney(int64 amount, bool sendError=true)
Definition Player.cpp:18342
void SetLootSpecialization(uint32 specialization)
Definition Player.cpp:23886
void ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool apply_dur=true, bool ignore_condition=false)
Definition Player.cpp:11168
void SwapItem(uint16 src, uint16 dst)
Item * GetItemByGuid(uint64 guid) const
Item * GetItemByPos(uint16 pos) const
void ApplyReforgeEnchantment(Item *item, bool apply)
Definition Player.cpp:10919
Creature * GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
Definition Player.cpp:2836
void SendRefundInfo(Item *item)
Definition Player.cpp:22163
void SendMessageToSet(WorldPacket *data, bool self) override
Definition Player.h:2443
void RefundItem(Item *item)
Definition Player.cpp:22304
void SetVisibleItemSlot(uint8 slot, Item *pItem)
bool BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot)
Definition Player.cpp:17183
bool HasEnoughMoney(uint64 amount) const
Definition Player.h:1950
void setUInt32(const uint8 index, const uint32 value)
bool IsArmorer() const
Definition Unit.h:1877
void StopMoving()
-------—End of Pet responses methods-------—
Definition Unit.cpp:5877
void RemoveAurasByType(AuraType auraType, uint64 casterGUID=0, Aura *except=NULL, bool negative=true, bool positive=true)
bool HasUnitState(const uint32 f) const
Definition Unit.h:1485
std::string const & GetName() const
Definition Object.h:664
void Initialize(Opcodes opcode, size_t newres=200)
Definition WorldPacket.h:31
void HandleDestroyItemOpcode(WorldPacket &recvPacket)
void HandleBuyBankSlotOpcode(WorldPacket &recvPacket)
void HandleSocketOpcode(WorldPacket &recvData)
void HandleSellItemOpcode(WorldPacket &recvPacket)
void HandleSwapItem(WorldPacket &recvPacket)
void HandleAutoStoreBagItemOpcode(WorldPacket &recvPacket)
void HandleWrapItemOpcode(WorldPacket &recvPacket)
void HandleAutoStoreBankItemOpcode(WorldPacket &recvPacket)
void HandleItemRefund(WorldPacket &recvData)
Player * GetPlayer() const
void HandleAutoEquipItemSlotOpcode(WorldPacket &recvPacket)
void HandleItemRefundInfoRequest(WorldPacket &recvData)
void HandleSwapInvItemOpcode(WorldPacket &recvPacket)
void HandleAutoEquipItemOpcode(WorldPacket &recvPacket)
void SendItemEnchantTimeUpdate(ObjectGuid Playerguid, ObjectGuid Itemguid, uint32 slot, uint32 Duration)
void HandleReforgeItemOpcode(WorldPacket &recvData)
void HandleReadItem(WorldPacket &recvPacket)
void HandleTransmogrifyItems(WorldPacket &recvData)
void HandleBuyItemOpcode(WorldPacket &recvPacket)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void HandleSplitItemOpcode(WorldPacket &recvPacket)
Player * _player
void SendUpdateSockets(ObjectGuid ItemGUID, Item *item)
void SendItemExpirePurchaseRefund(ObjectGuid itemGuid)
void HandleAutoBankItemOpcode(WorldPacket &recvPacket)
void HandleBuyItemInSlotOpcode(WorldPacket &recvPacket)
void HandleCancelTempEnchantmentOpcode(WorldPacket &recvData)
void HandleItemTextQuery(WorldPacket &recvData)
void SendListInventory(uint64 guid)
void SendReforgeResult(bool success)
void HandleBuybackItem(WorldPacket &recvPacket)
void HandleListInventoryOpcode(WorldPacket &recvPacket)
void SendEnchantmentLog(uint64 target, uint64 caster, uint64 itemGuid, uint32 itemId, uint32 enchantId, uint32 enchantmentSlot)
void HandleSetLootSpecialization(WorldPacket &recvData)
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
@ SMSG_READ_ITEM_RESULT_FAILED
Definition Opcodes.h:927
@ SMSG_ITEM_EXPIRE_PURCHASE_REFUND
Definition Opcodes.h:730
@ SMSG_ENCHANTMENT_LOG
Definition Opcodes.h:649
@ SMSG_SOCKET_GEMS_RESULT
Definition Opcodes.h:969
@ SMSG_READ_ITEM_RESULT_OK
Definition Opcodes.h:928
@ SMSG_LIST_INVENTORY
Definition Opcodes.h:757
@ SMSG_REFORGE_RESULT
Definition Opcodes.h:933
@ SMSG_BUY_BANK_SLOT_RESULT
Definition Opcodes.h:570
@ SMSG_ITEM_TEXT_QUERY_RESPONSE
Definition Opcodes.h:733
@ SMSG_ITEM_ENCHANT_TIME_UPDATE
Definition Opcodes.h:729
uint32 Color
uint32 price
uint32 color
uint32 SourceStat
uint32 FinalStat
uint32 AllowableClass
uint32 DisplayInfoID
uint32 ItemLimitCategory
_Socket Socket[MAX_ITEM_PROTO_SOCKETS]
uint32 GetItemCount() const
Definition Creature.h:364
VendorItem * GetItem(uint32 slot) const
Definition Creature.h:356
uint32 ExtendedCost
Definition Creature.h:344
bool IsGoldRequired(ItemTemplate const *pProto) const
Definition Creature.h:348
uint32 item
Definition Creature.h:341
uint32 maxcount
Definition Creature.h:342
uint8 Type
Definition Creature.h:345