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

Revision 221, 26.0 kB (checked in by yumileroy, 17 years ago)

[svn] Fix a bug that players cannot hear others talking.
Provide script support for type 10 gameobject.
Add some missing script sql.

Original author: megamage
Date: 2008-11-12 16:21:08-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 "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    GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
277    // remove fake death
278    //if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
279    //    GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
280
281    if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
282    {
283        unit->StopMoving();
284    }
285
286    // If spiritguide, no need for gossip menu, just put player into resurrect queue
287    if (unit->isSpiritGuide())
288    {
289        BattleGround *bg = _player->GetBattleGround();
290        if(bg)
291        {
292            bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
293            sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
294            return;
295        }
296    }
297
298    if(!Script->GossipHello( _player, unit ))
299    {
300        _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
301        unit->prepareGossipMenu(_player);
302        unit->sendPreparedGossip(_player);
303    }
304}
305
306void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
307{
308    CHECK_PACKET_SIZE(recv_data,8+4+4);
309
310    sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
311
312    uint32 option;
313    uint32 unk;
314    uint64 guid;
315    std::string code = "";
316
317    recv_data >> guid >> unk >> option;
318
319    if(_player->PlayerTalkClass->GossipOptionCoded( option ))
320    {
321        // recheck
322        CHECK_PACKET_SIZE(recv_data,8+4+1);
323        sLog.outBasic("reading string");
324        recv_data >> code;
325        sLog.outBasic("string read: %s", code.c_str());
326    }
327
328    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
329    if (!unit)
330    {
331        sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
332        return;
333    }
334
335    // remove fake death
336    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
337        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
338
339    if(!code.empty())
340    {
341
342        if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()))
343            unit->OnGossipSelect (_player, option);
344    }
345    else
346
347    {
348        if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option)))
349            unit->OnGossipSelect (_player, option);
350    }
351}
352
353void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data )
354{
355    CHECK_PACKET_SIZE(recv_data,8);
356
357    sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
358
359    uint64 guid;
360
361    recv_data >> guid;
362
363    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER);
364    if (!unit)
365    {
366        sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
367        return;
368    }
369
370    // remove fake death
371    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
372        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
373
374    SendSpiritResurrect();
375}
376
377void WorldSession::SendSpiritResurrect()
378{
379    _player->ResurrectPlayer(0.5f,false, true);
380
381    _player->DurabilityLossAll(0.25f,true);
382
383    // get corpse nearest graveyard
384    WorldSafeLocsEntry const *corpseGrave = NULL;
385    Corpse *corpse = _player->GetCorpse();
386    if(corpse)
387        corpseGrave = objmgr.GetClosestGraveYard(
388            corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam() );
389
390    // now can spawn bones
391    _player->SpawnCorpseBones();
392
393    // teleport to nearest from corpse graveyard, if different from nearest to player ghost
394    if(corpseGrave)
395    {
396        WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard(
397            _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam() );
398
399        if(corpseGrave != ghostGrave)
400            _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
401        // or update at original position
402        else
403            ObjectAccessor::UpdateVisibilityForPlayer(_player);
404    }
405    // or update at original position
406    else
407        ObjectAccessor::UpdateVisibilityForPlayer(_player);
408
409    _player->SaveToDB();
410}
411
412void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
413{
414    CHECK_PACKET_SIZE(recv_data,8);
415
416    uint64 npcGUID;
417    recv_data >> npcGUID;
418
419    if(!GetPlayer()->isAlive())
420        return;
421
422    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER);
423    if (!unit)
424    {
425        sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
426        return;
427    }
428
429    // remove fake death
430    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
431        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
432
433    SendBindPoint(unit);
434}
435
436void WorldSession::SendBindPoint(Creature *npc)
437{
438    uint32 bindspell = 3286;
439
440    // update sql homebind
441    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());
442    _player->m_homebindMapId = _player->GetMapId();
443    _player->m_homebindZoneId = _player->GetZoneId();
444    _player->m_homebindX = _player->GetPositionX();
445    _player->m_homebindY = _player->GetPositionY();
446    _player->m_homebindZ = _player->GetPositionZ();
447
448    // send spell for bind 3286 bind magic
449    npc->CastSpell(_player, bindspell, true);
450
451    WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
452    data << npc->GetGUID();
453    data << bindspell;
454    SendPacket( &data );
455
456    // binding
457    data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
458    data << float(_player->GetPositionX());
459    data << float(_player->GetPositionY());
460    data << float(_player->GetPositionZ());
461    data << uint32(_player->GetMapId());
462    data << uint32(_player->GetZoneId());
463    SendPacket( &data );
464
465    DEBUG_LOG("New Home Position X is %f",_player->GetPositionX());
466    DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY());
467    DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ());
468    DEBUG_LOG("New Home MapId is %u",_player->GetMapId());
469    DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId());
470
471    // zone update
472    data.Initialize( SMSG_PLAYERBOUND, 8+4 );
473    data << uint64(_player->GetGUID());
474    data << uint32(_player->GetZoneId());
475    SendPacket( &data );
476
477    _player->PlayerTalkClass->CloseGossip();
478}
479
480//Need fix
481void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
482{
483    CHECK_PACKET_SIZE(recv_data,8);
484
485    sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS");
486    uint64 npcGUID;
487
488    recv_data >> npcGUID;
489
490    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
491    if (!unit)
492    {
493        sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
494        return;
495    }
496
497    // remove fake death
498    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
499        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
500
501    SendStablePet(npcGUID);
502}
503
504void WorldSession::SendStablePet(uint64 guid )
505{
506    sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");
507
508    WorldPacket data(MSG_LIST_STABLED_PETS, 200);           // guess size
509    data << uint64 ( guid );
510
511    Pet *pet = _player->GetPet();
512
513    data << uint8(0);                                       // place holder for slot show number
514    data << uint8(GetPlayer()->m_stableSlots);
515
516    uint8 num = 0;                                          // counter for place holder
517
518    // not let move dead pet in slot
519    if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET)
520    {
521        data << uint32(pet->GetCharmInfo()->GetPetNumber());
522        data << uint32(pet->GetEntry());
523        data << uint32(pet->getLevel());
524        data << pet->GetName();                             // petname
525        data << uint32(pet->GetLoyaltyLevel());             // loyalty
526        data << uint8(0x01);                                // client slot 1 == current pet (0)
527        ++num;
528    }
529
530    //                                                     0      1     2   3      4      5        6
531    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());
532
533    if(result)
534    {
535        do
536        {
537            Field *fields = result->Fetch();
538
539            data << uint32(fields[2].GetUInt32());          // petnumber
540            data << uint32(fields[3].GetUInt32());          // creature entry
541            data << uint32(fields[4].GetUInt32());          // level
542            data << fields[6].GetString();                  // name
543            data << uint32(fields[5].GetUInt32());          // loyalty
544            data << uint8(fields[1].GetUInt32()+1);         // slot
545
546            ++num;
547        }while( result->NextRow() );
548
549        delete result;
550    }
551
552    data.put<uint8>(8, num);                                // set real data to placeholder
553    SendPacket(&data);
554}
555
556void WorldSession::HandleStablePet( WorldPacket & recv_data )
557{
558    CHECK_PACKET_SIZE(recv_data,8);
559
560    sLog.outDebug("WORLD: Recv CMSG_STABLE_PET not dispose.");
561    uint64 npcGUID;
562
563    recv_data >> npcGUID;
564
565    if(!GetPlayer()->isAlive())
566        return;
567
568    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
569    if (!unit)
570    {
571        sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
572        return;
573    }
574
575    // remove fake death
576    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
577        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
578
579    Pet *pet = _player->GetPet();
580
581    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size
582
583    // can't place in stable dead pet
584    if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
585    {
586        data << uint8(0x06);
587        SendPacket(&data);
588        return;
589    }
590
591    uint32 free_slot = 1;
592
593    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());
594    if(result)
595    {
596        do
597        {
598            Field *fields = result->Fetch();
599
600            uint32 slot = fields[1].GetUInt32();
601
602            if(slot==free_slot)                             // this slot not free
603                ++free_slot;
604        }while( result->NextRow() );
605    }
606    delete result;
607
608    if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
609    {
610        _player->RemovePet(pet,PetSaveMode(free_slot));
611        data << uint8(0x08);
612    }
613    else
614        data << uint8(0x06);
615
616    SendPacket(&data);
617}
618
619void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
620{
621    CHECK_PACKET_SIZE(recv_data,8+4);
622
623    sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET.");
624    uint64 npcGUID;
625    uint32 petnumber;
626
627    recv_data >> npcGUID >> petnumber;
628
629    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
630    if (!unit)
631    {
632        sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
633        return;
634    }
635
636    // remove fake death
637    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
638        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
639
640    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size
641
642    Pet* pet = _player->GetPet();
643    if(pet && pet->isAlive())
644    {
645        uint8 i = 0x06;
646        data << uint8(i);
647        SendPacket(&data);
648        return;
649    }
650
651    // delete dead pet
652    if(pet)
653        _player->RemovePet(pet,PET_SAVE_AS_DELETED);
654
655    Pet *newpet = NULL;
656
657    QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber);
658    if(result)
659    {
660        Field *fields = result->Fetch();
661        uint32 petentry = fields[0].GetUInt32();
662
663        newpet = new Pet(HUNTER_PET);
664        if(!newpet->LoadPetFromDB(_player,petentry,petnumber))
665        {
666            delete newpet;
667            newpet = NULL;
668        }
669        delete result;
670    }
671
672    if(newpet)
673        data << uint8(0x09);
674    else
675        data << uint8(0x06);
676    SendPacket(&data);
677}
678
679void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
680{
681    CHECK_PACKET_SIZE(recv_data,8);
682
683    sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT.");
684    uint64 npcGUID;
685
686    recv_data >> npcGUID;
687
688    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
689    if (!unit)
690    {
691        sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
692        return;
693    }
694
695    // remove fake death
696    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
697        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
698
699    WorldPacket data(SMSG_STABLE_RESULT, 200);
700
701    if(GetPlayer()->m_stableSlots < 2)                      // max slots amount = 2
702    {
703        StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
704        if(_player->GetMoney() >= SlotPrice->Price)
705        {
706            ++GetPlayer()->m_stableSlots;
707            _player->ModifyMoney(-int32(SlotPrice->Price));
708            data << uint8(0x0A);                            // success buy
709        }
710        else
711            data << uint8(0x06);
712    }
713    else
714        data << uint8(0x06);
715
716    SendPacket(&data);
717}
718
719void WorldSession::HandleStableRevivePet( WorldPacket &/* recv_data */)
720{
721    sLog.outDebug("HandleStableRevivePet: Not implemented");
722}
723
724void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
725{
726    CHECK_PACKET_SIZE(recv_data,8+4);
727
728    sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET.");
729    uint64 npcGUID;
730    uint32 pet_number;
731
732    recv_data >> npcGUID >> pet_number;
733
734    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
735    if (!unit)
736    {
737        sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
738        return;
739    }
740
741    // remove fake death
742    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
743        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
744
745    WorldPacket data(SMSG_STABLE_RESULT, 200);              // guess size
746
747    Pet* pet = _player->GetPet();
748
749    if(!pet || pet->getPetType()!=HUNTER_PET)
750        return;
751
752    // find swapped pet slot in stable
753    QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
754    if(!result)
755        return;
756
757    Field *fields = result->Fetch();
758
759    uint32 slot     = fields[0].GetUInt32();
760    uint32 petentry = fields[1].GetUInt32();
761    delete result;
762
763    // move alive pet to slot or delele dead pet
764    _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
765
766    // summon unstabled pet
767    Pet *newpet = new Pet;
768    if(!newpet->LoadPetFromDB(_player,petentry,pet_number))
769    {
770        delete newpet;
771        data << uint8(0x06);
772    }
773    else
774        data << uint8(0x09);
775
776    SendPacket(&data);
777}
778
779void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data )
780{
781    CHECK_PACKET_SIZE(recv_data,8+8+1);
782
783    sLog.outDebug("WORLD: CMSG_REPAIR_ITEM");
784
785    uint64 npcGUID, itemGUID;
786    uint8 guildBank;                                        // new in 2.3.2, bool that means from guild bank money
787
788    recv_data >> npcGUID >> itemGUID >> guildBank;
789
790    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR);
791    if (!unit)
792    {
793        sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
794        return;
795    }
796
797    // remove fake death
798    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
799        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
800
801    // reputation discount
802    float discountMod = _player->GetReputationPriceDiscount(unit);
803
804    uint32 TotalCost = 0;
805    if (itemGUID)
806    {
807        sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
808
809        Item* item = _player->GetItemByGuid(itemGUID);
810
811        if(item)
812            TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false);
813    }
814    else
815    {
816        sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
817
818        TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false);
819    }
820    if (guildBank)
821    {
822        uint32 GuildId = _player->GetGuildId();
823        if (!GuildId)
824            return;
825        Guild *pGuild = objmgr.GetGuildById(GuildId);
826        if (!pGuild)
827            return;
828        pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost);
829        pGuild->SendMoneyInfo(this, _player->GetGUIDLow());
830    }
831}
Note: See TracBrowser for help on using the browser.