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

Revision 6, 26.7 kB (checked in by yumileroy, 17 years ago)

[svn] * Added ACE for Linux and Windows (Thanks Derex for Linux part and partial Windows part)
* Updated to 6721 and 676
* Fixed TrinityScript? logo
* Version updated to 0.2.6721.676

Original author: Neo2003
Date: 2008-10-04 06:17:19-05:00

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