[7512] Implement checks of item bag mask at server startup.
[AHbot.git] / src / game / NPCHandler.cpp
blob65163b924fd96062722aa85a080c57c762e822be
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 "UpdateMask.h"
31 #include "ScriptCalls.h"
32 #include "ObjectAccessor.h"
33 #include "Creature.h"
34 #include "Pet.h"
35 #include "BattleGroundMgr.h"
36 #include "BattleGround.h"
37 #include "Guild.h"
39 void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data )
41 CHECK_PACKET_SIZE(recv_data,8);
43 uint64 guid;
44 recv_data >> guid;
46 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER);
47 if (!unit)
49 sLog.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
50 return;
53 // remove fake death
54 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
55 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
57 SendTabardVendorActivate(guid);
60 void WorldSession::SendTabardVendorActivate( uint64 guid )
62 WorldPacket data( MSG_TABARDVENDOR_ACTIVATE, 8 );
63 data << guid;
64 SendPacket( &data );
67 void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data )
69 CHECK_PACKET_SIZE(recv_data,8);
71 uint64 guid;
73 sLog.outDebug( "WORLD: Received CMSG_BANKER_ACTIVATE" );
75 recv_data >> guid;
77 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER);
78 if (!unit)
80 sLog.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
81 return;
84 // remove fake death
85 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
86 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
88 SendShowBank(guid);
91 void WorldSession::SendShowBank( uint64 guid )
93 WorldPacket data( SMSG_SHOW_BANK, 8 );
94 data << guid;
95 SendPacket( &data );
98 void WorldSession::HandleTrainerListOpcode( WorldPacket & recv_data )
100 CHECK_PACKET_SIZE(recv_data,8);
102 uint64 guid;
104 recv_data >> guid;
105 SendTrainerList( guid );
108 void WorldSession::SendTrainerList( uint64 guid )
110 std::string str = GetMangosString(LANG_NPC_TAINER_HELLO);
111 SendTrainerList( guid, str );
114 void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle )
116 sLog.outDebug( "WORLD: SendTrainerList" );
118 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER);
119 if (!unit)
121 sLog.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
122 return;
125 // remove fake death
126 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
127 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
129 // trainer list loaded at check;
130 if(!unit->isCanTrainingOf(_player,true))
131 return;
133 CreatureInfo const *ci = unit->GetCreatureInfo();
135 if (!ci)
137 sLog.outDebug( "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(guid) );
138 return;
141 TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
142 if(!trainer_spells)
144 sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)",
145 GUID_LOPART(guid), unit->GetEntry());
146 return;
149 WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1);
150 data << guid;
151 data << uint32(trainer_spells->trainerType);
153 size_t count_pos = data.wpos();
154 data << uint32(trainer_spells->spellList.size());
156 // reputation discount
157 float fDiscountMod = _player->GetReputationPriceDiscount(unit);
159 uint32 count = 0;
160 for(TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
162 TrainerSpell const* tSpell = &itr->second;
164 if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell))
165 continue;
167 ++count;
169 bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell);
171 SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learnedSpell);
173 data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case)
174 data << uint8(_player->GetTrainerSpellState(tSpell));
175 data << uint32(floor(tSpell->spellCost * fDiscountMod));
177 data << uint32(primary_prof_first_rank ? 1 : 0); // primary prof. learn confirmation dialog
178 data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
179 data << uint8(tSpell->reqLevel);
180 data << uint32(tSpell->reqSkill);
181 data << uint32(tSpell->reqSkillValue);
182 data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
183 data << uint32(chain_node && chain_node->prev ? chain_node->req : 0);
184 data << uint32(0);
187 data << strTitle;
189 data.put<uint32>(count_pos,count);
190 SendPacket( &data );
193 void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
195 CHECK_PACKET_SIZE(recv_data,8+4);
197 uint64 guid;
198 uint32 spellId = 0;
200 recv_data >> guid >> spellId;
201 sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId );
203 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER);
204 if (!unit)
206 sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
207 return;
210 // remove fake death
211 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
212 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
214 if(!unit->isCanTrainingOf(_player,true))
215 return;
217 // check present spell in trainer spell list
218 TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
219 if(!trainer_spells)
220 return;
222 // not found, cheat?
223 TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
224 if(!trainer_spell)
225 return;
227 // can't be learn, cheat? Or double learn with lags...
228 if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
229 return;
231 // apply reputation discount
232 uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit)));
234 // check money requirement
235 if(_player->GetMoney() < nSpellCost )
236 return;
238 _player->ModifyMoney( -int32(nSpellCost) );
240 WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
241 data << uint64(guid) << uint32(0xB3);
242 SendPacket(&data);
244 data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player
245 data << uint64(_player->GetGUID()) << uint32(0x016A);
246 SendPacket(&data);
248 // learn explicitly or cast explicitly
249 if(trainer_spell->IsCastable ())
250 //FIXME: prof. spell entry in trainer list not marked gray until list re-open.
251 _player->CastSpell(_player,trainer_spell->spell,true);
252 else
253 _player->learnSpell(spellId,false);
255 data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
256 data << uint64(guid) << uint32(trainer_spell->spell);
257 SendPacket(&data);
260 void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data )
262 CHECK_PACKET_SIZE(recv_data,8);
264 sLog.outDebug( "WORLD: Received CMSG_GOSSIP_HELLO" );
266 uint64 guid;
267 recv_data >> guid;
269 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
270 if (!unit)
272 sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
273 return;
276 // remove fake death
277 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
278 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
280 if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
282 unit->StopMoving();
285 // If spiritguide, no need for gossip menu, just put player into resurrect queue
286 if (unit->isSpiritGuide())
288 BattleGround *bg = _player->GetBattleGround();
289 if(bg)
291 bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
292 sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
293 return;
297 if(!Script->GossipHello( _player, unit ))
299 _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
300 unit->prepareGossipMenu(_player);
301 unit->sendPreparedGossip(_player);
305 void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
307 CHECK_PACKET_SIZE(recv_data,8+4+4);
309 sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
311 uint32 option;
312 uint32 unk;
313 uint64 guid;
314 std::string code = "";
316 recv_data >> guid >> unk >> option;
318 if(_player->PlayerTalkClass->GossipOptionCoded( option ))
320 // recheck
321 CHECK_PACKET_SIZE(recv_data,8+4+1);
322 sLog.outBasic("reading string");
323 recv_data >> code;
324 sLog.outBasic("string read: %s", code.c_str());
327 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
328 if (!unit)
330 sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
331 return;
334 // remove fake death
335 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
336 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
338 if(!code.empty())
340 if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()))
341 unit->OnGossipSelect (_player, option);
343 else
345 if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option)))
346 unit->OnGossipSelect (_player, option);
350 void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data )
352 CHECK_PACKET_SIZE(recv_data,8);
354 sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
356 uint64 guid;
358 recv_data >> guid;
360 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER);
361 if (!unit)
363 sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
364 return;
367 // remove fake death
368 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
369 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
371 SendSpiritResurrect();
374 void WorldSession::SendSpiritResurrect()
376 _player->ResurrectPlayer(0.5f, true);
378 _player->DurabilityLossAll(0.25f,true);
380 // get corpse nearest graveyard
381 WorldSafeLocsEntry const *corpseGrave = NULL;
382 Corpse *corpse = _player->GetCorpse();
383 if(corpse)
384 corpseGrave = objmgr.GetClosestGraveYard(
385 corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam() );
387 // now can spawn bones
388 _player->SpawnCorpseBones();
390 // teleport to nearest from corpse graveyard, if different from nearest to player ghost
391 if(corpseGrave)
393 WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard(
394 _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam() );
396 if(corpseGrave != ghostGrave)
397 _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
398 // or update at original position
399 else
400 ObjectAccessor::UpdateVisibilityForPlayer(_player);
402 // or update at original position
403 else
404 ObjectAccessor::UpdateVisibilityForPlayer(_player);
406 _player->SaveToDB();
409 void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
411 CHECK_PACKET_SIZE(recv_data,8);
413 uint64 npcGUID;
414 recv_data >> npcGUID;
416 if(!GetPlayer()->isAlive())
417 return;
419 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER);
420 if (!unit)
422 sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
423 return;
426 // remove fake death
427 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
428 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
430 SendBindPoint(unit);
433 void WorldSession::SendBindPoint(Creature *npc)
435 uint32 bindspell = 3286;
436 uint32 zone_id = _player->GetZoneId();
438 // update sql homebind
439 CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), zone_id, _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow());
440 _player->m_homebindMapId = _player->GetMapId();
441 _player->m_homebindZoneId = zone_id;
442 _player->m_homebindX = _player->GetPositionX();
443 _player->m_homebindY = _player->GetPositionY();
444 _player->m_homebindZ = _player->GetPositionZ();
446 // send spell for bind 3286 bind magic
447 npc->CastSpell(_player, bindspell, true);
449 WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
450 data << npc->GetGUID();
451 data << bindspell;
452 SendPacket( &data );
454 // binding
455 data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
456 data << float(_player->GetPositionX());
457 data << float(_player->GetPositionY());
458 data << float(_player->GetPositionZ());
459 data << uint32(_player->GetMapId());
460 data << uint32(zone_id);
461 SendPacket( &data );
463 DEBUG_LOG("New Home Position X is %f",_player->GetPositionX());
464 DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY());
465 DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ());
466 DEBUG_LOG("New Home MapId is %u",_player->GetMapId());
467 DEBUG_LOG("New Home ZoneId is %u",zone_id);
469 // zone update
470 data.Initialize( SMSG_PLAYERBOUND, 8+4 );
471 data << uint64(_player->GetGUID());
472 data << uint32(zone_id);
473 SendPacket( &data );
475 _player->PlayerTalkClass->CloseGossip();
478 //Need fix
479 void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
481 CHECK_PACKET_SIZE(recv_data,8);
483 sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS");
484 uint64 npcGUID;
486 recv_data >> npcGUID;
488 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
489 if (!unit)
491 sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
492 return;
495 // remove fake death
496 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
497 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
499 SendStablePet(npcGUID);
502 void WorldSession::SendStablePet(uint64 guid )
504 sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");
506 WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size
507 data << uint64 ( guid );
509 Pet *pet = _player->GetPet();
511 data << uint8(0); // place holder for slot show number
512 data << uint8(GetPlayer()->m_stableSlots);
514 uint8 num = 0; // counter for place holder
516 // not let move dead pet in slot
517 if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET)
519 data << uint32(pet->GetCharmInfo()->GetPetNumber());
520 data << uint32(pet->GetEntry());
521 data << uint32(pet->getLevel());
522 data << pet->GetName(); // petname
523 data << uint8(0x01); // flags?, client slot 1 == current pet (0)
524 ++num;
527 // 0 1 2 3 4 5
528 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());
530 if(result)
534 Field *fields = result->Fetch();
536 data << uint32(fields[2].GetUInt32()); // petnumber
537 data << uint32(fields[3].GetUInt32()); // creature entry
538 data << uint32(fields[4].GetUInt32()); // level
539 data << fields[5].GetString(); // name
540 data << uint8(fields[1].GetUInt32()+1); // slot
542 ++num;
543 }while( result->NextRow() );
545 delete result;
548 data.put<uint8>(8, num); // set real data to placeholder
549 SendPacket(&data);
552 void WorldSession::HandleStablePet( WorldPacket & recv_data )
554 CHECK_PACKET_SIZE(recv_data, 8);
556 sLog.outDebug("WORLD: Recv CMSG_STABLE_PET");
557 uint64 npcGUID;
559 recv_data >> npcGUID;
561 if(!GetPlayer()->isAlive())
562 return;
564 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
565 if (!unit)
567 sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
568 return;
571 // remove fake death
572 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
573 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
575 Pet *pet = _player->GetPet();
577 WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
579 // can't place in stable dead pet
580 if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
582 data << uint8(0x06);
583 SendPacket(&data);
584 return;
587 uint32 free_slot = 1;
589 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());
590 if(result)
594 Field *fields = result->Fetch();
596 uint32 slot = fields[1].GetUInt32();
598 if(slot==free_slot) // this slot not free
599 ++free_slot;
600 }while( result->NextRow() );
602 delete result;
604 if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
606 _player->RemovePet(pet,PetSaveMode(free_slot));
607 data << uint8(0x08);
609 else
610 data << uint8(0x06);
612 SendPacket(&data);
615 void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
617 CHECK_PACKET_SIZE(recv_data, 8+4);
619 sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET.");
620 uint64 npcGUID;
621 uint32 petnumber;
623 recv_data >> npcGUID >> petnumber;
625 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
626 if (!unit)
628 sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
629 return;
632 // remove fake death
633 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
634 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
636 WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
638 Pet* pet = _player->GetPet();
639 if(pet && pet->isAlive())
641 uint8 i = 0x06;
642 data << uint8(i);
643 SendPacket(&data);
644 return;
647 // delete dead pet
648 if(pet)
649 _player->RemovePet(pet,PET_SAVE_AS_DELETED);
651 Pet *newpet = NULL;
653 QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber);
654 if(result)
656 Field *fields = result->Fetch();
657 uint32 petentry = fields[0].GetUInt32();
659 newpet = new Pet(HUNTER_PET);
660 if(!newpet->LoadPetFromDB(_player,petentry,petnumber))
662 delete newpet;
663 newpet = NULL;
665 delete result;
668 if(newpet)
669 data << uint8(0x09);
670 else
671 data << uint8(0x06);
672 SendPacket(&data);
675 void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
677 CHECK_PACKET_SIZE(recv_data, 8);
679 sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT.");
680 uint64 npcGUID;
682 recv_data >> npcGUID;
684 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
685 if (!unit)
687 sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
688 return;
691 // remove fake death
692 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
693 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
695 WorldPacket data(SMSG_STABLE_RESULT, 200);
697 if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4
699 StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
700 if(_player->GetMoney() >= SlotPrice->Price)
702 ++GetPlayer()->m_stableSlots;
703 _player->ModifyMoney(-int32(SlotPrice->Price));
704 data << uint8(0x0A); // success buy
706 else
707 data << uint8(0x06);
709 else
710 data << uint8(0x06);
712 SendPacket(&data);
715 void WorldSession::HandleStableRevivePet( WorldPacket &/* recv_data */)
717 sLog.outDebug("HandleStableRevivePet: Not implemented");
720 void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
722 CHECK_PACKET_SIZE(recv_data, 8+4);
724 sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET.");
725 uint64 npcGUID;
726 uint32 pet_number;
728 recv_data >> npcGUID >> pet_number;
730 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
731 if (!unit)
733 sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
734 return;
737 // remove fake death
738 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
739 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
741 WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
743 Pet* pet = _player->GetPet();
745 if(!pet || pet->getPetType()!=HUNTER_PET)
746 return;
748 // find swapped pet slot in stable
749 QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
750 if(!result)
751 return;
753 Field *fields = result->Fetch();
755 uint32 slot = fields[0].GetUInt32();
756 uint32 petentry = fields[1].GetUInt32();
757 delete result;
759 // move alive pet to slot or delele dead pet
760 _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
762 // summon unstabled pet
763 Pet *newpet = new Pet;
764 if(!newpet->LoadPetFromDB(_player,petentry,pet_number))
766 delete newpet;
767 data << uint8(0x06);
769 else
770 data << uint8(0x09);
772 SendPacket(&data);
775 void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data )
777 CHECK_PACKET_SIZE(recv_data, 8+8+1);
779 sLog.outDebug("WORLD: CMSG_REPAIR_ITEM");
781 uint64 npcGUID, itemGUID;
782 uint8 guildBank; // new in 2.3.2, bool that means from guild bank money
784 recv_data >> npcGUID >> itemGUID >> guildBank;
786 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR);
787 if (!unit)
789 sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
790 return;
793 // remove fake death
794 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
795 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
797 // reputation discount
798 float discountMod = _player->GetReputationPriceDiscount(unit);
800 uint32 TotalCost = 0;
801 if (itemGUID)
803 sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
805 Item* item = _player->GetItemByGuid(itemGUID);
807 if(item)
808 TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false);
810 else
812 sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
814 TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false);
816 if (guildBank)
818 uint32 GuildId = _player->GetGuildId();
819 if (!GuildId)
820 return;
821 Guild *pGuild = objmgr.GetGuildById(GuildId);
822 if (!pGuild)
823 return;
824 pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost);
825 pGuild->SendMoneyInfo(this, _player->GetGUIDLow());