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

Revision 260, 41.3 kB (checked in by yumileroy, 17 years ago)

*DB script table stucture change. Source Mangos. Also fix some bugs. Hopefully this rev will make program usable again.

Original author: megamage
Date: 2008-11-20 10:43:20-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() > size_t(loc_idx) && !il->Name[loc_idx].empty())
317                    Name = il->Name[loc_idx];
318                if (il->Description.size() > size_t(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
364        // resistances (7)
365        data << pProto->Armor;
366        data << pProto->HolyRes;
367        data << pProto->FireRes;
368        data << pProto->NatureRes;
369        data << pProto->FrostRes;
370        data << pProto->ShadowRes;
371        data << pProto->ArcaneRes;
372
373        data << pProto->Delay;
374        data << pProto->Ammo_type;
375        data << pProto->RangedModRange;
376
377        for(int s = 0; s < 5; s++)
378        {
379            // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
380            // use `item_template` or if not set then only use spell cooldowns
381            SpellEntry const* spell = sSpellStore.LookupEntry(pProto->Spells[s].SpellId);
382            if(spell)
383            {
384                bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0;
385
386                data << pProto->Spells[s].SpellId;
387                data << pProto->Spells[s].SpellTrigger;
388                data << uint32(-abs(pProto->Spells[s].SpellCharges));
389
390                if(db_data)
391                {
392                    data << uint32(pProto->Spells[s].SpellCooldown);
393                    data << uint32(pProto->Spells[s].SpellCategory);
394                    data << uint32(pProto->Spells[s].SpellCategoryCooldown);
395                }
396                else
397                {
398                    data << uint32(spell->RecoveryTime);
399                    data << uint32(spell->Category);
400                    data << uint32(spell->CategoryRecoveryTime);
401                }
402            }
403            else
404            {
405                data << uint32(0);
406                data << uint32(0);
407                data << uint32(0);
408                data << uint32(-1);
409                data << uint32(0);
410                data << uint32(-1);
411            }
412        }
413        data << pProto->Bonding;
414        data << Description;
415        data << pProto->PageText;
416        data << pProto->LanguageID;
417        data << pProto->PageMaterial;
418        data << pProto->StartQuest;
419        data << pProto->LockID;
420        data << pProto->Material;
421        data << pProto->Sheath;
422        data << pProto->RandomProperty;
423        data << pProto->RandomSuffix;
424        data << pProto->Block;
425        data << pProto->ItemSet;
426        data << pProto->MaxDurability;
427        data << pProto->Area;
428        data << pProto->Map;                                // Added in 1.12.x & 2.0.1 client branch
429        data << pProto->BagFamily;
430        data << pProto->TotemCategory;
431        for(int s = 0; s < 3; s++)
432        {
433            data << pProto->Socket[s].Color;
434            data << pProto->Socket[s].Content;
435        }
436        data << pProto->socketBonus;
437        data << pProto->GemProperties;
438        data << pProto->RequiredDisenchantSkill;
439        data << pProto->ArmorDamageModifier;
440        data << uint32(0);                                  // added in 2.4.2.8209, duration (seconds)
441        SendPacket( &data );
442    }
443    else
444    {
445        sLog.outDebug(  "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item );
446        WorldPacket data( SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4);
447        data << uint32(item | 0x80000000);
448        SendPacket( &data );
449    }
450}
451
452void WorldSession::HandleReadItem( WorldPacket & recv_data )
453{
454    CHECK_PACKET_SIZE(recv_data,1+1);
455
456    //sLog.outDebug( "WORLD: CMSG_READ_ITEM");
457
458    uint8 bag, slot;
459    recv_data >> bag >> slot;
460
461    //sLog.outDetail("STORAGE: Read bag = %u, slot = %u", bag, slot);
462    Item *pItem = _player->GetItemByPos( bag, slot );
463
464    if( pItem && pItem->GetProto()->PageText )
465    {
466        WorldPacket data;
467
468        uint8 msg = _player->CanUseItem( pItem );
469        if( msg == EQUIP_ERR_OK )
470        {
471            data.Initialize (SMSG_READ_ITEM_OK, 8);
472            sLog.outDetail("STORAGE: Item page sent");
473        }
474        else
475        {
476            data.Initialize( SMSG_READ_ITEM_FAILED, 8 );
477            sLog.outDetail("STORAGE: Unable to read item");
478            _player->SendEquipError( msg, pItem, NULL );
479        }
480        data << pItem->GetGUID();
481        SendPacket(&data);
482    }
483    else
484        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
485}
486
487void WorldSession::HandlePageQuerySkippedOpcode( WorldPacket & recv_data )
488{
489    CHECK_PACKET_SIZE(recv_data,4+8);
490
491    sLog.outDebug(  "WORLD: Received CMSG_PAGE_TEXT_QUERY" );
492
493    uint32 itemid;
494    uint64 guid;
495
496    recv_data >> itemid >> guid;
497
498    sLog.outDetail( "Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u",
499        itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid));
500}
501
502void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data )
503{
504    CHECK_PACKET_SIZE(recv_data,8+8+1);
505
506    sLog.outDebug(  "WORLD: Received CMSG_SELL_ITEM" );
507    uint64 vendorguid, itemguid;
508    uint8 _count;
509
510    recv_data >> vendorguid >> itemguid >> _count;
511
512    // prevent possible overflow, as Trinity uses uint32 for item count
513    uint32 count = _count;
514
515    if(!itemguid)
516        return;
517
518    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR);
519    if (!pCreature)
520    {
521        sLog.outDebug( "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
522        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0);
523        return;
524    }
525
526    // remove fake death
527    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
528        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
529
530    Item *pItem = _player->GetItemByGuid( itemguid );
531    if( pItem )
532    {
533        // prevent sell not owner item
534        if(_player->GetGUID()!=pItem->GetOwnerGUID())
535        {
536            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
537            return;
538        }
539
540        // prevent sell non empty bag by drag-and-drop at vendor's item list
541        if(pItem->IsBag() && !((Bag*)pItem)->IsEmpty())
542        {
543            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
544            return;
545        }
546
547        // prevent sell currently looted item
548        if(_player->GetLootGUID()==pItem->GetGUID())
549        {
550            _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
551            return;
552        }
553
554        // special case at auto sell (sell all)
555        if(count==0)
556        {
557            count = pItem->GetCount();
558        }
559        else
560        {
561            // prevent sell more items that exist in stack (possible only not from client)
562            if(count > pItem->GetCount())
563            {
564                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
565                return;
566            }
567        }
568
569        ItemPrototype const *pProto = pItem->GetProto();
570        if( pProto )
571        {
572            if( pProto->SellPrice > 0 )
573            {
574                if(count < pItem->GetCount())               // need split items
575                {
576                    Item *pNewItem = pItem->CloneItem( count, _player );
577                    if (!pNewItem)
578                    {
579                        sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count );
580                        _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
581                        return;
582                    }
583
584                    pItem->SetCount( pItem->GetCount() - count );
585                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), count );
586                    if( _player->IsInWorld() )
587                        pItem->SendUpdateToPlayer( _player );
588                    pItem->SetState(ITEM_CHANGED, _player);
589
590                    _player->AddItemToBuyBackSlot( pNewItem );
591                    if( _player->IsInWorld() )
592                        pNewItem->SendUpdateToPlayer( _player );
593                }
594                else
595                {
596                    _player->ItemRemovedQuestCheck( pItem->GetEntry(), pItem->GetCount());
597                    _player->RemoveItem( pItem->GetBagSlot(), pItem->GetSlot(), true);
598                    pItem->RemoveFromUpdateQueueOf(_player);
599                    _player->AddItemToBuyBackSlot( pItem );
600                }
601
602                _player->ModifyMoney( pProto->SellPrice * count );
603            }
604            else
605                _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
606            return;
607        }
608    }
609    _player->SendSellError( SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0);
610    return;
611}
612
613void WorldSession::HandleBuybackItem(WorldPacket & recv_data)
614{
615    CHECK_PACKET_SIZE(recv_data,8+4);
616
617    sLog.outDebug(  "WORLD: Received CMSG_BUYBACK_ITEM" );
618    uint64 vendorguid;
619    uint32 slot;
620
621    recv_data >> vendorguid >> slot;
622
623    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR);
624    if (!pCreature)
625    {
626        sLog.outDebug( "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
627        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
628        return;
629    }
630
631    // remove fake death
632    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
633        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
634
635    Item *pItem = _player->GetItemFromBuyBackSlot( slot );
636    if( pItem )
637    {
638        uint32 price = _player->GetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START );
639        if( _player->GetMoney() < price )
640        {
641            _player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, pItem->GetEntry(), 0);
642            return;
643        }
644
645        ItemPosCountVec dest;
646        uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
647        if( msg == EQUIP_ERR_OK )
648        {
649            _player->ModifyMoney( -(int32)price );
650            _player->RemoveItemFromBuyBackSlot( slot, false );
651            _player->ItemAddedQuestCheck( pItem->GetEntry(), pItem->GetCount());
652            _player->StoreItem( dest, pItem, true );
653        }
654        else
655            _player->SendEquipError( msg, pItem, NULL );
656        return;
657    }
658    else
659        _player->SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, 0, 0);
660}
661
662void WorldSession::HandleBuyItemInSlotOpcode( WorldPacket & recv_data )
663{
664    CHECK_PACKET_SIZE(recv_data,8+4+8+1+1);
665
666    sLog.outDebug(  "WORLD: Received CMSG_BUY_ITEM_IN_SLOT" );
667    uint64 vendorguid, bagguid;
668    uint32 item;
669    uint8 slot, count;
670
671    recv_data >> vendorguid >> item >> bagguid >> slot >> count;
672
673    GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bagguid,slot);
674}
675
676void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data )
677{
678    CHECK_PACKET_SIZE(recv_data,8+4+1+1);
679
680    sLog.outDebug(  "WORLD: Received CMSG_BUY_ITEM" );
681    uint64 vendorguid;
682    uint32 item;
683    uint8 count, unk1;
684
685    recv_data >> vendorguid >> item >> count >> unk1;
686
687    GetPlayer()->BuyItemFromVendor(vendorguid,item,count,NULL_BAG,NULL_SLOT);
688}
689
690void WorldSession::HandleListInventoryOpcode( WorldPacket & recv_data )
691{
692    CHECK_PACKET_SIZE(recv_data,8);
693
694    uint64 guid;
695
696    recv_data >> guid;
697
698    if(!GetPlayer()->isAlive())
699        return;
700
701    sLog.outDebug(  "WORLD: Recvd CMSG_LIST_INVENTORY" );
702
703    SendListInventory( guid );
704}
705
706void WorldSession::SendListInventory( uint64 vendorguid )
707{
708    sLog.outDebug(  "WORLD: Sent SMSG_LIST_INVENTORY" );
709
710    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR);
711    if (!pCreature)
712    {
713        sLog.outDebug( "WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
714        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
715        return;
716    }
717
718    // remove fake death
719    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
720        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
721
722    // Stop the npc if moving
723    pCreature->StopMoving();
724
725    VendorItemData const* vItems = pCreature->GetVendorItems();
726    if(!vItems)
727    {
728        _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
729        return;
730    }
731
732    uint8 numitems = vItems->GetItemCount();
733    uint8 count = 0;
734
735    WorldPacket data( SMSG_LIST_INVENTORY, (8+1+numitems*8*4) );
736    data << uint64(vendorguid);
737    data << uint8(numitems);
738
739    float discountMod = _player->GetReputationPriceDiscount(pCreature);
740
741    for(int i = 0; i < numitems; i++ )
742    {
743        if(VendorItem const* crItem = vItems->GetItem(i))
744        {
745            if(ItemPrototype const *pProto = objmgr.GetItemPrototype(crItem->item))
746            {
747                if((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster())
748                    continue;
749
750                ++count;
751
752                // reputation discount
753                uint32 price = uint32(floor(pProto->BuyPrice * discountMod));
754
755                data << uint32(count);
756                data << uint32(crItem->item);
757                data << uint32(pProto->DisplayInfoID);
758                data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem));
759                data << uint32(price);
760                data << uint32(pProto->MaxDurability);
761                data << uint32(pProto->BuyCount);
762                data << uint32(crItem->ExtendedCost);
763            }
764        }
765    }
766
767    if ( count == 0 || data.size() != 8 + 1 + size_t(count) * 8 * 4 )
768        return;
769
770    data.put<uint8>(8, count);
771    SendPacket( &data );
772}
773
774void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data )
775{
776    CHECK_PACKET_SIZE(recv_data,1+1+1);
777
778    //sLog.outDebug("WORLD: CMSG_AUTOSTORE_BAG_ITEM");
779    uint8 srcbag, srcslot, dstbag;
780
781    recv_data >> srcbag >> srcslot >> dstbag;
782    //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag);
783
784    Item *pItem = _player->GetItemByPos( srcbag, srcslot );
785    if( !pItem )
786        return;
787
788    if(!_player->IsValidPos(dstbag,NULL_SLOT))
789    {
790        _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
791        return;
792    }
793
794    uint16 src = pItem->GetPos();
795
796    // check unequip potability for equipped items and bank bags
797    if(_player->IsEquipmentPos ( src ) || _player->IsBagPos ( src ))
798    {
799        uint8 msg = _player->CanUnequipItem( src, !_player->IsBagPos ( src ));
800        if(msg != EQUIP_ERR_OK)
801        {
802            _player->SendEquipError( msg, pItem, NULL );
803            return;
804        }
805    }
806
807    ItemPosCountVec dest;
808    uint8 msg = _player->CanStoreItem( dstbag, NULL_SLOT, dest, pItem, false );
809    if( msg != EQUIP_ERR_OK )
810    {
811        _player->SendEquipError( msg, pItem, NULL );
812        return;
813    }
814
815    // no-op: placed in same slot
816    if(dest.size()==1 && dest[0].pos==src)
817    {
818        // just remove grey item state
819        _player->SendEquipError( EQUIP_ERR_NONE, pItem, NULL );
820        return;
821    }
822
823    _player->RemoveItem(srcbag, srcslot, true );
824    _player->StoreItem( dest, pItem, true );
825}
826
827void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/)
828{
829    sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT");
830
831    uint32 slot = _player->GetByteValue(PLAYER_BYTES_2, 2);
832
833    // next slot
834    ++slot;
835
836    sLog.outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot);
837
838    BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot);
839
840    if(!slotEntry)
841        return;
842
843    uint32 price = slotEntry->price;
844
845    if (_player->GetMoney() < price)
846        return;
847
848    _player->SetByteValue(PLAYER_BYTES_2, 2, slot);
849    _player->ModifyMoney(-int32(price));
850}
851
852void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket)
853{
854    CHECK_PACKET_SIZE(recvPacket,1+1);
855
856    sLog.outDebug("WORLD: CMSG_AUTOBANK_ITEM");
857    uint8 srcbag, srcslot;
858
859    recvPacket >> srcbag >> srcslot;
860    sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
861
862    Item *pItem = _player->GetItemByPos( srcbag, srcslot );
863    if( !pItem )
864        return;
865
866    ItemPosCountVec dest;
867    uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
868    if( msg != EQUIP_ERR_OK )
869    {
870        _player->SendEquipError( msg, pItem, NULL );
871        return;
872    }
873
874    _player->RemoveItem(srcbag, srcslot, true);
875    _player->BankItem( dest, pItem, true );
876}
877
878void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
879{
880    CHECK_PACKET_SIZE(recvPacket,1+1);
881
882    sLog.outDebug("WORLD: CMSG_AUTOSTORE_BANK_ITEM");
883    uint8 srcbag, srcslot;
884
885    recvPacket >> srcbag >> srcslot;
886    sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
887
888    Item *pItem = _player->GetItemByPos( srcbag, srcslot );
889    if( !pItem )
890        return;
891
892    if(_player->IsBankPos(srcbag, srcslot))                 // moving from bank to inventory
893    {
894        ItemPosCountVec dest;
895        uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
896        if( msg != EQUIP_ERR_OK )
897        {
898            _player->SendEquipError( msg, pItem, NULL );
899            return;
900        }
901
902        _player->RemoveItem(srcbag, srcslot, true);
903        _player->StoreItem( dest, pItem, true );
904    }
905    else                                                    // moving from inventory to bank
906    {
907        ItemPosCountVec dest;
908        uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
909        if( msg != EQUIP_ERR_OK )
910        {
911            _player->SendEquipError( msg, pItem, NULL );
912            return;
913        }
914
915        _player->RemoveItem(srcbag, srcslot, true);
916        _player->BankItem( dest, pItem, true );
917    }
918}
919
920void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data)
921{
922    CHECK_PACKET_SIZE(recv_data,4);
923
924    if(!GetPlayer()->isAlive())
925    {
926        GetPlayer()->SendEquipError( EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL );
927        return;
928    }
929
930    sLog.outDebug("WORLD: CMSG_SET_AMMO");
931    uint32 item;
932
933    recv_data >> item;
934
935    if(!item)
936        GetPlayer()->RemoveAmmo();
937    else
938        GetPlayer()->SetAmmo(item);
939}
940
941void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID)
942{
943    WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1));     // last check 2.0.10
944    data << Target;
945    data << Caster;
946    data << ItemID;
947    data << SpellID;
948    data << uint8(0);
949    SendPacket(&data);
950}
951
952void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration)
953{
954                                                            // last check 2.0.10
955    WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8));
956    data << uint64(Itemguid);
957    data << uint32(slot);
958    data << uint32(Duration);
959    data << uint64(Playerguid);
960    SendPacket(&data);
961}
962
963void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data)
964{
965    CHECK_PACKET_SIZE(recv_data,4);
966
967    uint32 itemid;
968    recv_data >> itemid;
969    sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid);
970    ItemPrototype const *pProto = objmgr.GetItemPrototype( itemid );
971    if( pProto )
972    {
973        std::string Name;
974        Name = pProto->Name1;
975
976        int loc_idx = GetSessionDbLocaleIndex();
977        if (loc_idx >= 0)
978        {
979            ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId);
980            if (il)
981            {
982                if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
983                    Name = il->Name[loc_idx];
984            }
985        }
986                                                            // guess size
987        WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+10));
988        data << uint32(pProto->ItemId);
989        data << Name;
990        data << uint32(pProto->InventoryType);
991        SendPacket(&data);
992        return;
993    }
994    else
995        sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (unknown item)", itemid);
996}
997
998void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data)
999{
1000    CHECK_PACKET_SIZE(recv_data,1+1+1+1);
1001
1002    sLog.outDebug("Received opcode CMSG_WRAP_ITEM");
1003
1004    uint8 gift_bag, gift_slot, item_bag, item_slot;
1005    //recv_data.hexlike();
1006
1007    recv_data >> gift_bag >> gift_slot;                     // paper
1008    recv_data >> item_bag >> item_slot;                     // item
1009
1010    sLog.outDebug("WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot);
1011
1012    Item *gift = _player->GetItemByPos( gift_bag, gift_slot );
1013    if(!gift)
1014    {
1015        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL );
1016        return;
1017    }
1018
1019    if(!gift->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPER))// cheating: non-wrapper wrapper
1020    {
1021        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL );
1022        return;
1023    }
1024
1025    Item *item = _player->GetItemByPos( item_bag, item_slot );
1026
1027    if( !item )
1028    {
1029        _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, item, NULL );
1030        return;
1031    }
1032
1033    if(item==gift)                                          // not possable with pacjket from real client
1034    {
1035        _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL );
1036        return;
1037    }
1038
1039    if(item->IsEquipped())
1040    {
1041        _player->SendEquipError( EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL );
1042        return;
1043    }
1044
1045    if(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR))        // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
1046    {
1047        _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL );
1048        return;
1049    }
1050
1051    if(item->IsBag())
1052    {
1053        _player->SendEquipError( EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL );
1054        return;
1055    }
1056
1057    if(item->IsSoulBound())
1058    {
1059        _player->SendEquipError( EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL );
1060        return;
1061    }
1062
1063    if(item->GetMaxStackCount() != 1)
1064    {
1065        _player->SendEquipError( EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL );
1066        return;
1067    }
1068
1069    // maybe not correct check  (it is better than nothing)
1070    if(item->GetProto()->MaxCount>0)
1071    {
1072        _player->SendEquipError( EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL );
1073        return;
1074    }
1075
1076    CharacterDatabase.BeginTransaction();
1077    CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS));
1078    item->SetEntry(gift->GetEntry());
1079
1080    switch (item->GetEntry())
1081    {
1082        case 5042:  item->SetEntry( 5043); break;
1083        case 5048:  item->SetEntry( 5044); break;
1084        case 17303: item->SetEntry(17302); break;
1085        case 17304: item->SetEntry(17305); break;
1086        case 17307: item->SetEntry(17308); break;
1087        case 21830: item->SetEntry(21831); break;
1088    }
1089    item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
1090    item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
1091    item->SetState(ITEM_CHANGED, _player);
1092
1093    if(item->GetState()==ITEM_NEW)                          // save new item, to have alway for `character_gifts` record in `item_instance`
1094    {
1095        // after save it will be impossible to remove the item from the queue
1096        item->RemoveFromUpdateQueueOf(_player);
1097        item->SaveToDB();                                   // item gave inventory record unchanged and can be save standalone
1098    }
1099    CharacterDatabase.CommitTransaction();
1100
1101    uint32 count = 1;
1102    _player->DestroyItemCount(gift, count, true);
1103}
1104
1105void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
1106{
1107    sLog.outDebug("WORLD: CMSG_SOCKET_GEMS");
1108
1109    CHECK_PACKET_SIZE(recv_data,8*4);
1110
1111    uint64 guids[4];
1112    uint32 GemEnchants[3], OldEnchants[3];
1113    Item *Gems[3];
1114    bool SocketBonusActivated, SocketBonusToBeActivated;
1115
1116    for(int i = 0; i < 4; i++)
1117        recv_data >> guids[i];
1118
1119    if(!guids[0])
1120        return;
1121
1122    //cheat -> tried to socket same gem multiple times
1123    if((guids[1] && (guids[1] == guids[2] || guids[1] == guids[3])) || (guids[2] && (guids[2] == guids[3])))
1124        return;
1125
1126    Item *itemTarget = _player->GetItemByGuid(guids[0]);
1127    if(!itemTarget)                                         //missing item to socket
1128        return;
1129
1130    //this slot is excepted when applying / removing meta gem bonus
1131    uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT;
1132
1133    for(int i = 0; i < 3; i++)
1134        Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL;
1135
1136    GemPropertiesEntry const *GemProps[3];
1137    for(int i = 0; i < 3; ++i)                              //get geminfo from dbc storage
1138    {
1139        GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL;
1140    }
1141
1142    for(int i = 0; i < 3; ++i)                              //check for hack maybe
1143    {
1144        // tried to put gem in socket where no socket exists / tried to put normal gem in meta socket
1145        // tried to put meta gem in normal socket
1146        if( GemProps[i] && ( !itemTarget->GetProto()->Socket[i].Color ||
1147            itemTarget->GetProto()->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META ||
1148            itemTarget->GetProto()->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META ) )
1149            return;
1150    }
1151
1152    for(int i = 0; i < 3; ++i)                              //get new and old enchantments
1153    {
1154        GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
1155        OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i));
1156    }
1157
1158    // check unique-equipped conditions
1159    for(int i = 0; i < 3; ++i)
1160    {
1161        if (Gems[i] && (Gems[i]->GetProto()->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED))
1162        {
1163            // for equipped item check all equipment for duplicate equipped gems
1164            if(itemTarget->IsEquipped())
1165            {
1166                if(GetPlayer()->GetItemOrItemWithGemEquipped(Gems[i]->GetEntry()))
1167                {
1168                    _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE, itemTarget, NULL );
1169                    return;
1170                }
1171            }
1172
1173            // continue check for case when attempt add 2 similar unique equipped gems in one item.
1174            for (int j = 0; j < 3; ++j)
1175            {
1176                if ((i != j) && (Gems[j]) && (Gems[i]->GetProto()->ItemId == Gems[j]->GetProto()->ItemId))
1177                {
1178                    _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
1179                    return;
1180                }
1181            }
1182            for (int j = 0; j < 3; ++j)
1183            {
1184                if (OldEnchants[j])
1185                {
1186                    SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]);
1187                    if(!enchantEntry)
1188                        continue;
1189
1190                    if ((enchantEntry->GemID == Gems[i]->GetProto()->ItemId) && (i != j))
1191                    {
1192                        _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
1193                        return;
1194                    }
1195                }
1196            }
1197        }
1198    }
1199
1200    SocketBonusActivated = itemTarget->GemsFitSockets();    //save state of socketbonus
1201    _player->ToggleMetaGemsActive(slot, false);             //turn off all metagems (except for the target item)
1202
1203    //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
1204
1205    //remove ALL enchants
1206    for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
1207        _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false);
1208
1209    for(int i = 0; i < 3; ++i)
1210    {
1211        if(GemEnchants[i])
1212        {
1213            itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0);
1214            if(Item* guidItem = _player->GetItemByGuid(guids[i + 1]))
1215                _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true );
1216        }
1217    }
1218
1219    for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
1220        _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true);
1221
1222    SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
1223    if(SocketBonusActivated ^ SocketBonusToBeActivated)     //if there was a change...
1224    {
1225        _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false);
1226        itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0);
1227        _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,true);
1228        //it is not displayed, client has an inbuilt system to determine if the bonus is activated
1229    }
1230
1231    _player->ToggleMetaGemsActive(slot, true);              //turn on all metagems (except for target item)
1232}
1233
1234void WorldSession::HandleCancelTempItemEnchantmentOpcode(WorldPacket& recv_data)
1235{
1236    sLog.outDebug("WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");
1237
1238    CHECK_PACKET_SIZE(recv_data,4);
1239
1240    uint32 eslot;
1241
1242    recv_data >> eslot;
1243
1244    // apply only to equipped item
1245    if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0,eslot))
1246        return;
1247
1248    Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot);
1249
1250    if(!item)
1251        return;
1252
1253    if(!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
1254        return;
1255
1256    GetPlayer()->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1257    item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);
1258}
Note: See TracBrowser for help on using the browser.