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
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
26 #include "ObjectMgr.h"
29 #include "GossipDef.h"
30 #include "UpdateMask.h"
31 #include "ScriptCalls.h"
32 #include "ObjectAccessor.h"
35 #include "BattleGroundMgr.h"
36 #include "BattleGround.h"
39 void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket
& recv_data
)
41 CHECK_PACKET_SIZE(recv_data
,8);
46 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(guid
,UNIT_NPC_FLAG_TABARDDESIGNER
);
49 sLog
.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid
)) );
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 );
67 void WorldSession::HandleBankerActivateOpcode( WorldPacket
& recv_data
)
69 CHECK_PACKET_SIZE(recv_data
,8);
73 sLog
.outDebug( "WORLD: Received CMSG_BANKER_ACTIVATE" );
77 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(guid
,UNIT_NPC_FLAG_BANKER
);
80 sLog
.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid
)) );
85 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
86 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
91 void WorldSession::SendShowBank( uint64 guid
)
93 WorldPacket
data( SMSG_SHOW_BANK
, 8 );
98 void WorldSession::HandleTrainerListOpcode( WorldPacket
& recv_data
)
100 CHECK_PACKET_SIZE(recv_data
,8);
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
= GetPlayer()->GetNPCIfCanInteractWith(guid
,UNIT_NPC_FLAG_TRAINER
);
121 sLog
.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid
)) );
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))
133 CreatureInfo
const *ci
= unit
->GetCreatureInfo();
137 sLog
.outDebug( "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(guid
) );
141 TrainerSpellData
const* trainer_spells
= unit
->GetTrainerSpells();
144 sLog
.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)",
145 GUID_LOPART(guid
), unit
->GetEntry());
149 WorldPacket
data( SMSG_TRAINER_LIST
, 8+4+4+trainer_spells
->spellList
.size()*38 + strTitle
.size()+1);
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
);
158 bool can_learn_primary_prof
= GetPlayer()->GetFreePrimaryProffesionPoints() > 0;
161 for(TrainerSpellMap::const_iterator itr
= trainer_spells
->spellList
.begin(); itr
!= trainer_spells
->spellList
.end(); ++itr
)
163 TrainerSpell
const* tSpell
= &itr
->second
;
165 if(!_player
->IsSpellFitByClassAndRace(tSpell
->learnedSpell
))
168 bool primary_prof_first_rank
= spellmgr
.IsPrimaryProfessionFirstRankSpell(tSpell
->learnedSpell
);
169 SpellChainNode
const* chain_node
= spellmgr
.GetSpellChainNode(tSpell
->learnedSpell
);
170 TrainerSpellState state
= _player
->GetTrainerSpellState(tSpell
);
172 data
<< uint32(tSpell
->spell
); // learned spell (or cast-spell in profession case)
173 data
<< uint8(state
==TRAINER_SPELL_GREEN_DISABLED
? TRAINER_SPELL_GREEN
: state
);
174 data
<< uint32(floor(tSpell
->spellCost
* fDiscountMod
));
176 data
<< uint32(primary_prof_first_rank
&& can_learn_primary_prof
? 1 : 0);
177 // 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(!tSpell
->IsCastable() && chain_node
? (chain_node
->prev
? chain_node
->prev
: chain_node
->req
) : 0);
183 data
<< uint32(!tSpell
->IsCastable() && chain_node
&& chain_node
->prev
? chain_node
->req
: 0);
191 data
.put
<uint32
>(count_pos
,count
);
195 void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket
& recv_data
)
197 CHECK_PACKET_SIZE(recv_data
,8+4);
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
= GetPlayer()->GetNPCIfCanInteractWith(guid
, UNIT_NPC_FLAG_TRAINER
);
208 sLog
.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid
)) );
213 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
214 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
216 if(!unit
->isCanTrainingOf(_player
,true))
219 // check present spell in trainer spell list
220 TrainerSpellData
const* trainer_spells
= unit
->GetTrainerSpells();
225 TrainerSpell
const* trainer_spell
= trainer_spells
->Find(spellId
);
229 // can't be learn, cheat? Or double learn with lags...
230 if(_player
->GetTrainerSpellState(trainer_spell
) != TRAINER_SPELL_GREEN
)
233 // apply reputation discount
234 uint32 nSpellCost
= uint32(floor(trainer_spell
->spellCost
* _player
->GetReputationPriceDiscount(unit
)));
236 // check money requirement
237 if(_player
->GetMoney() < nSpellCost
)
240 _player
->ModifyMoney( -int32(nSpellCost
) );
242 WorldPacket
data(SMSG_PLAY_SPELL_VISUAL
, 12); // visual effect on trainer
243 data
<< uint64(guid
) << uint32(0xB3);
246 data
.Initialize(SMSG_PLAY_SPELL_IMPACT
, 12); // visual effect on player
247 data
<< uint64(_player
->GetGUID()) << uint32(0x016A);
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);
255 _player
->learnSpell(spellId
,false);
257 data
.Initialize(SMSG_TRAINER_BUY_SUCCEEDED
, 12);
258 data
<< uint64(guid
) << uint32(trainer_spell
->spell
);
262 void WorldSession::HandleGossipHelloOpcode( WorldPacket
& recv_data
)
264 CHECK_PACKET_SIZE(recv_data
,8);
266 sLog
.outDebug( "WORLD: Received CMSG_GOSSIP_HELLO" );
271 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(guid
, UNIT_NPC_FLAG_NONE
);
274 sLog
.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid
)) );
279 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
280 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
282 if( unit
->isArmorer() || unit
->isCivilian() || unit
->isQuestGiver() || unit
->isServiceProvider())
287 // If spiritguide, no need for gossip menu, just put player into resurrect queue
288 if (unit
->isSpiritGuide())
290 BattleGround
*bg
= _player
->GetBattleGround();
293 bg
->AddPlayerToResurrectQueue(unit
->GetGUID(), _player
->GetGUID());
294 sBattleGroundMgr
.SendAreaSpiritHealerQueryOpcode(_player
, bg
, unit
->GetGUID());
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");
316 std::string code
= "";
318 recv_data
>> guid
>> unk
>> option
;
320 if(_player
->PlayerTalkClass
->GossipOptionCoded( option
))
323 CHECK_PACKET_SIZE(recv_data
,8+4+1);
324 sLog
.outBasic("reading string");
326 sLog
.outBasic("string read: %s", code
.c_str());
329 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(guid
, UNIT_NPC_FLAG_NONE
);
332 sLog
.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid
)) );
337 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
338 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
342 if (!Script
->GossipSelectWithCode(_player
, unit
, _player
->PlayerTalkClass
->GossipOptionSender (option
), _player
->PlayerTalkClass
->GossipOptionAction( option
), code
.c_str()))
343 unit
->OnGossipSelect (_player
, option
);
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");
362 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(guid
, UNIT_NPC_FLAG_SPIRITHEALER
);
365 sLog
.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid
)) );
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();
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
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
402 ObjectAccessor::UpdateVisibilityForPlayer(_player
);
404 // or update at original position
406 ObjectAccessor::UpdateVisibilityForPlayer(_player
);
411 void WorldSession::HandleBinderActivateOpcode( WorldPacket
& recv_data
)
413 CHECK_PACKET_SIZE(recv_data
,8);
416 recv_data
>> npcGUID
;
418 if(!GetPlayer()->isAlive())
421 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(npcGUID
,UNIT_NPC_FLAG_INNKEEPER
);
424 sLog
.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID
)) );
429 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
430 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
435 void WorldSession::SendBindPoint(Creature
*npc
)
437 // prevent set homebind to instances in any case
438 if(sMapStore
.LookupEntry(GetPlayer()->GetMapId())->Instanceable())
441 uint32 bindspell
= 3286;
442 uint32 zone_id
= _player
->GetZoneId();
444 // update sql homebind
445 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());
446 _player
->m_homebindMapId
= _player
->GetMapId();
447 _player
->m_homebindZoneId
= zone_id
;
448 _player
->m_homebindX
= _player
->GetPositionX();
449 _player
->m_homebindY
= _player
->GetPositionY();
450 _player
->m_homebindZ
= _player
->GetPositionZ();
452 // send spell for bind 3286 bind magic
453 npc
->CastSpell(_player
, bindspell
, true);
455 WorldPacket
data( SMSG_TRAINER_BUY_SUCCEEDED
, (8+4));
456 data
<< npc
->GetGUID();
461 data
.Initialize( SMSG_BINDPOINTUPDATE
, (4+4+4+4+4) );
462 data
<< float(_player
->GetPositionX());
463 data
<< float(_player
->GetPositionY());
464 data
<< float(_player
->GetPositionZ());
465 data
<< uint32(_player
->GetMapId());
466 data
<< uint32(zone_id
);
469 DEBUG_LOG("New Home Position X is %f",_player
->GetPositionX());
470 DEBUG_LOG("New Home Position Y is %f",_player
->GetPositionY());
471 DEBUG_LOG("New Home Position Z is %f",_player
->GetPositionZ());
472 DEBUG_LOG("New Home MapId is %u",_player
->GetMapId());
473 DEBUG_LOG("New Home ZoneId is %u",zone_id
);
476 data
.Initialize( SMSG_PLAYERBOUND
, 8+4 );
477 data
<< uint64(_player
->GetGUID());
478 data
<< uint32(zone_id
);
481 _player
->PlayerTalkClass
->CloseGossip();
484 void WorldSession::HandleListStabledPetsOpcode( WorldPacket
& recv_data
)
486 CHECK_PACKET_SIZE(recv_data
,8);
488 sLog
.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS");
491 recv_data
>> npcGUID
;
493 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(npcGUID
, UNIT_NPC_FLAG_STABLEMASTER
);
496 sLog
.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID
)) );
501 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
502 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
504 SendStablePet(npcGUID
);
507 void WorldSession::SendStablePet(uint64 guid
)
509 sLog
.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");
511 WorldPacket
data(MSG_LIST_STABLED_PETS
, 200); // guess size
512 data
<< uint64 ( guid
);
514 Pet
*pet
= _player
->GetPet();
516 size_t wpos
= data
.wpos();
517 data
<< uint8(0); // place holder for slot show number
519 data
<< uint8(GetPlayer()->m_stableSlots
);
521 uint8 num
= 0; // counter for place holder
523 // not let move dead pet in slot
524 if(pet
&& pet
->isAlive() && pet
->getPetType()==HUNTER_PET
)
526 data
<< uint32(pet
->GetCharmInfo()->GetPetNumber());
527 data
<< uint32(pet
->GetEntry());
528 data
<< uint32(pet
->getLevel());
529 data
<< pet
->GetName(); // petname
530 data
<< uint8(1); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)
535 QueryResult
* result
= CharacterDatabase
.PQuery("SELECT owner, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot",
536 _player
->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT
,PET_SAVE_LAST_STABLE_SLOT
);
542 Field
*fields
= result
->Fetch();
544 data
<< uint32(fields
[1].GetUInt32()); // petnumber
545 data
<< uint32(fields
[2].GetUInt32()); // creature entry
546 data
<< uint32(fields
[3].GetUInt32()); // level
547 data
<< fields
[4].GetString(); // name
548 data
<< uint8(2); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)
551 }while( result
->NextRow() );
556 data
.put
<uint8
>(wpos
, num
); // set real data to placeholder
560 void WorldSession::HandleStablePet( WorldPacket
& recv_data
)
562 CHECK_PACKET_SIZE(recv_data
, 8);
564 sLog
.outDebug("WORLD: Recv CMSG_STABLE_PET");
567 recv_data
>> npcGUID
;
569 if(!GetPlayer()->isAlive())
572 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(npcGUID
, UNIT_NPC_FLAG_STABLEMASTER
);
575 sLog
.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID
)) );
580 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
581 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
583 Pet
*pet
= _player
->GetPet();
585 WorldPacket
data(SMSG_STABLE_RESULT
, 200); // guess size
587 // can't place in stable dead pet
588 if(!pet
||!pet
->isAlive()||pet
->getPetType()!=HUNTER_PET
)
595 uint32 free_slot
= 1;
597 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot ",
598 _player
->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT
,PET_SAVE_LAST_STABLE_SLOT
);
603 Field
*fields
= result
->Fetch();
605 uint32 slot
= fields
[1].GetUInt32();
607 // slots ordered in query, and if not equal then free
611 // this slot not free, skip
613 }while( result
->NextRow() );
618 if( free_slot
> 0 && free_slot
<= GetPlayer()->m_stableSlots
)
620 _player
->RemovePet(pet
,PetSaveMode(free_slot
));
629 void WorldSession::HandleUnstablePet( WorldPacket
& recv_data
)
631 CHECK_PACKET_SIZE(recv_data
, 8+4);
633 sLog
.outDebug("WORLD: Recv CMSG_UNSTABLE_PET.");
637 recv_data
>> npcGUID
>> petnumber
;
639 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(npcGUID
, UNIT_NPC_FLAG_STABLEMASTER
);
642 sLog
.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID
)) );
647 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
648 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
650 WorldPacket
data(SMSG_STABLE_RESULT
, 200); // guess size
652 Pet
* pet
= _player
->GetPet();
653 if(pet
&& pet
->isAlive())
662 _player
->RemovePet(pet
,PET_SAVE_AS_DELETED
);
666 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'",
667 _player
->GetGUIDLow(),petnumber
,PET_SAVE_FIRST_STABLE_SLOT
,PET_SAVE_LAST_STABLE_SLOT
);
670 Field
*fields
= result
->Fetch();
671 uint32 petentry
= fields
[0].GetUInt32();
673 newpet
= new Pet(HUNTER_PET
);
674 if(!newpet
->LoadPetFromDB(_player
,petentry
,petnumber
))
689 void WorldSession::HandleBuyStableSlot( WorldPacket
& recv_data
)
691 CHECK_PACKET_SIZE(recv_data
, 8);
693 sLog
.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT.");
696 recv_data
>> npcGUID
;
698 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(npcGUID
, UNIT_NPC_FLAG_STABLEMASTER
);
701 sLog
.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID
)) );
706 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
707 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
709 WorldPacket
data(SMSG_STABLE_RESULT
, 200);
711 if(GetPlayer()->m_stableSlots
< MAX_PET_STABLES
)
713 StableSlotPricesEntry
const *SlotPrice
= sStableSlotPricesStore
.LookupEntry(GetPlayer()->m_stableSlots
+1);
714 if(_player
->GetMoney() >= SlotPrice
->Price
)
716 ++GetPlayer()->m_stableSlots
;
717 _player
->ModifyMoney(-int32(SlotPrice
->Price
));
718 data
<< uint8(0x0A); // success buy
729 void WorldSession::HandleStableRevivePet( WorldPacket
&/* recv_data */)
731 sLog
.outDebug("HandleStableRevivePet: Not implemented");
734 void WorldSession::HandleStableSwapPet( WorldPacket
& recv_data
)
736 CHECK_PACKET_SIZE(recv_data
, 8+4);
738 sLog
.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET.");
742 recv_data
>> npcGUID
>> pet_number
;
744 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(npcGUID
, UNIT_NPC_FLAG_STABLEMASTER
);
747 sLog
.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID
)) );
752 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
753 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
755 WorldPacket
data(SMSG_STABLE_RESULT
, 200); // guess size
757 Pet
* pet
= _player
->GetPet();
759 if(!pet
|| pet
->getPetType()!=HUNTER_PET
)
762 // find swapped pet slot in stable
763 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",
764 _player
->GetGUIDLow(),pet_number
);
768 Field
*fields
= result
->Fetch();
770 uint32 slot
= fields
[0].GetUInt32();
771 uint32 petentry
= fields
[1].GetUInt32();
774 // move alive pet to slot or delete dead pet
775 _player
->RemovePet(pet
,pet
->isAlive() ? PetSaveMode(slot
) : PET_SAVE_AS_DELETED
);
777 // summon unstabled pet
778 Pet
*newpet
= new Pet
;
779 if(!newpet
->LoadPetFromDB(_player
,petentry
,pet_number
))
790 void WorldSession::HandleRepairItemOpcode( WorldPacket
& recv_data
)
792 CHECK_PACKET_SIZE(recv_data
, 8+8+1);
794 sLog
.outDebug("WORLD: CMSG_REPAIR_ITEM");
796 uint64 npcGUID
, itemGUID
;
797 uint8 guildBank
; // new in 2.3.2, bool that means from guild bank money
799 recv_data
>> npcGUID
>> itemGUID
>> guildBank
;
801 Creature
*unit
= GetPlayer()->GetNPCIfCanInteractWith(npcGUID
, UNIT_NPC_FLAG_REPAIR
);
804 sLog
.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID
)) );
809 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
810 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
812 // reputation discount
813 float discountMod
= _player
->GetReputationPriceDiscount(unit
);
815 uint32 TotalCost
= 0;
818 sLog
.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID
), GUID_LOPART(npcGUID
));
820 Item
* item
= _player
->GetItemByGuid(itemGUID
);
823 TotalCost
= _player
->DurabilityRepair(item
->GetPos(),true,discountMod
,guildBank
>0?true:false);
827 sLog
.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID
));
829 TotalCost
= _player
->DurabilityRepairAll(true,discountMod
,guildBank
>0?true:false);
833 uint32 GuildId
= _player
->GetGuildId();
836 Guild
*pGuild
= objmgr
.GetGuildById(GuildId
);
839 pGuild
->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY
, 0, _player
->GetGUIDLow(), TotalCost
);
840 pGuild
->SendMoneyInfo(this, _player
->GetGUIDLow());