removed unneeded World.h includes
[getmangos.git] / src / game / NPCHandler.cpp
blob12f7bfb93715043da5aa63d36f2050753ec55331
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
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.
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.
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
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 "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "GossipDef.h"
30 #include "SpellAuras.h"
31 #include "UpdateMask.h"
32 #include "ScriptCalls.h"
33 #include "ObjectAccessor.h"
34 #include "Creature.h"
35 #include "MapManager.h"
36 #include "Pet.h"
37 #include "BattleGroundMgr.h"
38 #include "BattleGround.h"
39 #include "Guild.h"
41 void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data )
43 CHECK_PACKET_SIZE(recv_data,8);
45 uint64 guid;
46 recv_data >> guid;
48 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER);
49 if (!unit)
51 sLog.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
52 return;
55 // remove fake death
56 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
57 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
59 SendTabardVendorActivate(guid);
62 void WorldSession::SendTabardVendorActivate( uint64 guid )
64 WorldPacket data( MSG_TABARDVENDOR_ACTIVATE, 8 );
65 data << guid;
66 SendPacket( &data );
69 void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data )
71 CHECK_PACKET_SIZE(recv_data,8);
73 uint64 guid;
75 sLog.outDebug( "WORLD: Received CMSG_BANKER_ACTIVATE" );
77 recv_data >> guid;
79 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER);
80 if (!unit)
82 sLog.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
83 return;
86 // remove fake death
87 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
88 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
90 SendShowBank(guid);
93 void WorldSession::SendShowBank( uint64 guid )
95 WorldPacket data( SMSG_SHOW_BANK, 8 );
96 data << guid;
97 SendPacket( &data );
100 void WorldSession::HandleTrainerListOpcode( WorldPacket & recv_data )
102 CHECK_PACKET_SIZE(recv_data,8);
104 uint64 guid;
106 recv_data >> guid;
107 SendTrainerList( guid );
110 void WorldSession::SendTrainerList( uint64 guid )
112 std::string str = GetMangosString(LANG_NPC_TAINER_HELLO);
113 SendTrainerList( guid, str );
116 void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle )
118 sLog.outDebug( "WORLD: SendTrainerList" );
120 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER);
121 if (!unit)
123 sLog.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
124 return;
127 // remove fake death
128 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
129 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
131 // trainer list loaded at check;
132 if(!unit->isCanTrainingOf(_player,true))
133 return;
135 CreatureInfo const *ci = unit->GetCreatureInfo();
137 if (!ci)
139 sLog.outDebug( "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(guid) );
140 return;
143 TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
144 if(!trainer_spells)
146 sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)",
147 GUID_LOPART(guid), unit->GetEntry());
148 return;
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);
155 size_t count_pos = data.wpos();
156 data << uint32(trainer_spells->spellList.size());
158 // reputation discount
159 float fDiscountMod = _player->GetReputationPriceDiscount(unit);
161 uint32 count = 0;
162 for(TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
164 TrainerSpell const* tSpell = &itr->second;
166 if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell))
167 continue;
169 ++count;
171 bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell);
173 SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learnedSpell);
175 data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case)
176 data << uint8(_player->GetTrainerSpellState(tSpell));
177 data << uint32(floor(tSpell->spellCost * fDiscountMod));
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);
189 data << strTitle;
191 data.put<uint32>(count_pos,count);
192 SendPacket( &data );
195 void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
197 CHECK_PACKET_SIZE(recv_data,8+4);
199 uint64 guid;
200 uint32 spellId = 0;
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 );
205 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER);
206 if (!unit)
208 sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
209 return;
212 // remove fake death
213 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
214 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
216 if(!unit->isCanTrainingOf(_player,true))
217 return;
219 // check present spell in trainer spell list
220 TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
221 if(!trainer_spells)
222 return;
224 // not found, cheat?
225 TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
226 if(!trainer_spell)
227 return;
229 // can't be learn, cheat? Or double learn with lags...
230 if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
231 return;
233 // apply reputation discount
234 uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit)));
236 // check money requirement
237 if(_player->GetMoney() < nSpellCost )
238 return;
240 _player->ModifyMoney( -int32(nSpellCost) );
242 WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
243 data << uint64(guid) << uint32(0xB3);
244 SendPacket(&data);
246 data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player
247 data << uint64(_player->GetGUID()) << uint32(0x016A);
248 SendPacket(&data);
250 // learn explicitly or cast explicitly
251 if(trainer_spell->IsCastable ())
252 //FIXME: prof. spell entry in trainer list not marked gray until list re-open.
253 _player->CastSpell(_player,trainer_spell->spell,true);
254 else
255 _player->learnSpell(spellId,false);
257 data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
258 data << uint64(guid) << uint32(trainer_spell->spell);
259 SendPacket(&data);
262 void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data )
264 CHECK_PACKET_SIZE(recv_data,8);
266 sLog.outDebug( "WORLD: Received CMSG_GOSSIP_HELLO" );
268 uint64 guid;
269 recv_data >> guid;
271 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
272 if (!unit)
274 sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
275 return;
278 // remove fake death
279 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
280 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
282 if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
284 unit->StopMoving();
287 // If spiritguide, no need for gossip menu, just put player into resurrect queue
288 if (unit->isSpiritGuide())
290 BattleGround *bg = _player->GetBattleGround();
291 if(bg)
293 bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
294 sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
295 return;
299 if(!Script->GossipHello( _player, unit ))
301 _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
302 unit->prepareGossipMenu(_player);
303 unit->sendPreparedGossip(_player);
307 void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
309 CHECK_PACKET_SIZE(recv_data,8+4+4);
311 sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
313 uint32 option;
314 uint32 unk;
315 uint64 guid;
316 std::string code = "";
318 recv_data >> guid >> unk >> option;
320 if(_player->PlayerTalkClass->GossipOptionCoded( option ))
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());
329 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
330 if (!unit)
332 sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
333 return;
336 // remove fake death
337 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
338 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
340 if(!code.empty())
342 if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()))
343 unit->OnGossipSelect (_player, option);
345 else
347 if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option)))
348 unit->OnGossipSelect (_player, option);
352 void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data )
354 CHECK_PACKET_SIZE(recv_data,8);
356 sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
358 uint64 guid;
360 recv_data >> guid;
362 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER);
363 if (!unit)
365 sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
366 return;
369 // remove fake death
370 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
371 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
373 SendSpiritResurrect();
376 void WorldSession::SendSpiritResurrect()
378 _player->ResurrectPlayer(0.5f, true);
380 _player->DurabilityLossAll(0.25f,true);
382 // get corpse nearest graveyard
383 WorldSafeLocsEntry const *corpseGrave = NULL;
384 Corpse *corpse = _player->GetCorpse();
385 if(corpse)
386 corpseGrave = objmgr.GetClosestGraveYard(
387 corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam() );
389 // now can spawn bones
390 _player->SpawnCorpseBones();
392 // teleport to nearest from corpse graveyard, if different from nearest to player ghost
393 if(corpseGrave)
395 WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard(
396 _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam() );
398 if(corpseGrave != ghostGrave)
399 _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
400 // or update at original position
401 else
402 ObjectAccessor::UpdateVisibilityForPlayer(_player);
404 // or update at original position
405 else
406 ObjectAccessor::UpdateVisibilityForPlayer(_player);
408 _player->SaveToDB();
411 void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
413 CHECK_PACKET_SIZE(recv_data,8);
415 uint64 npcGUID;
416 recv_data >> npcGUID;
418 if(!GetPlayer()->isAlive())
419 return;
421 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER);
422 if (!unit)
424 sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
425 return;
428 // remove fake death
429 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
430 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
432 SendBindPoint(unit);
435 void WorldSession::SendBindPoint(Creature *npc)
437 uint32 bindspell = 3286;
439 // update sql homebind
440 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());
441 _player->m_homebindMapId = _player->GetMapId();
442 _player->m_homebindZoneId = _player->GetZoneId();
443 _player->m_homebindX = _player->GetPositionX();
444 _player->m_homebindY = _player->GetPositionY();
445 _player->m_homebindZ = _player->GetPositionZ();
447 // send spell for bind 3286 bind magic
448 npc->CastSpell(_player, bindspell, true);
450 WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
451 data << npc->GetGUID();
452 data << bindspell;
453 SendPacket( &data );
455 // binding
456 data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
457 data << float(_player->GetPositionX());
458 data << float(_player->GetPositionY());
459 data << float(_player->GetPositionZ());
460 data << uint32(_player->GetMapId());
461 data << uint32(_player->GetZoneId());
462 SendPacket( &data );
464 DEBUG_LOG("New Home Position X is %f",_player->GetPositionX());
465 DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY());
466 DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ());
467 DEBUG_LOG("New Home MapId is %u",_player->GetMapId());
468 DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId());
470 // zone update
471 data.Initialize( SMSG_PLAYERBOUND, 8+4 );
472 data << uint64(_player->GetGUID());
473 data << uint32(_player->GetZoneId());
474 SendPacket( &data );
476 _player->PlayerTalkClass->CloseGossip();
479 //Need fix
480 void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
482 CHECK_PACKET_SIZE(recv_data,8);
484 sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS");
485 uint64 npcGUID;
487 recv_data >> npcGUID;
489 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
490 if (!unit)
492 sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
493 return;
496 // remove fake death
497 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
498 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
500 SendStablePet(npcGUID);
503 void WorldSession::SendStablePet(uint64 guid )
505 sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");
507 WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size
508 data << uint64 ( guid );
510 Pet *pet = _player->GetPet();
512 data << uint8(0); // place holder for slot show number
513 data << uint8(GetPlayer()->m_stableSlots);
515 uint8 num = 0; // counter for place holder
517 // not let move dead pet in slot
518 if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET)
520 data << uint32(pet->GetCharmInfo()->GetPetNumber());
521 data << uint32(pet->GetEntry());
522 data << uint32(pet->getLevel());
523 data << pet->GetName(); // petname
524 data << uint8(0x01); // flags?, client slot 1 == current pet (0)
525 ++num;
528 // 0 1 2 3 4 5
529 QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow());
531 if(result)
535 Field *fields = result->Fetch();
537 data << uint32(fields[2].GetUInt32()); // petnumber
538 data << uint32(fields[3].GetUInt32()); // creature entry
539 data << uint32(fields[4].GetUInt32()); // level
540 data << fields[5].GetString(); // name
541 data << uint8(fields[1].GetUInt32()+1); // slot
543 ++num;
544 }while( result->NextRow() );
546 delete result;
549 data.put<uint8>(8, num); // set real data to placeholder
550 SendPacket(&data);
553 void WorldSession::HandleStablePet( WorldPacket & recv_data )
555 CHECK_PACKET_SIZE(recv_data, 8);
557 sLog.outDebug("WORLD: Recv CMSG_STABLE_PET");
558 uint64 npcGUID;
560 recv_data >> npcGUID;
562 if(!GetPlayer()->isAlive())
563 return;
565 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
566 if (!unit)
568 sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
569 return;
572 // remove fake death
573 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
574 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
576 Pet *pet = _player->GetPet();
578 WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
580 // can't place in stable dead pet
581 if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
583 data << uint8(0x06);
584 SendPacket(&data);
585 return;
588 uint32 free_slot = 1;
590 QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5 ORDER BY slot ",_player->GetGUIDLow());
591 if(result)
595 Field *fields = result->Fetch();
597 uint32 slot = fields[1].GetUInt32();
599 if(slot==free_slot) // this slot not free
600 ++free_slot;
601 }while( result->NextRow() );
603 delete result;
605 if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
607 _player->RemovePet(pet,PetSaveMode(free_slot));
608 data << uint8(0x08);
610 else
611 data << uint8(0x06);
613 SendPacket(&data);
616 void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
618 CHECK_PACKET_SIZE(recv_data, 8+4);
620 sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET.");
621 uint64 npcGUID;
622 uint32 petnumber;
624 recv_data >> npcGUID >> petnumber;
626 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
627 if (!unit)
629 sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
630 return;
633 // remove fake death
634 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
635 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
637 WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
639 Pet* pet = _player->GetPet();
640 if(pet && pet->isAlive())
642 uint8 i = 0x06;
643 data << uint8(i);
644 SendPacket(&data);
645 return;
648 // delete dead pet
649 if(pet)
650 _player->RemovePet(pet,PET_SAVE_AS_DELETED);
652 Pet *newpet = NULL;
654 QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber);
655 if(result)
657 Field *fields = result->Fetch();
658 uint32 petentry = fields[0].GetUInt32();
660 newpet = new Pet(HUNTER_PET);
661 if(!newpet->LoadPetFromDB(_player,petentry,petnumber))
663 delete newpet;
664 newpet = NULL;
666 delete result;
669 if(newpet)
670 data << uint8(0x09);
671 else
672 data << uint8(0x06);
673 SendPacket(&data);
676 void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
678 CHECK_PACKET_SIZE(recv_data, 8);
680 sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT.");
681 uint64 npcGUID;
683 recv_data >> npcGUID;
685 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
686 if (!unit)
688 sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
689 return;
692 // remove fake death
693 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
694 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
696 WorldPacket data(SMSG_STABLE_RESULT, 200);
698 if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4
700 StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
701 if(_player->GetMoney() >= SlotPrice->Price)
703 ++GetPlayer()->m_stableSlots;
704 _player->ModifyMoney(-int32(SlotPrice->Price));
705 data << uint8(0x0A); // success buy
707 else
708 data << uint8(0x06);
710 else
711 data << uint8(0x06);
713 SendPacket(&data);
716 void WorldSession::HandleStableRevivePet( WorldPacket &/* recv_data */)
718 sLog.outDebug("HandleStableRevivePet: Not implemented");
721 void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
723 CHECK_PACKET_SIZE(recv_data, 8+4);
725 sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET.");
726 uint64 npcGUID;
727 uint32 pet_number;
729 recv_data >> npcGUID >> pet_number;
731 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
732 if (!unit)
734 sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
735 return;
738 // remove fake death
739 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
740 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
742 WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
744 Pet* pet = _player->GetPet();
746 if(!pet || pet->getPetType()!=HUNTER_PET)
747 return;
749 // find swapped pet slot in stable
750 QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
751 if(!result)
752 return;
754 Field *fields = result->Fetch();
756 uint32 slot = fields[0].GetUInt32();
757 uint32 petentry = fields[1].GetUInt32();
758 delete result;
760 // move alive pet to slot or delele dead pet
761 _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
763 // summon unstabled pet
764 Pet *newpet = new Pet;
765 if(!newpet->LoadPetFromDB(_player,petentry,pet_number))
767 delete newpet;
768 data << uint8(0x06);
770 else
771 data << uint8(0x09);
773 SendPacket(&data);
776 void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data )
778 CHECK_PACKET_SIZE(recv_data, 8+8+1);
780 sLog.outDebug("WORLD: CMSG_REPAIR_ITEM");
782 uint64 npcGUID, itemGUID;
783 uint8 guildBank; // new in 2.3.2, bool that means from guild bank money
785 recv_data >> npcGUID >> itemGUID >> guildBank;
787 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR);
788 if (!unit)
790 sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
791 return;
794 // remove fake death
795 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
796 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
798 // reputation discount
799 float discountMod = _player->GetReputationPriceDiscount(unit);
801 uint32 TotalCost = 0;
802 if (itemGUID)
804 sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
806 Item* item = _player->GetItemByGuid(itemGUID);
808 if(item)
809 TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false);
811 else
813 sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
815 TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false);
817 if (guildBank)
819 uint32 GuildId = _player->GetGuildId();
820 if (!GuildId)
821 return;
822 Guild *pGuild = objmgr.GetGuildById(GuildId);
823 if (!pGuild)
824 return;
825 pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost);
826 pGuild->SendMoneyInfo(this, _player->GetGUIDLow());