root/trunk/src/game/ItemHandler.cpp @ 207

Revision 207, 41.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Improve some arena team related DB access
* Cache GM tickets on server startup.
* Remove unused src/game/HateMatrix.h and references.
* Better check client inventory pos data received in some client packets to
skip invalid cases

Original author: KingPin?
Date: 2008-11-10 09:04:23-06:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "Common.h"
22#include "WorldPacket.h"
23#include "WorldSession.h"
24#include "World.h"
25#include "Opcodes.h"
26#include "Log.h"
27#include "ObjectMgr.h"
28#include "Player.h"
29#include "Item.h"
30#include "UpdateData.h"
31#include "ObjectAccessor.h"
32
33void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data )
34{
35    CHECK_PACKET_SIZE(recv_data,1+1+1+1+1);
36
37    //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM");
38    uint8 srcbag, srcslot, dstbag, dstslot, count;
39
40    recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count;
41    //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count);
42
43    uint16 src = ( (srcbag << 8) | srcslot );
44    uint16 dst = ( (dstbag << 8) | dstslot );
45
46    if(src==dst)
47        return;
48
49    if (count==0)
50        return;                                             //check count - if zero it's fake packet
51
52    if(!_player->IsValidPos(srcbag,srcslot))
53    {
54        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
55        return;
56    }
57
58    if(!_player->IsValidPos(dstbag,dstslot))
59    {
60        _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
61        return;
62    }
63
64    _player->SplitItem( src, dst, count );
65}
66
67void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data )
68{
69    CHECK_PACKET_SIZE(recv_data,1+1);
70
71    //sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM");
72    uint8 srcslot, dstslot;
73
74    recv_data >> srcslot >> dstslot;
75    //sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
76
77    // prevent attempt swap same item to current position generated by client at special checting sequence
78    if(srcslot==dstslot)
79        return;
80
81    if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
82    {
83        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
84        return;
85    }
86
87    if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
88    {
89        _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
90        return;
91    }
92
93    uint16 src = ( (INVENTORY_SLOT_BAG_0 << 8) | srcslot );
94    uint16 dst = ( (INVENTORY_SLOT_BAG_0 << 8) | dstslot );
95
96    _player->SwapItem( src, dst );
97}
98
99void WorldSession::HandleAutoEquipItemSlotOpcode( WorldPacket & recv_data )
100{
101    CHECK_PACKET_SIZE(recv_data,8+1);
102    uint64 itemguid;
103    uint8 dstslot;
104    recv_data >> itemguid >> dstslot;
105
106    // cheating attempt, client should never send opcode in that case
107    if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, dstslot))
108        return;
109
110    Item* item = _player->GetItemByGuid(itemguid);
111    uint16 dstpos = dstslot | (INVENTORY_SLOT_BAG_0 << 8);
112
113    if(!item || item->GetPos() == dstpos)
114        return;
115
116    _player->SwapItem(item->GetPos(), dstpos);
117}
118
119void WorldSession::HandleSwapItem( WorldPacket & recv_data )
120{
121    CHECK_PACKET_SIZE(recv_data,1+1+1+1);
122
123    //sLog.outDebug("WORLD: CMSG_SWAP_ITEM");
124    uint8 dstbag, dstslot, srcbag, srcslot;
125
126    recv_data >> dstbag >> dstslot >> srcbag >> srcslot ;
127    //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot);
128
129    uint16 src = ( (srcbag << 8) | srcslot );
130    uint16 dst = ( (dstbag << 8) | dstslot );
131
132    // prevent attempt swap same item to current position generated by client at special checting sequence
133    if(src==dst)
134        return;
135
136    if(!_player->IsValidPos(srcbag,srcslot))
137    {
138        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
139        return;
140    }
141
142    if(!_player->IsValidPos(dstbag,dstslot))
143    {
144        _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
145        return;
146    }
147
148    _player->SwapItem( src, dst );
149}
150
151void WorldSession::HandleAutoEquipItemOpcode( WorldPacket & recv_data )
152{
153    CHECK_PACKET_SIZE(recv_data,1+1);
154
155    //sLog.outDebug("WORLD: CMSG_AUTOEQUIP_ITEM");
156    uint8 srcbag, srcslot;
157
158    recv_data >> srcbag >> srcslot;
159    //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
160
161    Item *pSrcItem  = _player->GetItemByPos( srcbag, srcslot );
162    if( !pSrcItem )
163        return;                                             // only at cheat
164
165    if(pSrcItem->m_lootGenerated)                           // prevent swap looting item
166    {
167        //best error message found for attempting to swap while looting
168        _player->SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL );
169        return;
170    }
171
172    uint16 dest;
173    uint8 msg = _player->CanEquipItem( NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag() );
174    if( msg != EQUIP_ERR_OK )
175    {
176        _player->SendEquipError( msg, pSrcItem, NULL );
177        return;
178    }
179
180    uint16 src = pSrcItem->GetPos();
181    if(dest==src)                                           // prevent equip in same slot, only at cheat
182        return;
183
184    Item *pDstItem = _player->GetItemByPos( dest );
185    if( !pDstItem )                                         // empty slot, simple case
186    {
187        _player->RemoveItem( srcbag, srcslot, true );
188        _player->EquipItem( dest, pSrcItem, true );
189        _player->AutoUnequipOffhandIfNeed();
190    }
191    else                                                    // have currently equipped item, not simple case
192    {
193        uint8 dstbag = pDstItem->GetBagSlot();
194        uint8 dstslot = pDstItem->GetSlot();
195
196        msg = _player->CanUnequipItem( dest, !pSrcItem->IsBag() );
197        if( msg != EQUIP_ERR_OK )
198        {
199            _player->SendEquipError( msg, pDstItem, NULL );
200            return;
201        }
202
203        // check dest->src move possibility
204        ItemPosCountVec sSrc;
205        uint16 eSrc;
206        if( _player->IsInventoryPos( src ) )
207        {
208            msg = _player->CanStoreItem( srcbag, srcslot, sSrc, pDstItem, true );
209            if( msg != EQUIP_ERR_OK )
210                msg = _player->CanStoreItem( srcbag, NULL_SLOT, sSrc, pDstItem, true );
211            if( msg != EQUIP_ERR_OK )
212                msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, sSrc, pDstItem, true );
213        }
214        else if( _player->IsBankPos( src ) )
215        {
216            msg = _player->CanBankItem( srcbag, srcslot, sSrc, pDstItem, true );
217            if( msg != EQUIP_ERR_OK )
218                msg = _player->CanBankItem( srcbag, NULL_SLOT, sSrc, pDstItem, true );
219            if( msg != EQUIP_ERR_OK )
220                msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, sSrc, pDstItem, true );
221        }
222        else if( _player->IsEquipmentPos( src ) )
223        {
224            msg = _player->CanEquipItem( srcslot, eSrc, pDstItem, true);
225            if( msg == EQUIP_ERR_OK )
226                msg = _player->CanUnequipItem( eSrc, true);
227        }
228
229        if( msg != EQUIP_ERR_OK )
230        {
231            _player->SendEquipError( msg, pDstItem, pSrcItem );
232            return;
233        }
234
235        // now do moves, remove...
236        _player->RemoveItem(dstbag, dstslot, false);
237        _player->RemoveItem(srcbag, srcslot, false);
238
239        // add to dest
240        _player->EquipItem(dest, pSrcItem, true);
241
242        // add to src
243        if( _player->IsInventoryPos( src ) )
244            _player->StoreItem(sSrc, pDstItem, true);
245        else if( _player->IsBankPos( src ) )
246            _player->BankItem(sSrc, pDstItem, true);
247        else if( _player->IsEquipmentPos( src ) )
248            _player->EquipItem(eSrc, pDstItem, true);
249
250        _player->AutoUnequipOffhandIfNeed();
251    }
252}
253
254void WorldSession::HandleDestroyItemOpcode( WorldPacket & recv_data )
255{
256    CHECK_PACKET_SIZE(recv_data,1+1+1+1+1+1);
257
258    //sLog.outDebug("WORLD: CMSG_DESTROYITEM");
259    uint8 bag, slot, count, data1, data2, data3;
260
261    recv_data >> bag >> slot >> count >> data1 >> data2 >> data3;
262    //sLog.outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count);
263
264    uint16 pos = (bag << 8) | slot;
265
266    // prevent drop unequipable items (in combat, for example) and non-empty bags
267    if(_player->IsEquipmentPos(pos) || _player->IsBagPos(pos))
268    {
269        uint8 msg = _player->CanUnequipItem( pos, false );
270        if( msg != EQUIP_ERR_OK )
271        {
272            _player->SendEquipError( msg, _player->GetItemByPos(pos), NULL );
273            return;
274        }
275    }
276
277    Item *pItem  = _player->GetItemByPos( bag, slot );
278    if(!pItem)
279    {
280        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
281        return;
282    }
283
284    if(count)
285    {
286        uint32 i_count = count;
287        _player->DestroyItemCount( pItem, i_count, true );
288    }
289    else
290        _player->DestroyItem( bag, slot, true );
291}
292
293// Only _static_ data send in this packet !!!
294void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
295{
296    CHECK_PACKET_SIZE(recv_data, 4);
297
298    //sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE");
299    uint32 item;
300    recv_data >> item;
301
302    sLog.outDetail("STORAGE: Item Query = %u", item);
303
304    ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
305    if( pProto )
306    {
307        std::string Name        = pProto->Name1;
308        std::string Description = pProto->Description;
309
310        int loc_idx = GetSessionDbLocaleIndex();
311        if ( loc_idx >= 0 )
312        {
313            ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId);
314            if (il)
315            {
316                if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty())
317                    Name = il->Name[loc_idx];
318                if (il->Description.size() > loc_idx && !il->Description[loc_idx].empty())
319                    Description = il->Description[loc_idx];
320            }
321        }
322                                                            // guess size
323        WorldPacket data( SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
324        data << pProto->ItemId;
325        data << pProto->Class;
326        data << pProto->SubClass;
327        data << uint32(-1);                                 // new 2.0.3, not exist in wdb cache?
328        data << Name;
329        data << uint8(0x00);                                //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
330        data << uint8(0x00);                                //pProto->Name3; // blizz not send name there, just uint8(0x00);
331        data << uint8(0x00);                                //pProto->Name4; // blizz not send name there, just uint8(0x00);
332        data << pProto->DisplayInfoID;
333        data << pProto->Quality;
334        data << pProto->Flags;
335        data << pProto->BuyPrice;
336        data << pProto->SellPrice;
337        data << pProto->InventoryType;
338        data << pProto->AllowableClass;
339        data << pProto->AllowableRace;
340        data << pProto->ItemLevel;
341        data << pProto->RequiredLevel;
342        data << pProto->RequiredSkill;
343        data << pProto->RequiredSkillRank;
344        data << pProto->RequiredSpell;
345        data << pProto->RequiredHonorRank;
346        data << pProto->RequiredCityRank;
347        data << pProto->RequiredReputationFaction;
348        data << pProto->RequiredReputationRank;
349        data << pProto->MaxCount;
350        data << pProto->Stackable;
351        data << pProto->ContainerSlots;
352        for(int i = 0; i < 10; i++)
353        {
354            data << pProto->ItemStat[i].ItemStatType;
355            data << pProto->ItemStat[i].ItemStatValue;
356        }
357        for(int i = 0; i < 5; i++)
358        {
359            data << pProto->Damage[i].DamageMin;
360            data << pProto->Damage[i].DamageMax;
361            data << pProto->Damage[i].DamageType;
362        }
363        data << pProto->Armor;
364        data << pProto->HolyRes;
365        data << pProto->FireRes;
366        data << pProto->NatureRes;
367        data << pProto->FrostRes;
368        data << pProto->ShadowRes;
369        data << pProto->ArcaneRes;
370        data << pProto->Delay;
371        data << pProto->Ammo_type;
372
373        data << (float)pProto->RangedModRange;
374        for(int s = 0; s < 5; s++)
375        {
376            // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
377            // use `item_template` or if not set then only use spell cooldowns
378            SpellEntry const* spell = sSpellStore.LookupEntry(pProto->Spells[s].SpellId);
379            if(spell)
380            {
381                bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0;
382
383                data << pProto->Spells[s].SpellId;
384                data << pProto->Spells[s].SpellTrigger;
385                data << uint32(-abs(pProto->Spells[s].SpellCharges));
386
387                if(db_data)
388                {
389                    data << uint32(pProto->Spells[s].SpellCooldown);
390                    data << uint32(pProto->Spells[s].SpellCategory);
391                    data << uint32(pProto->Spells[s].SpellCategoryCooldown);
392                }
393                else
394                {
395                    data << uint32(spell->RecoveryTime);
396                    data << uint32(spell->Category);
397                    data << uint32(spell->CategoryRecoveryTime);
398                }
399            }
400            else
401            {
402                data << uint32(0);
403                data << uint32(0);
404                data << uint32(0);
405                data << uint32(-1);
406                data << uint32(0);
407                data << uint32(-1);
408            }
409        }
410        data << pProto->Bonding;
411        data << Description;
412        data << pProto->PageText;
413        data << pProto->LanguageID;
414        data << pProto->PageMaterial;
415        data << pProto->StartQuest;
416        data << pProto->LockID;
417        data << pProto->Material;
418        data << pProto->Sheath;
419        data << pProto->RandomProperty;
420        data << pProto->RandomSuffix;
421        data << pProto->Block;
422        data << pProto->ItemSet;
423        data << pProto->MaxDurability;
424        data << pProto->Area;
425        data << pProto->Map;                                // Added in 1.12.x & 2.0.1 client branch
426        data << pProto->BagFamily;
427        data << pProto->TotemCategory;
428        for(int s = 0; s < 3; s++)
429        {
430            data << pProto->Socket[s].Color;
431            data << pProto->Socket[s].Content;
432        }
433        data << pProto->socketBonus;
434        data << pProto->GemProperties;
435        data << pProto->RequiredDisenchantSkill;
436        data << pProto->ArmorDamageModifier;
437        data << uint32(0);                                  // added in 2.4.2.8209, duration (seconds)
438        SendPacket( &data );
439    }
440    else
441    {
442        sLog.outDebug(  "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item );
443        WorldPacket data( SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4);
444        data << uint32(item | 0x80000000);
445        SendPacket( &data );
446    }
447}
448
449void WorldSession::HandleReadItem( WorldPacket & recv_data )
450{
451    CHECK_PACKET_SIZE(recv_data,1+1);
452
453    //sLog.outDebug( "WORLD: CMSG_READ_ITEM");
454
455    uint8 bag, slot;
456    recv_data >> bag >> slot;
457
458    //sLog.outDetail("STORAGE: Read bag = %u, slot = %u", bag, slot);
459    Item *pItem = _player->GetItemByPos( bag, slot );
460
461    if( pItem && pItem->GetProto()->PageText )
462    {
463        WorldPacket data;
464
465        uint8 msg = _player->CanUseItem( pItem );
466        if( msg == EQUIP_ERR_OK )
467        {
468            data.Initialize (SMSG_READ_ITEM_OK, 8);
469            sLog.outDetail("STORAGE: Item page sent");
470        }
471        else
472        {
473            data.Initialize( SMSG_READ_ITEM_FAILED, 8 );
474            sLog.outDetail("STORAGE: Unable to read item");
475            _player->SendEquipError( msg, pItem, NULL );
476        }
477        data << pItem->GetGUID();
478        SendPacket(&data);
479    }
480    else
481        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
482}
483
484void WorldSession::HandlePageQuerySkippedOpcode( WorldPacket & recv_data )
485{
486    CHECK_PACKET_SIZE(recv_data,4+8);
487
488    sLog.outDebug(  "WORLD: Received CMSG_PAGE_TEXT_QUERY" );
489
490    uint32 itemid;
491    uint64 guid;
492
493    recv_data >> itemid >> guid;
494
495    sLog.outDetail( "Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u",
496        itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid));
497}
498
499void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data )
500{
501    CHECK_PACKET_SIZE(recv_data,8+8+1);
502
503    sLog.outDebug(  "WORLD: Received CMSG_SELL_ITEM" );
504    uint64 vendorguid, itemguid;
505    uint8 _count;
506
507    recv_data >> vendorguid >> itemguid >> _count;
508
509    // prevent possible overflow, as Trinity uses uint32 for item count
510    uint32 count = _count;
511
512    if(!itemguid)
513        return;
514
515    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR);
516    if (!pCreature)
517    {
518        sLog.outDebug( "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
519        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0);
520        return;
521    }
522
523    // remove fake death
524    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
525        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
526
527    Item *pItem = _player->GetItemByGuid( itemguid );
528    if( pItem )
529    {
530        // prevent sell not owner item
531        if(_player->GetGUID()!=pItem->GetOwnerGUID())
532        {
533            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
534            return;
535        }
536
537        // prevent sell non empty bag by drag-and-drop at vendor's item list
538        if(pItem->IsBag() && !((Bag*)pItem)->IsEmpty())
539        {
540            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
541            return;
542        }
543
544        // prevent sell currently looted item
545        if(_player->GetLootGUID()==pItem->GetGUID())
546        {
547            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
548            return;
549        }
550
551        // special case at auto sell (sell all)
552        if(count==0)
553        {
554            count = pItem->GetCount();
555        }
556        else
557        {
558            // prevent sell more items that exist in stack (possable only not from client)
559            if(count > pItem->GetCount())
560            {
561                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
562                return;
563            }
564        }
565
566        ItemPrototype const *pProto = pItem->GetProto();
567        if( pProto )
568        {
569            if( pProto->SellPrice > 0 )
570            {
571                if(count < pItem->GetCount())               // need split items
572                {
573                    Item *pNewItem = pItem->CloneItem( count, _player );
574                    if (!pNewItem)
575                    {
576                        sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count );
577                        _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
578                        return;
579                    }
580
581                    pItem->SetCount( pItem->GetCount() - count );
582                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), count );
583                    if( _player->IsInWorld() )
584                        pItem->SendUpdateToPlayer( _player );
585                    pItem->SetState(ITEM_CHANGED, _player);
586
587                    _player->AddItemToBuyBackSlot( pNewItem );
588                    if( _player->IsInWorld() )
589                        pNewItem->SendUpdateToPlayer( _player );
590                }
591                else
592                {
593                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), pItem->GetCount());
594                    _player->RemoveItem( pItem->GetBagSlot(), pItem->GetSlot(), true);
595                    pItem->RemoveFromUpdateQueueOf(_player);
596                    _player->AddItemToBuyBackSlot( pItem );
597                }
598
599                _player->ModifyMoney( pProto->SellPrice * count );
600            }
601            else
602                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
603            return;
604        }
605    }
606    _player->SendSellError( SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0);
607    return;
608}
609
610void WorldSession::HandleBuybackItem(WorldPacket & recv_data)
611{
612    CHECK_PACKET_SIZE(recv_data,8+4);
613
614    sLog.outDebug(  "WORLD: Received CMSG_BUYBACK_ITEM" );
615    uint64 vendorguid;
616    uint32 slot;
617
618    recv_data >> vendorguid >> slot;
619
620    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR);
621    if (!pCreature)
622    {
623        sLog.outDebug( "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
624        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
625        return;
626    }
627
628    // remove fake death
629    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
630        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
631
632    Item *pItem = _player->GetItemFromBuyBackSlot( slot );
633    if( pItem )
634    {
635        uint32 price = _player->GetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START );
636        if( _player->GetMoney() < price )
637        {
638            _player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, pItem->GetEntry(), 0);
639            return;
640        }
641
642        ItemPosCountVec dest;
643        uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
644        if( msg == EQUIP_ERR_OK )
645        {
646            _player->ModifyMoney( -(int32)price );
647            _player->RemoveItemFromBuyBackSlot( slot, false );
648            _player->ItemAddedQuestCheck( pItem->GetEntry(), pItem->GetCount());
649            _player->StoreItem( dest, pItem, true );
650        }
651        else
652            _player->SendEquipError( msg, pItem, NULL );
653        return;
654    }
655    else
656        _player->SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, 0, 0);
657}
658
659void WorldSession::HandleBuyItemInSlotOpcode( WorldPacket & recv_data )
660{
661    CHECK_PACKET_SIZE(recv_data,8+4+8+1+1);
662
663    sLog.outDebug(  "WORLD: Received CMSG_BUY_ITEM_IN_SLOT" );
664    uint64 vendorguid, bagguid;
665    uint32 item;
666    uint8 slot, count;
667
668    recv_data >> vendorguid >> item >> bagguid >> slot >> count;
669
670    GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bagguid,slot);
671}
672
673void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data )
674{
675    CHECK_PACKET_SIZE(recv_data,8+4+1+1);
676
677    sLog.outDebug(  "WORLD: Received CMSG_BUY_ITEM" );
678    uint64 vendorguid;
679    uint32 item;
680    uint8 count, unk1;
681
682    recv_data >> vendorguid >> item >> count >> unk1;
683
684    GetPlayer()->BuyItemFromVendor(vendorguid,item,count,NULL_BAG,NULL_SLOT);
685}
686
687void WorldSession::HandleListInventoryOpcode( WorldPacket & recv_data )
688{
689    CHECK_PACKET_SIZE(recv_data,8);
690
691    uint64 guid;
692
693    recv_data >> guid;
694
695    if(!GetPlayer()->isAlive())
696        return;
697
698    sLog.outDebug(  "WORLD: Recvd CMSG_LIST_INVENTORY" );
699
700    SendListInventory( guid );
701}
702
703void WorldSession::SendListInventory( uint64 vendorguid )
704{
705    sLog.outDebug(  "WORLD: Sent SMSG_LIST_INVENTORY" );
706
707    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR);
708    if (!pCreature)
709    {
710        sLog.outDebug( "WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
711        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
712        return;
713    }
714
715    // remove fake death
716    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
717        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
718
719    // Stop the npc if moving
720    pCreature->StopMoving();
721
722    VendorItemData const* vItems = pCreature->GetVendorItems();
723    if(!vItems)
724    {
725        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
726        return;
727    }
728
729    uint8 numitems = vItems->GetItemCount();
730    uint8 count = 0;
731
732    WorldPacket data( SMSG_LIST_INVENTORY, (8+1+numitems*8*4) );
733    data << uint64(vendorguid);
734    data << uint8(numitems);
735
736    float discountMod = _player->GetReputationPriceDiscount(pCreature);
737
738    for(int i = 0; i < numitems; i++ )
739    {
740        if(VendorItem const* crItem = vItems->GetItem(i))
741        {
742            if(ItemPrototype const *pProto = objmgr.GetItemPrototype(crItem->item))
743            {
744                if((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster())
745                    continue;
746
747                ++count;
748
749                // reputation discount
750                uint32 price = uint32(floor(pProto->BuyPrice * discountMod));
751
752                data << uint32(count);
753                data << uint32(crItem->item);
754                data << uint32(pProto->DisplayInfoID);
755                data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem));
756                data << uint32(price);
757                data << uint32(pProto->MaxDurability);
758                data << uint32(pProto->BuyCount);
759                data << uint32(crItem->ExtendedCost);
760            }
761        }
762    }
763
764    if ( count == 0 || data.size() != 8 + 1 + size_t(count) * 8 * 4 )
765        return;
766
767    data.put<uint8>(8, count);
768    SendPacket( &data );
769}
770
771void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data )
772{
773    CHECK_PACKET_SIZE(recv_data,1+1+1);
774
775    //sLog.outDebug("WORLD: CMSG_AUTOSTORE_BAG_ITEM");
776    uint8 srcbag, srcslot, dstbag;
777
778    recv_data >> srcbag >> srcslot >> dstbag;
779    //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag);
780
781    Item *pItem = _player->GetItemByPos( srcbag, srcslot );
782    if( !pItem )
783        return;
784
785    if(!_player->IsValidPos(dstbag,NULL_SLOT))
786    {
787        _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
788        return;
789    }
790
791    uint16 src = pItem->GetPos();
792
793    // check unequip potability for equipped items and bank bags
794    if(_player->IsEquipmentPos ( src ) || _player->IsBagPos ( src ))
795    {
796        uint8 msg = _player->CanUnequipItem( src, !_player->IsBagPos ( src ));
797        if(msg != EQUIP_ERR_OK)
798        {
799            _player->SendEquipError( msg, pItem, NULL );
800            return;
801        }
802    }
803
804    ItemPosCountVec dest;
805    uint8 msg = _player->CanStoreItem( dstbag, NULL_SLOT, dest, pItem, false );
806    if( msg != EQUIP_ERR_OK )
807    {
808        _player->SendEquipError( msg, pItem, NULL );
809        return;
810    }
811
812    // no-op: placed in same slot
813    if(dest.size()==1 && dest[0].pos==src)
814    {
815        // just remove grey item state
816        _player->SendEquipError( EQUIP_ERR_NONE, pItem, NULL );
817        return;
818    }
819
820    _player->RemoveItem(srcbag, srcslot, true );
821    _player->StoreItem( dest, pItem, true );
822}
823
824void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/)
825{
826    sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT");
827
828    uint32 slot = _player->GetByteValue(PLAYER_BYTES_2, 2);
829
830    // next slot
831    ++slot;
832
833    sLog.outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot);
834
835    BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot);
836
837    if(!slotEntry)
838        return;
839
840    uint32 price = slotEntry->price;
841
842    if (_player->GetMoney() < price)
843        return;
844
845    _player->SetByteValue(PLAYER_BYTES_2, 2, slot);
846    _player->ModifyMoney(-int32(price));
847}
848
849void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket)
850{
851    CHECK_PACKET_SIZE(recvPacket,1+1);
852
853    sLog.outDebug("WORLD: CMSG_AUTOBANK_ITEM");
854    uint8 srcbag, srcslot;
855
856    recvPacket >> srcbag >> srcslot;
857    sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
858
859    Item *pItem = _player->GetItemByPos( srcbag, srcslot );
860    if( !pItem )
861        return;
862
863    ItemPosCountVec dest;
864    uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
865    if( msg != EQUIP_ERR_OK )
866    {
867        _player->SendEquipError( msg, pItem, NULL );
868        return;
869    }
870
871    _player->RemoveItem(srcbag, srcslot, true);
872    _player->BankItem( dest, pItem, true );
873}
874
875void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
876{
877    CHECK_PACKET_SIZE(recvPacket,1+1);
878
879    sLog.outDebug("WORLD: CMSG_AUTOSTORE_BANK_ITEM");
880    uint8 srcbag, srcslot;
881
882    recvPacket >> srcbag >> srcslot;
883    sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
884
885    Item *pItem = _player->GetItemByPos( srcbag, srcslot );
886    if( !pItem )
887        return;
888
889    if(_player->IsBankPos(srcbag, srcslot))                 // moving from bank to inventory
890    {
891        ItemPosCountVec dest;
892        uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
893        if( msg != EQUIP_ERR_OK )
894        {
895            _player->SendEquipError( msg, pItem, NULL );
896            return;
897        }
898
899        _player->RemoveItem(srcbag, srcslot, true);
900        _player->StoreItem( dest, pItem, true );
901    }
902    else                                                    // moving from inventory to bank
903    {
904        ItemPosCountVec dest;
905        uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
906        if( msg != EQUIP_ERR_OK )
907        {
908            _player->SendEquipError( msg, pItem, NULL );
909            return;
910        }
911
912        _player->RemoveItem(srcbag, srcslot, true);
913        _player->BankItem( dest, pItem, true );
914    }
915}
916
917void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data)
918{
919    CHECK_PACKET_SIZE(recv_data,4);
920
921    if(!GetPlayer()->isAlive())
922    {
923        GetPlayer()->SendEquipError( EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL );
924        return;
925    }
926
927    sLog.outDebug("WORLD: CMSG_SET_AMMO");
928    uint32 item;
929
930    recv_data >> item;
931
932    if(!item)
933        GetPlayer()->RemoveAmmo();
934    else
935        GetPlayer()->SetAmmo(item);
936}
937
938void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID)
939{
940    WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1));     // last check 2.0.10
941    data << Target;
942    data << Caster;
943    data << ItemID;
944    data << SpellID;
945    data << uint8(0);
946    SendPacket(&data);
947}
948
949void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration)
950{
951                                                            // last check 2.0.10
952    WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8));
953    data << uint64(Itemguid);
954    data << uint32(slot);
955    data << uint32(Duration);
956    data << uint64(Playerguid);
957    SendPacket(&data);
958}
959
960void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data)
961{
962    CHECK_PACKET_SIZE(recv_data,4);
963
964    uint32 itemid;
965    recv_data >> itemid;
966    sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid);
967    ItemPrototype const *pProto = objmgr.GetItemPrototype( itemid );
968    if( pProto )
969    {
970        std::string Name;
971        Name = pProto->Name1;
972
973        int loc_idx = GetSessionDbLocaleIndex();
974        if (loc_idx >= 0)
975        {
976            ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId);
977            if (il)
978            {
979                if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty())
980                    Name = il->Name[loc_idx];
981            }
982        }
983                                                            // guess size
984        WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+10));
985        data << uint32(pProto->ItemId);
986        data << Name;
987        data << uint32(pProto->InventoryType);
988        SendPacket(&data);
989        return;
990    }
991    else
992        sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (unknown item)", itemid);
993}
994
995void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data)
996{
997    CHECK_PACKET_SIZE(recv_data,1+1+1+1);
998
999    sLog.outDebug("Received opcode CMSG_WRAP_ITEM");
1000
1001    uint8 gift_bag, gift_slot, item_bag, item_slot;
1002    //recv_data.hexlike();
1003
1004    recv_data >> gift_bag >> gift_slot;                     // paper
1005    recv_data >> item_bag >> item_slot;                     // item
1006
1007    sLog.outDebug("WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot);
1008
1009    Item *gift = _player->GetItemByPos( gift_bag, gift_slot );
1010    if(!gift)
1011    {
1012        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL );
1013        return;
1014    }
1015
1016    if(!gift->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPER))// cheating: non-wrapper wrapper
1017    {
1018        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL );
1019        return;
1020    }
1021
1022    Item *item = _player->GetItemByPos( item_bag, item_slot );
1023
1024    if( !item )
1025    {
1026        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, item, NULL );
1027        return;
1028    }
1029
1030    if(item==gift)                                          // not possable with pacjket from real client
1031    {
1032        _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL );
1033        return;
1034    }
1035
1036    if(item->IsEquipped())
1037    {
1038        _player->SendEquipError( EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL );
1039        return;
1040    }
1041
1042    if(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR))        // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
1043    {
1044        _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL );
1045        return;
1046    }
1047
1048    if(item->IsBag())
1049    {
1050        _player->SendEquipError( EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL );
1051        return;
1052    }
1053
1054    if(item->IsSoulBound())
1055    {
1056        _player->SendEquipError( EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL );
1057        return;
1058    }
1059
1060    if(item->GetMaxStackCount() != 1)
1061    {
1062        _player->SendEquipError( EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL );
1063        return;
1064    }
1065
1066    // maybe not correct check  (it is better than nothing)
1067    if(item->GetProto()->MaxCount>0)
1068    {
1069        _player->SendEquipError( EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL );
1070        return;
1071    }
1072
1073    CharacterDatabase.BeginTransaction();
1074    CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS));
1075    item->SetUInt32Value(OBJECT_FIELD_ENTRY, gift->GetUInt32Value(OBJECT_FIELD_ENTRY));
1076
1077    switch (item->GetEntry())
1078    {
1079        case 5042:  item->SetUInt32Value(OBJECT_FIELD_ENTRY,  5043); break;
1080        case 5048:  item->SetUInt32Value(OBJECT_FIELD_ENTRY,  5044); break;
1081        case 17303: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17302); break;
1082        case 17304: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17305); break;
1083        case 17307: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 17308); break;
1084        case 21830: item->SetUInt32Value(OBJECT_FIELD_ENTRY, 21831); break;
1085    }
1086    item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
1087    item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
1088    item->SetState(ITEM_CHANGED, _player);
1089
1090    if(item->GetState()==ITEM_NEW)                          // save new item, to have alway for `character_gifts` record in `item_instance`
1091    {
1092        // after save it will be impossible to remove the item from the queue
1093        item->RemoveFromUpdateQueueOf(_player);
1094        item->SaveToDB();                                   // item gave inventory record unchanged and can be save standalone
1095    }
1096    CharacterDatabase.CommitTransaction();
1097
1098    uint32 count = 1;
1099    _player->DestroyItemCount(gift, count, true);
1100}
1101
1102void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
1103{
1104    sLog.outDebug("WORLD: CMSG_SOCKET_GEMS");
1105
1106    CHECK_PACKET_SIZE(recv_data,8*4);
1107
1108    uint64 guids[4];
1109    uint32 GemEnchants[3], OldEnchants[3];
1110    Item *Gems[3];
1111    bool SocketBonusActivated, SocketBonusToBeActivated;
1112
1113    for(int i = 0; i < 4; i++)
1114        recv_data >> guids[i];
1115
1116    if(!guids[0])
1117        return;
1118
1119    //cheat -> tried to socket same gem multiple times
1120    if((guids[1] && (guids[1] == guids[2] || guids[1] == guids[3])) || (guids[2] && (guids[2] == guids[3])))
1121        return;
1122
1123    Item *itemTarget = _player->GetItemByGuid(guids[0]);
1124    if(!itemTarget)                                         //missing item to socket
1125        return;
1126
1127    //this slot is excepted when applying / removing meta gem bonus
1128    uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT;
1129
1130    for(int i = 0; i < 3; i++)
1131        Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL;
1132
1133    GemPropertiesEntry const *GemProps[3];
1134    for(int i = 0; i < 3; ++i)                              //get geminfo from dbc storage
1135    {
1136        GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL;
1137    }
1138
1139    for(int i = 0; i < 3; ++i)                              //check for hack maybe
1140    {
1141        // tried to put gem in socket where no socket exists / tried to put normal gem in meta socket
1142        // tried to put meta gem in normal socket
1143        if( GemProps[i] && ( !itemTarget->GetProto()->Socket[i].Color ||
1144            itemTarget->GetProto()->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META ||
1145            itemTarget->GetProto()->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META ) )
1146            return;
1147    }
1148
1149    for(int i = 0; i < 3; ++i)                              //get new and old enchantments
1150    {
1151        GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
1152        OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i));
1153    }
1154
1155    // check unique-equipped conditions
1156    for(int i = 0; i < 3; ++i)
1157    {
1158        if (Gems[i] && (Gems[i]->GetProto()->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED))
1159        {
1160            // for equipped item check all equipment for duplicate equipped gems
1161            if(itemTarget->IsEquipped())
1162            {
1163                if(GetPlayer()->GetItemOrItemWithGemEquipped(Gems[i]->GetEntry()))
1164                {
1165                    _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE, itemTarget, NULL );
1166                    return;
1167                }
1168            }
1169
1170            // continue check for case when attempt add 2 similar unique equipped gems in one item.
1171            for (int j = 0; j < 3; ++j)
1172            {
1173                if ((i != j) && (Gems[j]) && (Gems[i]->GetProto()->ItemId == Gems[j]->GetProto()->ItemId))
1174                {
1175                    _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
1176                    return;
1177                }
1178            }
1179            for (int j = 0; j < 3; ++j)
1180            {
1181                if (OldEnchants[j])
1182                {
1183                    SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]);
1184                    if(!enchantEntry)
1185                        continue;
1186
1187                    if ((enchantEntry->GemID == Gems[i]->GetProto()->ItemId) && (i != j))
1188                    {
1189                        _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
1190                        return;
1191                    }
1192                }
1193            }
1194        }
1195    }
1196
1197    SocketBonusActivated = itemTarget->GemsFitSockets();    //save state of socketbonus
1198    _player->ToggleMetaGemsActive(slot, false);             //turn off all metagems (except for the target item)
1199
1200    //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
1201
1202    //remove ALL enchants
1203    for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
1204        _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false);
1205
1206    for(int i = 0; i < 3; ++i)
1207    {
1208        if(GemEnchants[i])
1209        {
1210            itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0);
1211            if(Item* guidItem = _player->GetItemByGuid(guids[i + 1]))
1212                _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true );
1213        }
1214    }
1215
1216    for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
1217        _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true);
1218
1219    SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
1220    if(SocketBonusActivated ^ SocketBonusToBeActivated)     //if there was a change...
1221    {
1222        _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false);
1223        itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0);
1224        _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,true);
1225        //it is not displayed, client has an inbuilt system to determine if the bonus is activated
1226    }
1227
1228    _player->ToggleMetaGemsActive(slot, true);              //turn on all metagems (except for target item)
1229}
1230
1231void WorldSession::HandleCancelTempItemEnchantmentOpcode(WorldPacket& recv_data)
1232{
1233    sLog.outDebug("WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");
1234
1235    CHECK_PACKET_SIZE(recv_data,4);
1236
1237    uint32 eslot;
1238
1239    recv_data >> eslot;
1240
1241    // apply only to equipped item
1242    if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0,eslot))
1243        return;
1244
1245    Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot);
1246
1247    if(!item)
1248        return;
1249
1250    if(!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
1251        return;
1252
1253    GetPlayer()->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1254    item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);
1255}
Note: See TracBrowser for help on using the browser.