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

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

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

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