2008-10-11 14:16:25 -05:00
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Common.h"
#include "Language.h"
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Player.h"
#include "GossipDef.h"
#include "SpellAuras.h"
#include "UpdateMask.h"
#include "ScriptCalls.h"
#include "ObjectAccessor.h"
#include "Creature.h"
#include "MapManager.h"
#include "Pet.h"
#include "BattleGroundMgr.h"
#include "BattleGround.h"
#include "Guild.h"
void WorldSession :: HandleTabardVendorActivateOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
uint64 guid ;
recv_data >> guid ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , guid , UNIT_NPC_FLAG_TABARDDESIGNER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( guid )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
SendTabardVendorActivate ( guid );
}
void WorldSession :: SendTabardVendorActivate ( uint64 guid )
{
WorldPacket data ( MSG_TABARDVENDOR_ACTIVATE , 8 );
data << guid ;
SendPacket ( & data );
}
void WorldSession :: HandleBankerActivateOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
uint64 guid ;
sLog . outDebug ( "WORLD: Received CMSG_BANKER_ACTIVATE" );
recv_data >> guid ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , guid , UNIT_NPC_FLAG_BANKER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( guid )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
SendShowBank ( guid );
}
void WorldSession :: SendShowBank ( uint64 guid )
{
WorldPacket data ( SMSG_SHOW_BANK , 8 );
data << guid ;
SendPacket ( & data );
}
void WorldSession :: HandleTrainerListOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
uint64 guid ;
recv_data >> guid ;
SendTrainerList ( guid );
}
void WorldSession :: SendTrainerList ( uint64 guid )
{
std :: string str = GetMangosString ( LANG_NPC_TAINER_HELLO );
SendTrainerList ( guid , str );
}
void WorldSession :: SendTrainerList ( uint64 guid , std :: string strTitle )
{
sLog . outDebug ( "WORLD: SendTrainerList" );
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , guid , UNIT_NPC_FLAG_TRAINER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( guid )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
// trainer list loaded at check;
if ( ! unit -> isCanTrainingOf ( _player , true ))
return ;
CreatureInfo const * ci = unit -> GetCreatureInfo ();
if ( ! ci )
{
sLog . outDebug ( "WORLD: SendTrainerList - (%u) NO CREATUREINFO! (GUID: %u)" , uint32 ( GUID_LOPART ( guid )), guid );
return ;
}
TrainerSpellData const * trainer_spells = unit -> GetTrainerSpells ();
if ( ! trainer_spells )
{
sLog . outDebug ( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)" , guid , unit -> GetEntry ());
return ;
}
WorldPacket data ( SMSG_TRAINER_LIST , 8 + 4 + 4 + trainer_spells -> spellList . size () * 38 + strTitle . size () + 1 );
data << guid ;
data << uint32 ( trainer_spells -> trainerType );
size_t count_pos = data . wpos ();
data << uint32 ( trainer_spells -> spellList . size ());
// reputation discount
float fDiscountMod = _player -> GetReputationPriceDiscount ( unit );
uint32 count = 0 ;
for ( TrainerSpellList :: const_iterator itr = trainer_spells -> spellList . begin (); itr != trainer_spells -> spellList . end (); ++ itr )
{
TrainerSpell const * tSpell = * itr ;
if ( ! _player -> IsSpellFitByClassAndRace ( tSpell -> spell ))
continue ;
++ count ;
bool primary_prof_first_rank = spellmgr . IsPrimaryProfessionFirstRankSpell ( tSpell -> spell );
SpellChainNode const * chain_node = spellmgr . GetSpellChainNode ( tSpell -> spell );
data << uint32 ( tSpell -> spell );
data << uint8 ( _player -> GetTrainerSpellState ( tSpell ));
data << uint32 ( floor ( tSpell -> spellcost * fDiscountMod ));
data << uint32 ( primary_prof_first_rank ? 1 : 0 ); // primary prof. learn confirmation dialog
data << uint32 ( primary_prof_first_rank ? 1 : 0 ); // must be equal prev. field to have learn button in enabled state
data << uint8 ( tSpell -> reqlevel );
data << uint32 ( tSpell -> reqskill );
data << uint32 ( tSpell -> reqskillvalue );
data << uint32 ( chain_node ? ( chain_node -> prev ? chain_node -> prev : chain_node -> req ) : 0 );
data << uint32 ( chain_node && chain_node -> prev ? chain_node -> req : 0 );
data << uint32 ( 0 );
}
data << strTitle ;
data . put < uint32 > ( count_pos , count );
SendPacket ( & data );
}
void WorldSession :: HandleTrainerBuySpellOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 + 4 );
uint64 guid ;
uint32 spellId = 0 ;
recv_data >> guid >> spellId ;
sLog . outDebug ( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u" , uint32 ( GUID_LOPART ( guid )), spellId );
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , guid , UNIT_NPC_FLAG_TRAINER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( guid )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
if ( ! unit -> isCanTrainingOf ( _player , true ))
return ;
// check present spell in trainer spell list
TrainerSpellData const * trainer_spells = unit -> GetTrainerSpells ();
if ( ! trainer_spells )
return ;
// not found, cheat?
TrainerSpell const * trainer_spell = trainer_spells -> Find ( spellId );
if ( ! trainer_spell )
return ;
// can't be learn, cheat? Or double learn with lags...
if ( _player -> GetTrainerSpellState ( trainer_spell ) != TRAINER_SPELL_GREEN )
return ;
// apply reputation discount
uint32 nSpellCost = uint32 ( floor ( trainer_spell -> spellcost * _player -> GetReputationPriceDiscount ( unit )));
// check money requirement
if ( _player -> GetMoney () < nSpellCost )
return ;
WorldPacket data ( SMSG_PLAY_SPELL_VISUAL , 12 ); // visual effect on trainer
data << uint64 ( guid ) << uint32 ( 0xB3 );
SendPacket ( & data );
data . Initialize ( SMSG_PLAY_SPELL_IMPACT , 12 ); // visual effect on player
data << uint64 ( _player -> GetGUID ()) << uint32 ( 0x016A );
SendPacket ( & data );
_player -> ModifyMoney ( - int32 ( nSpellCost ) );
// learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
_player -> learnSpell ( trainer_spell -> spell );
data . Initialize ( SMSG_TRAINER_BUY_SUCCEEDED , 12 );
data << uint64 ( guid ) << uint32 ( spellId );
SendPacket ( & data );
}
void WorldSession :: HandleGossipHelloOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
sLog . outDebug ( "WORLD: Received CMSG_GOSSIP_HELLO" );
uint64 guid ;
recv_data >> guid ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , guid , UNIT_NPC_FLAG_NONE );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( guid )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
if ( unit -> isArmorer () || unit -> isCivilian () || unit -> isQuestGiver () || unit -> isServiceProvider ())
{
unit -> StopMoving ();
}
// If spiritguide, no need for gossip menu, just put player into resurrect queue
if ( unit -> isSpiritGuide ())
{
BattleGround * bg = _player -> GetBattleGround ();
if ( bg )
{
bg -> AddPlayerToResurrectQueue ( unit -> GetGUID (), _player -> GetGUID ());
sBattleGroundMgr . SendAreaSpiritHealerQueryOpcode ( _player , bg , unit -> GetGUID ());
return ;
}
}
if ( ! Script -> GossipHello ( _player , unit ))
{
_player -> TalkedToCreature ( unit -> GetEntry (), unit -> GetGUID ());
unit -> prepareGossipMenu ( _player , 0 );
unit -> sendPreparedGossip ( _player );
}
}
void WorldSession :: HandleGossipSelectOptionOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 + 4 + 4 );
sLog . outDebug ( "WORLD: CMSG_GOSSIP_SELECT_OPTION" );
uint32 option ;
uint32 unk ;
uint64 guid ;
std :: string code = "" ;
recv_data >> guid >> unk >> option ;
if ( _player -> PlayerTalkClass -> GossipOptionCoded ( option ))
{
// recheck
CHECK_PACKET_SIZE ( recv_data , 8 + 4 + 1 );
sLog . outBasic ( "reading string" );
recv_data >> code ;
sLog . outBasic ( "string read: %s" , code . c_str ());
}
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , guid , UNIT_NPC_FLAG_NONE );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( guid )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
if ( ! code . empty ())
{
if ( ! Script -> GossipSelectWithCode ( _player , unit , _player -> PlayerTalkClass -> GossipOptionSender ( option ), _player -> PlayerTalkClass -> GossipOptionAction ( option ), code . c_str ()) )
unit -> OnGossipSelect ( _player , option );
}
else
if ( ! Script -> GossipSelect ( _player , unit , _player -> PlayerTalkClass -> GossipOptionSender ( option ), _player -> PlayerTalkClass -> GossipOptionAction ( option )) )
unit -> OnGossipSelect ( _player , option );
}
void WorldSession :: HandleSpiritHealerActivateOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
sLog . outDebug ( "WORLD: CMSG_SPIRIT_HEALER_ACTIVATE" );
uint64 guid ;
recv_data >> guid ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , guid , UNIT_NPC_FLAG_SPIRITHEALER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( guid )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
SendSpiritResurrect ();
}
void WorldSession :: SendSpiritResurrect ()
{
_player -> ResurrectPlayer ( 0.5f , false , true );
_player -> DurabilityLossAll ( 0.25f , true );
// get corpse nearest graveyard
WorldSafeLocsEntry const * corpseGrave = NULL ;
Corpse * corpse = _player -> GetCorpse ();
if ( corpse )
corpseGrave = objmgr . GetClosestGraveYard (
corpse -> GetPositionX (), corpse -> GetPositionY (), corpse -> GetPositionZ (), corpse -> GetMapId (), _player -> GetTeam () );
// now can spawn bones
_player -> SpawnCorpseBones ();
// teleport to nearest from corpse graveyard, if different from nearest to player ghost
if ( corpseGrave )
{
WorldSafeLocsEntry const * ghostGrave = objmgr . GetClosestGraveYard (
_player -> GetPositionX (), _player -> GetPositionY (), _player -> GetPositionZ (), _player -> GetMapId (), _player -> GetTeam () );
if ( corpseGrave != ghostGrave )
_player -> TeleportTo ( corpseGrave -> map_id , corpseGrave -> x , corpseGrave -> y , corpseGrave -> z , _player -> GetOrientation ());
// or update at original position
else
ObjectAccessor :: UpdateVisibilityForPlayer ( _player );
}
// or update at original position
else
ObjectAccessor :: UpdateVisibilityForPlayer ( _player );
_player -> SaveToDB ();
}
void WorldSession :: HandleBinderActivateOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
uint64 npcGUID ;
recv_data >> npcGUID ;
if ( ! GetPlayer () -> isAlive ())
return ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , npcGUID , UNIT_NPC_FLAG_INNKEEPER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( npcGUID )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
SendBindPoint ( unit );
}
void WorldSession :: SendBindPoint ( Creature * npc )
{
uint32 bindspell = 3286 ;
// update sql homebind
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 ());
_player -> m_homebindMapId = _player -> GetMapId ();
_player -> m_homebindZoneId = _player -> GetZoneId ();
_player -> m_homebindX = _player -> GetPositionX ();
_player -> m_homebindY = _player -> GetPositionY ();
_player -> m_homebindZ = _player -> GetPositionZ ();
// send spell for bind 3286 bind magic
npc -> CastSpell ( _player , bindspell , true );
WorldPacket data ( SMSG_TRAINER_BUY_SUCCEEDED , ( 8 + 4 ));
data << npc -> GetGUID ();
data << bindspell ;
SendPacket ( & data );
// binding
data . Initialize ( SMSG_BINDPOINTUPDATE , ( 4 + 4 + 4 + 4 + 4 ) );
data << float ( _player -> GetPositionX ());
data << float ( _player -> GetPositionY ());
data << float ( _player -> GetPositionZ ());
data << uint32 ( _player -> GetMapId ());
data << uint32 ( _player -> GetZoneId ());
SendPacket ( & data );
DEBUG_LOG ( "New Home Position X is %f" , _player -> GetPositionX ());
DEBUG_LOG ( "New Home Position Y is %f" , _player -> GetPositionY ());
DEBUG_LOG ( "New Home Position Z is %f" , _player -> GetPositionZ ());
DEBUG_LOG ( "New Home MapId is %u" , _player -> GetMapId ());
DEBUG_LOG ( "New Home ZoneId is %u" , _player -> GetZoneId ());
// zone update
data . Initialize ( SMSG_PLAYERBOUND , 8 + 4 );
data << uint64 ( _player -> GetGUID ());
data << uint32 ( _player -> GetZoneId ());
SendPacket ( & data );
_player -> PlayerTalkClass -> CloseGossip ();
}
//Need fix
void WorldSession :: HandleListStabledPetsOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
sLog . outDebug ( "WORLD: Recv MSG_LIST_STABLED_PETS" );
uint64 npcGUID ;
recv_data >> npcGUID ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , npcGUID , UNIT_NPC_FLAG_STABLEMASTER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( npcGUID )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
SendStablePet ( npcGUID );
}
void WorldSession :: SendStablePet ( uint64 guid )
{
sLog . outDebug ( "WORLD: Recv MSG_LIST_STABLED_PETS Send." );
WorldPacket data ( MSG_LIST_STABLED_PETS , 200 ); // guess size
data << uint64 ( guid );
Pet * pet = _player -> GetPet ();
data << uint8 ( 0 ); // place holder for slot show number
data << uint8 ( GetPlayer () -> m_stableSlots );
uint8 num = 0 ; // counter for place holder
// not let move dead pet in slot
if ( pet && pet -> isAlive () && pet -> getPetType () == HUNTER_PET )
{
data << uint32 ( pet -> GetCharmInfo () -> GetPetNumber ());
data << uint32 ( pet -> GetEntry ());
data << uint32 ( pet -> getLevel ());
data << pet -> GetName (); // petname
data << uint32 ( pet -> GetLoyaltyLevel ()); // loyalty
data << uint8 ( 0x01 ); // client slot 1 == current pet (0)
++ num ;
}
// 0 1 2 3 4 5 6
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 ());
if ( result )
{
do
{
Field * fields = result -> Fetch ();
data << uint32 ( fields [ 2 ]. GetUInt32 ()); // petnumber
data << uint32 ( fields [ 3 ]. GetUInt32 ()); // creature entry
data << uint32 ( fields [ 4 ]. GetUInt32 ()); // level
data << fields [ 6 ]. GetString (); // name
data << uint32 ( fields [ 5 ]. GetUInt32 ()); // loyalty
data << uint8 ( fields [ 1 ]. GetUInt32 () + 1 ); // slot
++ num ;
} while ( result -> NextRow () );
delete result ;
}
data . put < uint8 > ( 8 , num ); // set real data to placeholder
SendPacket ( & data );
}
void WorldSession :: HandleStablePet ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
sLog . outDebug ( "WORLD: Recv CMSG_STABLE_PET not dispose." );
uint64 npcGUID ;
recv_data >> npcGUID ;
if ( ! GetPlayer () -> isAlive ())
return ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , npcGUID , UNIT_NPC_FLAG_STABLEMASTER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( npcGUID )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
Pet * pet = _player -> GetPet ();
WorldPacket data ( SMSG_STABLE_RESULT , 200 ); // guess size
// can't place in stable dead pet
if ( ! pet ||! pet -> isAlive () || pet -> getPetType () != HUNTER_PET )
{
data << uint8 ( 0x06 );
SendPacket ( & data );
return ;
}
uint32 free_slot = 1 ;
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 ());
if ( result )
{
do
{
Field * fields = result -> Fetch ();
uint32 slot = fields [ 1 ]. GetUInt32 ();
if ( slot == free_slot ) // this slot not free
++ free_slot ;
} while ( result -> NextRow () );
}
delete result ;
if ( free_slot > 0 && free_slot <= GetPlayer () -> m_stableSlots )
{
_player -> RemovePet ( pet , PetSaveMode ( free_slot ));
data << uint8 ( 0x08 );
}
else
data << uint8 ( 0x06 );
SendPacket ( & data );
}
void WorldSession :: HandleUnstablePet ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 + 4 );
sLog . outDebug ( "WORLD: Recv CMSG_UNSTABLE_PET." );
uint64 npcGUID ;
uint32 petnumber ;
recv_data >> npcGUID >> petnumber ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , npcGUID , UNIT_NPC_FLAG_STABLEMASTER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( npcGUID )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
WorldPacket data ( SMSG_STABLE_RESULT , 200 ); // guess size
Pet * pet = _player -> GetPet ();
if ( pet && pet -> isAlive ())
{
uint8 i = 0x06 ;
data << uint8 ( i );
SendPacket ( & data );
return ;
}
// delete dead pet
if ( pet )
_player -> RemovePet ( pet , PET_SAVE_AS_DELETED );
Pet * newpet = NULL ;
QueryResult * result = CharacterDatabase . PQuery ( "SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3" , _player -> GetGUIDLow (), petnumber );
if ( result )
{
Field * fields = result -> Fetch ();
uint32 petentry = fields [ 0 ]. GetUInt32 ();
newpet = new Pet ( HUNTER_PET );
if ( ! newpet -> LoadPetFromDB ( _player , petentry , petnumber ))
{
delete newpet ;
newpet = NULL ;
}
delete result ;
}
if ( newpet )
data << uint8 ( 0x09 );
else
data << uint8 ( 0x06 );
SendPacket ( & data );
}
void WorldSession :: HandleBuyStableSlot ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 );
sLog . outDebug ( "WORLD: Recv CMSG_BUY_STABLE_SLOT." );
uint64 npcGUID ;
recv_data >> npcGUID ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , npcGUID , UNIT_NPC_FLAG_STABLEMASTER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( npcGUID )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
WorldPacket data ( SMSG_STABLE_RESULT , 200 );
if ( GetPlayer () -> m_stableSlots < 2 ) // max slots amount = 2
{
StableSlotPricesEntry const * SlotPrice = sStableSlotPricesStore . LookupEntry ( GetPlayer () -> m_stableSlots + 1 );
if ( _player -> GetMoney () >= SlotPrice -> Price )
{
++ GetPlayer () -> m_stableSlots ;
_player -> ModifyMoney ( - int32 ( SlotPrice -> Price ));
data << uint8 ( 0x0A ); // success buy
}
else
data << uint8 ( 0x06 );
}
else
data << uint8 ( 0x06 );
SendPacket ( & data );
}
void WorldSession :: HandleStableRevivePet ( WorldPacket & /* recv_data */ )
{
sLog . outDebug ( "HandleStableRevivePet: Not implemented" );
}
void WorldSession :: HandleStableSwapPet ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 + 4 );
sLog . outDebug ( "WORLD: Recv CMSG_STABLE_SWAP_PET." );
uint64 npcGUID ;
uint32 pet_number ;
recv_data >> npcGUID >> pet_number ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , npcGUID , UNIT_NPC_FLAG_STABLEMASTER );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( npcGUID )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
WorldPacket data ( SMSG_STABLE_RESULT , 200 ); // guess size
Pet * pet = _player -> GetPet ();
if ( ! pet || pet -> getPetType () != HUNTER_PET )
return ;
// find swapped pet slot in stable
QueryResult * result = CharacterDatabase . PQuery ( "SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'" , _player -> GetGUIDLow (), pet_number );
if ( ! result )
return ;
Field * fields = result -> Fetch ();
uint32 slot = fields [ 0 ]. GetUInt32 ();
uint32 petentry = fields [ 1 ]. GetUInt32 ();
delete result ;
// move alive pet to slot or delele dead pet
_player -> RemovePet ( pet , pet -> isAlive () ? PetSaveMode ( slot ) : PET_SAVE_AS_DELETED );
// summon unstabled pet
Pet * newpet = new Pet ;
if ( ! newpet -> LoadPetFromDB ( _player , petentry , pet_number ))
{
delete newpet ;
data << uint8 ( 0x06 );
}
else
data << uint8 ( 0x09 );
SendPacket ( & data );
}
void WorldSession :: HandleRepairItemOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 + 8 + 1 );
sLog . outDebug ( "WORLD: CMSG_REPAIR_ITEM" );
uint64 npcGUID , itemGUID ;
uint8 guildBank ; // new in 2.3.2, bool that means from guild bank money
recv_data >> npcGUID >> itemGUID >> guildBank ;
Creature * unit = ObjectAccessor :: GetNPCIfCanInteractWith ( * _player , npcGUID , UNIT_NPC_FLAG_REPAIR );
if ( ! unit )
{
sLog . outDebug ( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him." , uint32 ( GUID_LOPART ( npcGUID )) );
return ;
}
// remove fake death
if ( GetPlayer () -> hasUnitState ( UNIT_STAT_DIED ))
GetPlayer () -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
// reputation discount
float discountMod = _player -> GetReputationPriceDiscount ( unit );
uint32 TotalCost = 0 ;
if ( itemGUID )
{
sLog . outDebug ( "ITEM: Repair item, itemGUID = %u, npcGUID = %u" , GUID_LOPART ( itemGUID ), GUID_LOPART ( npcGUID ));
Item * item = _player -> GetItemByGuid ( itemGUID );
if ( item )
TotalCost = _player -> DurabilityRepair ( item -> GetPos (), true , discountMod , guildBank > 0 ? true : false );
}
else
{
sLog . outDebug ( "ITEM: Repair all items, npcGUID = %u" , GUID_LOPART ( npcGUID ));
TotalCost = _player -> DurabilityRepairAll ( true , discountMod , guildBank > 0 ? true : false );
}
if ( guildBank )
{
uint32 GuildId = _player -> GetGuildId ();
if ( ! GuildId )
return ;
Guild * pGuild = objmgr . GetGuildById ( GuildId );
if ( ! pGuild )
return ;
pGuild -> LogBankEvent ( GUILD_BANK_LOG_REPAIR_MONEY , 0 , _player -> GetGUIDLow (), TotalCost );
pGuild -> SendMoneyInfo ( this , _player -> GetGUIDLow ());
}
}