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

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

[svn] *** Source: MaNGOS ***
* Implement localization of creature/gameobject name that say/yell. Author: evilstar (rewrited by: Vladimir)
* Fix auth login queue. Author: Derex
* Allowed switching INVTYPE_HOLDABLE items during combat, used correct spells for triggering global cooldown at weapon switch. Author: mobel/simak
* Fixed some format arg type/value pairs. Other warnings. Author: Vladimir
* [238_world.sql] Allow have team dependent graveyards at entrance map for instances. Author: Vladimir

NOTE:
Entrance map graveyards selected by same way as local (by distance from entrance) Until DB support will work in old way base at current DB data.

Original author: visagalis
Date: 2008-11-14 17:03:03-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 - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(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)",
150            GUID_LOPART(guid), unit->GetEntry());
151        return;
152    }
153
154    WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1);
155    data << guid;
156    data << uint32(trainer_spells->trainerType);
157
158    size_t count_pos = data.wpos();
159    data << uint32(trainer_spells->spellList.size());
160
161    // reputation discount
162    float fDiscountMod = _player->GetReputationPriceDiscount(unit);
163
164    uint32 count = 0;
165    for(TrainerSpellList::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
166    {
167        TrainerSpell const* tSpell = *itr;
168
169        if(!_player->IsSpellFitByClassAndRace(tSpell->spell))
170            continue;
171
172        ++count;
173
174        bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell);
175
176        SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell);
177
178        data << uint32(tSpell->spell);
179        data << uint8(_player->GetTrainerSpellState(tSpell));
180        data << uint32(floor(tSpell->spellcost * fDiscountMod));
181
182        data << uint32(primary_prof_first_rank ? 1 : 0);    // primary prof. learn confirmation dialog
183        data << uint32(primary_prof_first_rank ? 1 : 0);    // must be equal prev. field to have learn button in enabled state
184        data << uint8(tSpell->reqlevel);
185        data << uint32(tSpell->reqskill);
186        data << uint32(tSpell->reqskillvalue);
187        data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
188        data << uint32(chain_node && chain_node->prev ? chain_node->req : 0);
189        data << uint32(0);
190    }
191
192    data << strTitle;
193
194    data.put<uint32>(count_pos,count);
195    SendPacket( &data );
196}
197
198void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
199{
200    CHECK_PACKET_SIZE(recv_data,8+4);
201
202    uint64 guid;
203    uint32 spellId = 0;
204
205    recv_data >> guid >> spellId;
206    sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId );
207
208    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER);
209    if (!unit)
210    {
211        sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
212        return;
213    }
214
215    // remove fake death
216    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
217        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
218
219    if(!unit->isCanTrainingOf(_player,true))
220        return;
221
222    // check present spell in trainer spell list
223    TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
224    if(!trainer_spells)
225        return; 
226
227    // not found, cheat?
228    TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
229    if(!trainer_spell)
230        return;
231
232    // can't be learn, cheat? Or double learn with lags...
233    if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
234        return;
235
236    // apply reputation discount
237    uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit)));
238
239    // check money requirement
240    if(_player->GetMoney() < nSpellCost )
241        return;
242
243    WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12);           // visual effect on trainer
244    data << uint64(guid) << uint32(0xB3);
245    SendPacket(&data);
246
247    data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12);            // visual effect on player
248    data << uint64(_player->GetGUID()) << uint32(0x016A);
249    SendPacket(&data);
250
251    _player->ModifyMoney( -int32(nSpellCost) );
252
253    // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
254    _player->learnSpell(trainer_spell->spell);
255
256    data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
257    data << uint64(guid) << uint32(spellId);
258    SendPacket(&data);
259}
260
261void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data )
262{
263    CHECK_PACKET_SIZE(recv_data,8);
264
265    sLog.outDebug(  "WORLD: Received CMSG_GOSSIP_HELLO" );
266
267    uint64 guid;
268    recv_data >> guid;
269
270    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
271    if (!unit)
272    {
273        sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
274        return;
275    }
276
277    GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
278    // remove fake death
279    //if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
280    //    GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
281
282    if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
283    {
284        unit->StopMoving();
285    }
286
287    // If spiritguide, no need for gossip menu, just put player into resurrect queue
288    if (unit->isSpiritGuide())
289    {
290        BattleGround *bg = _player->GetBattleGround();
291        if(bg)
292        {
293            bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
294            sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
295            return;
296        }
297    }
298
299    if(!Script->GossipHello( _player, unit ))
300    {
301        _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
302        unit->prepareGossipMenu(_player);
303        unit->sendPreparedGossip(_player);
304    }
305}
306
307void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
308{
309    CHECK_PACKET_SIZE(recv_data,8+4+4);
310
311    sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
312
313    uint32 option;
314    uint32 unk;
315    uint64 guid;
316    std::string code = "";
317
318    recv_data >> guid >> unk >> option;
319
320    if(_player->PlayerTalkClass->GossipOptionCoded( option ))
321    {
322        // recheck
323        CHECK_PACKET_SIZE(recv_data,8+4+1);
324        sLog.outBasic("reading string");
325        recv_data >> code;
326        sLog.outBasic("string read: %s", code.c_str());
327    }
328
329    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
330    if (!unit)
331    {
332        sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
333        return;
334    }
335
336    // remove fake death
337    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
338        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
339
340    if(!code.empty())
341    {
342
343        if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()))
344            unit->OnGossipSelect (_player, option);
345    }
346    else
347
348    {
349        if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option)))
350            unit->OnGossipSelect (_player, option);
351    }
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.