root/trunk/src/game/NPCHandler.cpp @ 102

Revision 102, 25.9 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05: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 "Language.h"
23#include "Database/DatabaseEnv.h"
24#include "WorldPacket.h"
25#include "WorldSession.h"
26#include "Opcodes.h"
27#include "Log.h"
28#include "World.h"
29#include "ObjectMgr.h"
30#include "SpellMgr.h"
31#include "Player.h"
32#include "GossipDef.h"
33#include "SpellAuras.h"
34#include "UpdateMask.h"
35#include "ScriptCalls.h"
36#include "ObjectAccessor.h"
37#include "Creature.h"
38#include "MapManager.h"
39#include "Pet.h"
40#include "BattleGroundMgr.h"
41#include "BattleGround.h"
42#include "Guild.h"
43
44void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data )
45{
46    CHECK_PACKET_SIZE(recv_data,8);
47
48    uint64 guid;
49    recv_data >> guid;
50
51    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER);
52    if (!unit)
53    {
54        sLog.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
55        return;
56    }
57
58    // remove fake death
59    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
60        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
61
62    SendTabardVendorActivate(guid);
63}
64
65void WorldSession::SendTabardVendorActivate( uint64 guid )
66{
67    WorldPacket data( MSG_TABARDVENDOR_ACTIVATE, 8 );
68    data << guid;
69    SendPacket( &data );
70}
71
72void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data )
73{
74    CHECK_PACKET_SIZE(recv_data,8);
75
76    uint64 guid;
77
78    sLog.outDebug(  "WORLD: Received CMSG_BANKER_ACTIVATE" );
79
80    recv_data >> guid;
81
82    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER);
83    if (!unit)
84    {
85        sLog.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
86        return;
87    }
88
89    // remove fake death
90    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
91        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
92
93    SendShowBank(guid);
94}
95
96void WorldSession::SendShowBank( uint64 guid )
97{
98    WorldPacket data( SMSG_SHOW_BANK, 8 );
99    data << guid;
100    SendPacket( &data );
101}
102
103void WorldSession::HandleTrainerListOpcode( WorldPacket & recv_data )
104{
105    CHECK_PACKET_SIZE(recv_data,8);
106
107    uint64 guid;
108
109    recv_data >> guid;
110    SendTrainerList( guid );
111}
112
113void WorldSession::SendTrainerList( uint64 guid )
114{
115    std::string str = GetTrinityString(LANG_NPC_TAINER_HELLO);
116    SendTrainerList( guid, str );
117}
118
119void WorldSession::SendTrainerList( uint64 guid,std::string strTitle )
120{
121    sLog.outDebug( "WORLD: SendTrainerList" );
122
123    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER);
124    if (!unit)
125    {
126        sLog.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
127        return;
128    }
129
130    // remove fake death
131    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
132        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
133
134    // trainer list loaded at check;
135    if(!unit->isCanTrainingOf(_player,true))
136        return;
137
138    CreatureInfo const *ci = unit->GetCreatureInfo();
139
140    if (!ci)
141    {
142        sLog.outDebug( "WORLD: SendTrainerList - (%u) NO CREATUREINFO! (GUID: %u)", uint32(GUID_LOPART(guid)), guid );
143        return;
144    }
145
146    TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
147    if(!trainer_spells)
148    {
149        sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", guid, unit->GetEntry());
150        return;
151    }
152
153    WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1);
154    data << guid;
155    data << uint32(trainer_spells->trainerType);
156
157    size_t count_pos = data.wpos();
158    data << uint32(trainer_spells->spellList.size());
159
160    // reputation discount
161    float fDiscountMod = _player->GetReputationPriceDiscount(unit);
162
163    uint32 count = 0;
164    for(TrainerSpellList::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
165    {
166        TrainerSpell const* tSpell = *itr;
167
168        if(!_player->IsSpellFitByClassAndRace(tSpell->spell))
169            continue;
170
171        ++count;
172
173        bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell);
174
175        SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell);
176
177        data << uint32(tSpell->spell);
178        data << uint8(_player->GetTrainerSpellState(tSpell));
179        data << uint32(floor(tSpell->spellcost * fDiscountMod));
180
181        data << uint32(primary_prof_first_rank ? 1 : 0);    // primary prof. learn confirmation dialog
182        data << uint32(primary_prof_first_rank ? 1 : 0);    // must be equal prev. field to have learn button in enabled state
183        data << uint8(tSpell->reqlevel);
184        data << uint32(tSpell->reqskill);
185        data << uint32(tSpell->reqskillvalue);
186        data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
187        data << uint32(chain_node && chain_node->prev ? chain_node->req : 0);
188        data << uint32(0);
189    }
190
191    data << strTitle;
192
193    data.put<uint32>(count_pos,count);
194    SendPacket( &data );
195}
196
197void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
198{
199    CHECK_PACKET_SIZE(recv_data,8+4);
200
201    uint64 guid;
202    uint32 spellId = 0;
203
204    recv_data >> guid >> spellId;
205    sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId );
206
207    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER);
208    if (!unit)
209    {
210        sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
211        return;
212    }
213
214    // remove fake death
215    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
216        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
217
218    if(!unit->isCanTrainingOf(_player,true))
219        return;
220
221    // check present spell in trainer spell list
222    TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
223    if(!trainer_spells)
224        return; 
225
226    // not found, cheat?
227    TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
228    if(!trainer_spell)
229        return;
230
231    // can't be learn, cheat? Or double learn with lags...
232    if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
233        return;
234
235    // apply reputation discount
236    uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit)));
237
238    // check money requirement
239    if(_player->GetMoney() < nSpellCost )
240        return;
241
242    WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12);           // visual effect on trainer
243    data << uint64(guid) << uint32(0xB3);
244    SendPacket(&data);
245
246    data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12);            // visual effect on player
247    data << uint64(_player->GetGUID()) << uint32(0x016A);
248    SendPacket(&data);
249
250    _player->ModifyMoney( -int32(nSpellCost) );
251
252    // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
253    _player->learnSpell(trainer_spell->spell);
254
255    data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
256    data << uint64(guid) << uint32(spellId);
257    SendPacket(&data);
258}
259
260void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data )
261{
262    CHECK_PACKET_SIZE(recv_data,8);
263
264    sLog.outDebug(  "WORLD: Received CMSG_GOSSIP_HELLO" );
265
266    uint64 guid;
267    recv_data >> guid;
268
269    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
270    if (!unit)
271    {
272        sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
273        return;
274    }
275
276    // remove fake death
277    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
278        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
279
280    if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
281    {
282        unit->StopMoving();
283    }
284
285    // If spiritguide, no need for gossip menu, just put player into resurrect queue
286    if (unit->isSpiritGuide())
287    {
288        BattleGround *bg = _player->GetBattleGround();
289        if(bg)
290        {
291            bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
292            sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
293            return;
294        }
295    }
296
297    if(!Script->GossipHello( _player, unit ))
298    {
299        _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
300        unit->prepareGossipMenu(_player,0);
301        unit->sendPreparedGossip( _player );
302    }
303}
304
305void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
306{
307    CHECK_PACKET_SIZE(recv_data,8+4+4);
308
309    sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
310
311    uint32 option;
312    uint32 unk;
313    uint64 guid;
314    std::string code = "";
315
316    recv_data >> guid >> unk >> option;
317
318    if(_player->PlayerTalkClass->GossipOptionCoded( option ))
319    {
320        // recheck
321        CHECK_PACKET_SIZE(recv_data,8+4+1);
322        sLog.outBasic("reading string");
323        recv_data >> code;
324        sLog.outBasic("string read: %s", code.c_str());
325    }
326
327    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
328    if (!unit)
329    {
330        sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
331        return;
332    }
333
334    // remove fake death
335    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
336        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
337
338    if(!code.empty())
339    {
340
341        if(!Script->GossipSelectWithCode( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()) )
342            unit->OnGossipSelect( _player, option );
343    }
344    else
345
346    if(!Script->GossipSelect( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option )) )
347        unit->OnGossipSelect( _player, option );
348}
349
350void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data )
351{
352    CHECK_PACKET_SIZE(recv_data,8);
353
354    sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
355
356    uint64 guid;
357
358    recv_data >> guid;
359
360    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER);
361    if (!unit)
362    {
363        sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
364        return;
365    }
366
367    // remove fake death
368    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
369        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
370
371    SendSpiritResurrect();
372}
373
374void WorldSession::SendSpiritResurrect()
375{
376    _player->ResurrectPlayer(0.5f,false, true);
377
378    _player->DurabilityLossAll(0.25f,true);
379
380    // get corpse nearest graveyard
381    WorldSafeLocsEntry const *corpseGrave = NULL;
382    Corpse *corpse = _player->GetCorpse();
383    if(corpse)
384        corpseGrave = objmgr.GetClosestGraveYard(
385            corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam() );
386
387    // now can spawn bones
388    _player->SpawnCorpseBones();
389
390    // teleport to nearest from corpse graveyard, if different from nearest to player ghost
391    if(corpseGrave)
392    {
393        WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard(
394            _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam() );
395
396        if(corpseGrave != ghostGrave)
397            _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
398        // or update at original position
399        else
400            ObjectAccessor::UpdateVisibilityForPlayer(_player);
401    }
402    // or update at original position
403    else
404        ObjectAccessor::UpdateVisibilityForPlayer(_player);
405
406    _player->SaveToDB();
407}
408
409void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
410{
411    CHECK_PACKET_SIZE(recv_data,8);
412
413    uint64 npcGUID;
414    recv_data >> npcGUID;
415
416    if(!GetPlayer()->isAlive())
417        return;
418
419    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER);
420    if (!unit)
421    {
422        sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
423        return;
424    }
425
426    // remove fake death
427    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
428        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
429
430    SendBindPoint(unit);
431}
432
433void WorldSession::SendBindPoint(Creature *npc)
434{
435    uint32 bindspell = 3286;
436
437    // update sql homebind
438    CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), _player->GetZoneId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow());
439    _player->m_homebindMapId = _player->GetMapId();
440    _player->m_homebindZoneId = _player->GetZoneId();
441    _player->m_homebindX = _player->GetPositionX();
442    _player->m_homebindY = _player->GetPositionY();
443    _player->m_homebindZ = _player->GetPositionZ();
444
445    // send spell for bind 3286 bind magic
446    npc->CastSpell(_player, bindspell, true);
447
448    WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
449    data << npc->GetGUID();
450    data << bindspell;
451    SendPacket( &data );
452
453    // binding
454    data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
455    data << float(_player->GetPositionX());
456    data << float(_player->GetPositionY());
457    data << float(_player->GetPositionZ());
458    data << uint32(_player->GetMapId());
459    data << uint32(_player->GetZoneId());
460    SendPacket( &data );
461
462    DEBUG_LOG("New Home Position X is %f",_player->GetPositionX());
463    DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY());
464    DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ());
465    DEBUG_LOG("New Home MapId is %u",_player->GetMapId());
466    DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId());
467
468    // zone update
469    data.Initialize( SMSG_PLAYERBOUND, 8+4 );
470    data << uint64(_player->GetGUID());
471    data << uint32(_player->GetZoneId());
472    SendPacket( &data );
473
474    _player->PlayerTalkClass->CloseGossip();
475}
476
477//Need fix
478void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
479{
480    CHECK_PACKET_SIZE(recv_data,8);
481
482    sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS");
483    uint64 npcGUID;
484
485    recv_data >> npcGUID;
486
487    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
488    if (!unit)
489    {
490        sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
491        return;
492    }
493
494    // remove fake death
495    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
496        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
497
498    SendStablePet(npcGUID);
499}
500
501void WorldSession::SendStablePet(uint64 guid )
502{
503    sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");
504
505    WorldPacket data(MSG_LIST_STABLED_PETS, 200);           // guess size
506    data << uint64 ( guid );
507
508    Pet *pet = _player->GetPet();
509
510    data << uint8(0);                                       // place holder for slot show number
511    data << uint8(GetPlayer()->m_stableSlots);
512
513    uint8 num = 0;                                          // counter for place holder
514
515    // not let move dead pet in slot
516    if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET)
517    {
518        data << uint32(pet->GetCharmInfo()->GetPetNumber());
519        data << uint32(pet->GetEntry());
520        data << uint32(pet->getLevel());
521        data << pet->GetName();                             // petname
522        data << uint32(pet->GetLoyaltyLevel());             // loyalty
523        data << uint8(0x01);                                // client slot 1 == current pet (0)
524        ++num;
525    }
526
527    //                                                     0      1     2   3      4      5        6
528    QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow());
529
530    if(result)
531    {
532        do
533        {
534            Field *fields = result->Fetch();
535
536            data << uint32(fields[2].GetUInt32());          // petnumber
537            data << uint32(fields[3].GetUInt32());          // creature entry
538            data << uint32(fields[4].GetUInt32());          // level
539            data << fields[6].GetString();                  // name
540            data << uint32(fields[5].GetUInt32());          // loyalty
541            data << uint8(fields[1].GetUInt32()+1);         // slot
542
543            ++num;
544        }while( result->NextRow() );
545
546        delete result;
547    }
548
549    data.put<uint8>(8, num);                                // set real data to placeholder
550    SendPacket(&data);
551}
552
553void WorldSession::HandleStablePet( WorldPacket & recv_data )
554{
555    CHECK_PACKET_SIZE(recv_data,8);
556
557    sLog.outDebug("WORLD: Recv CMSG_STABLE_PET not dispose.");
558    uint64 npcGUID;
559
560    recv_data >> npcGUID;
561
562    if(!GetPlayer()->isAlive())
563        return;
564
565    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
566    if (!unit)
567    {
568        sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
569        return;
570    }
571
572    // remove fake death
573    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
574        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
575
576    Pet *pet = _player->GetPet();
577
578    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size
579
580    // can't place in stable dead pet
581    if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
582    {
583        data << uint8(0x06);
584        SendPacket(&data);
585        return;
586    }
587
588    uint32 free_slot = 1;
589
590    QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u'  AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow());
591    if(result)
592    {
593        do
594        {
595            Field *fields = result->Fetch();
596
597            uint32 slot = fields[1].GetUInt32();
598
599            if(slot==free_slot)                             // this slot not free
600                ++free_slot;
601        }while( result->NextRow() );
602    }
603    delete result;
604
605    if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
606    {
607        _player->RemovePet(pet,PetSaveMode(free_slot));
608        data << uint8(0x08);
609    }
610    else
611        data << uint8(0x06);
612
613    SendPacket(&data);
614}
615
616void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
617{
618    CHECK_PACKET_SIZE(recv_data,8+4);
619
620    sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET.");
621    uint64 npcGUID;
622    uint32 petnumber;
623
624    recv_data >> npcGUID >> petnumber;
625
626    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
627    if (!unit)
628    {
629        sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
630        return;
631    }
632
633    // remove fake death
634    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
635        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
636
637    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size
638
639    Pet* pet = _player->GetPet();
640    if(pet && pet->isAlive())
641    {
642        uint8 i = 0x06;
643        data << uint8(i);
644        SendPacket(&data);
645        return;
646    }
647
648    // delete dead pet
649    if(pet)
650        _player->RemovePet(pet,PET_SAVE_AS_DELETED);
651
652    Pet *newpet = NULL;
653
654    QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber);
655    if(result)
656    {
657        Field *fields = result->Fetch();
658        uint32 petentry = fields[0].GetUInt32();
659
660        newpet = new Pet(HUNTER_PET);
661        if(!newpet->LoadPetFromDB(_player,petentry,petnumber))
662        {
663            delete newpet;
664            newpet = NULL;
665        }
666        delete result;
667    }
668
669    if(newpet)
670        data << uint8(0x09);
671    else
672        data << uint8(0x06);
673    SendPacket(&data);
674}
675
676void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
677{
678    CHECK_PACKET_SIZE(recv_data,8);
679
680    sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT.");
681    uint64 npcGUID;
682
683    recv_data >> npcGUID;
684
685    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
686    if (!unit)
687    {
688        sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
689        return;
690    }
691
692    // remove fake death
693    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
694        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
695
696    WorldPacket data(SMSG_STABLE_RESULT, 200);
697
698    if(GetPlayer()->m_stableSlots < 2)                      // max slots amount = 2
699    {
700        StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
701        if(_player->GetMoney() >= SlotPrice->Price)
702        {
703            ++GetPlayer()->m_stableSlots;
704            _player->ModifyMoney(-int32(SlotPrice->Price));
705            data << uint8(0x0A);                            // success buy
706        }
707        else
708            data << uint8(0x06);
709    }
710    else
711        data << uint8(0x06);
712
713    SendPacket(&data);
714}
715
716void WorldSession::HandleStableRevivePet( WorldPacket &/* recv_data */)
717{
718    sLog.outDebug("HandleStableRevivePet: Not implemented");
719}
720
721void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
722{
723    CHECK_PACKET_SIZE(recv_data,8+4);
724
725    sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET.");
726    uint64 npcGUID;
727    uint32 pet_number;
728
729    recv_data >> npcGUID >> pet_number;
730
731    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
732    if (!unit)
733    {
734        sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
735        return;
736    }
737
738    // remove fake death
739    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
740        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
741
742    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size
743
744    Pet* pet = _player->GetPet();
745
746    if(!pet || pet->getPetType()!=HUNTER_PET)
747        return;
748
749    // find swapped pet slot in stable
750    QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
751    if(!result)
752        return;
753
754    Field *fields = result->Fetch();
755
756    uint32 slot     = fields[0].GetUInt32();
757    uint32 petentry = fields[1].GetUInt32();
758    delete result;
759
760    // move alive pet to slot or delele dead pet
761    _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
762
763    // summon unstabled pet
764    Pet *newpet = new Pet;
765    if(!newpet->LoadPetFromDB(_player,petentry,pet_number))
766    {
767        delete newpet;
768        data << uint8(0x06);
769    }
770    else
771        data << uint8(0x09);
772
773    SendPacket(&data);
774}
775
776void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data )
777{
778    CHECK_PACKET_SIZE(recv_data,8+8+1);
779
780    sLog.outDebug("WORLD: CMSG_REPAIR_ITEM");
781
782    uint64 npcGUID, itemGUID;
783    uint8 guildBank;                                        // new in 2.3.2, bool that means from guild bank money
784
785    recv_data >> npcGUID >> itemGUID >> guildBank;
786
787    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR);
788    if (!unit)
789    {
790        sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
791        return;
792    }
793
794    // remove fake death
795    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
796        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
797
798    // reputation discount
799    float discountMod = _player->GetReputationPriceDiscount(unit);
800
801    uint32 TotalCost = 0;
802    if (itemGUID)
803    {
804        sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
805
806        Item* item = _player->GetItemByGuid(itemGUID);
807
808        if(item)
809            TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false);
810    }
811    else
812    {
813        sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
814
815        TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false);
816    }
817    if (guildBank)
818    {
819        uint32 GuildId = _player->GetGuildId();
820        if (!GuildId)
821            return;
822        Guild *pGuild = objmgr.GetGuildById(GuildId);
823        if (!pGuild)
824            return;
825        pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost);
826        pGuild->SendMoneyInfo(this, _player->GetGUIDLow());
827    }
828}
Note: See TracBrowser for help on using the browser.