2008-10-11 14:16:25 -05:00
/*
2009-02-04 12:42:26 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2009-02-04 12:04:12 +01:00
* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
2008-10-11 14:16:25 -05:00
*
* 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
2008-11-03 09:53:31 -06:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-11 14:16:25 -05:00
* 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
2008-11-03 09:53:31 -06:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Log.h"
#include "Opcodes.h"
#include "Spell.h"
#include "ObjectAccessor.h"
#include "CreatureAI.h"
#include "Util.h"
#include "Pet.h"
2009-05-25 12:51:14 -05:00
#include "World.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandlePetAction ( WorldPacket & recv_data )
{
uint64 guid1 ;
2009-07-01 18:07:20 -05:00
uint32 data ;
2008-10-11 14:16:25 -05:00
uint64 guid2 ;
recv_data >> guid1 ; //pet guid
2009-07-01 18:07:20 -05:00
recv_data >> data ;
2008-10-11 14:16:25 -05:00
recv_data >> guid2 ; //tag guid
2009-10-17 15:51:44 -07:00
2009-07-01 18:07:20 -05:00
uint32 spellid = UNIT_ACTION_BUTTON_ACTION ( data );
uint8 flag = UNIT_ACTION_BUTTON_TYPE ( data ); //delete = 0x07 CastSpell = C1
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// used also for charmed creature
2008-12-12 11:21:28 -06:00
Unit * pet = ObjectAccessor :: GetUnit ( * _player , guid1 );
2009-07-01 18:07:20 -05:00
sLog . outDetail ( "HandlePetAction.Pet %u flag is %u, spellid is %u, target %u." , uint32 ( GUID_LOPART ( guid1 )), uint32 ( flag ), spellid , uint32 ( GUID_LOPART ( guid2 )) );
2008-10-11 14:16:25 -05:00
if ( ! pet )
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "Pet %u not exist." , uint32 ( GUID_LOPART ( guid1 )) );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-03-21 10:17:24 -06:00
if ( pet != GetPlayer () -> GetFirstControlled ())
2008-10-11 14:16:25 -05:00
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "HandlePetAction.Pet %u isn't pet of player %s." , uint32 ( GUID_LOPART ( guid1 )), GetPlayer () -> GetName () );
2008-10-11 14:16:25 -05:00
return ;
}
2010-01-16 19:11:32 +03:00
if ( ! pet -> isAlive ())
return ;
2009-10-17 15:51:44 -07:00
2009-03-21 11:15:55 -06:00
//TODO: allow control charmed player?
2008-10-11 14:16:25 -05:00
if ( pet -> GetTypeId () == TYPEID_PLAYER && ! ( flag == ACT_COMMAND && spellid == COMMAND_ATTACK ))
return ;
2009-10-17 15:51:44 -07:00
2009-03-21 13:42:09 -06:00
if ( GetPlayer () -> m_Controlled . size () == 1 )
HandlePetActionHelper ( pet , guid1 , spellid , flag , guid2 );
else
2009-03-21 12:16:14 -06:00
{
2009-03-21 13:42:09 -06:00
//If a pet is dismissed, m_Controlled will change
std :: vector < Unit *> controlled ;
2009-10-17 16:20:24 -07:00
for ( Unit :: ControlList :: iterator itr = GetPlayer () -> m_Controlled . begin (); itr != GetPlayer () -> m_Controlled . end (); ++ itr )
2009-03-21 13:42:09 -06:00
if (( * itr ) -> GetEntry () == pet -> GetEntry () && ( * itr ) -> isAlive ())
controlled . push_back ( * itr );
2009-10-17 16:20:24 -07:00
for ( std :: vector < Unit *>:: iterator itr = controlled . begin (); itr != controlled . end (); ++ itr )
2009-03-21 13:42:09 -06:00
HandlePetActionHelper ( * itr , guid1 , spellid , flag , guid2 );
2009-03-21 12:16:14 -06:00
}
2009-03-21 11:15:55 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-21 11:15:55 -06:00
void WorldSession :: HandlePetActionHelper ( Unit * pet , uint64 guid1 , uint16 spellid , uint16 flag , uint64 guid2 )
{
2008-10-11 14:16:25 -05:00
CharmInfo * charmInfo = pet -> GetCharmInfo ();
if ( ! charmInfo )
{
2009-05-31 16:15:12 -05:00
sLog . outError ( "WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!" , pet -> GetGUIDLow (), pet -> GetTypeId ());
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
switch ( flag )
{
2009-07-01 18:07:20 -05:00
case ACT_COMMAND : //0x07
2008-10-11 14:16:25 -05:00
switch ( spellid )
{
case COMMAND_STAY : //flat=1792 //STAY
2009-03-12 14:15:44 -06:00
pet -> AttackStop ();
pet -> InterruptNonMeleeSpells ( false );
2008-10-11 14:16:25 -05:00
pet -> GetMotionMaster () -> MoveIdle ();
charmInfo -> SetCommandState ( COMMAND_STAY );
2009-10-17 15:51:44 -07:00
2009-09-10 09:59:16 -07:00
charmInfo -> SetIsCommandAttack ( false );
charmInfo -> SetIsAtStay ( true );
charmInfo -> SetIsFollowing ( false );
charmInfo -> SetIsReturning ( false );
charmInfo -> SaveStayPosition ();
2008-10-11 14:16:25 -05:00
break ;
case COMMAND_FOLLOW : //spellid=1792 //FOLLOW
pet -> AttackStop ();
2009-03-12 14:15:44 -06:00
pet -> InterruptNonMeleeSpells ( false );
2009-07-22 17:10:30 +02:00
pet -> GetMotionMaster () -> MoveFollow ( _player , PET_FOLLOW_DIST , pet -> GetFollowAngle ());
2008-10-11 14:16:25 -05:00
charmInfo -> SetCommandState ( COMMAND_FOLLOW );
2009-10-17 15:51:44 -07:00
2009-09-10 09:59:16 -07:00
charmInfo -> SetIsCommandAttack ( false );
charmInfo -> SetIsAtStay ( false );
charmInfo -> SetIsReturning ( true );
charmInfo -> SetIsFollowing ( false );
2008-10-11 14:16:25 -05:00
break ;
case COMMAND_ATTACK : //spellid=1792 //ATTACK
{
2008-11-20 20:27:04 -05:00
// Can't attack if owner is pacified
if ( _player -> HasAuraType ( SPELL_AURA_MOD_PACIFY ))
{
//pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED);
//TODO: Send proper error message to client
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// only place where pet can be player
2009-04-29 18:04:56 -05:00
Unit * TargetUnit = ObjectAccessor :: GetUnit ( * _player , guid2 );
2008-10-11 14:16:25 -05:00
if ( ! TargetUnit )
return ;
2009-10-17 15:51:44 -07:00
2009-04-30 09:58:34 -05:00
if ( ! pet -> canAttack ( TargetUnit ))
2008-11-28 11:38:28 -06:00
return ;
2009-10-17 15:51:44 -07:00
2008-11-28 11:38:28 -06:00
// Not let attack through obstructions
2009-05-21 23:17:52 +02:00
if ( sWorld . getConfig ( CONFIG_PET_LOS ))
{
2009-10-17 15:51:44 -07:00
2009-05-21 23:17:52 +02:00
if ( ! pet -> IsWithinLOSInMap ( TargetUnit ))
return ;
2009-10-17 15:51:44 -07:00
2009-05-21 23:17:52 +02:00
}
2009-10-17 16:20:24 -07:00
2009-04-30 09:58:34 -05:00
pet -> clearUnitState ( UNIT_STAT_FOLLOW );
2009-01-21 16:18:57 -06:00
// This is true if pet has no target or has target but targets differs.
2009-10-09 21:34:23 +02:00
if ( pet -> getVictim () != TargetUnit || ( pet -> getVictim () == TargetUnit && ! pet -> GetCharmInfo () -> IsCommandAttack () ))
2008-10-11 14:16:25 -05:00
{
2009-01-21 16:18:57 -06:00
if ( pet -> getVictim ())
pet -> AttackStop ();
2009-10-17 15:51:44 -07:00
2009-03-07 10:19:07 -06:00
if ( pet -> GetTypeId () != TYPEID_PLAYER && (( Creature * ) pet ) -> IsAIEnabled )
2008-10-11 14:16:25 -05:00
{
2009-09-10 09:59:16 -07:00
charmInfo -> SetIsCommandAttack ( true );
charmInfo -> SetIsAtStay ( false );
charmInfo -> SetIsFollowing ( false );
charmInfo -> SetIsReturning ( false );
2009-10-17 15:51:44 -07:00
2009-03-07 10:19:07 -06:00
(( Creature * ) pet ) -> AI () -> AttackStart ( TargetUnit );
2009-10-17 15:51:44 -07:00
2009-01-21 16:18:57 -06:00
//10% chance to play special pet attack talk, else growl
if ((( Creature * ) pet ) -> isPet () && (( Pet * ) pet ) -> getPetType () == SUMMON_PET && pet != TargetUnit && urand ( 0 , 100 ) < 10 )
pet -> SendPetTalk (( uint32 ) PET_TALK_ATTACK );
else
{
// 90% chance for pet and 100% chance for charmed creature
pet -> SendPetAIReaction ( guid1 );
}
2008-10-11 14:16:25 -05:00
}
2009-07-01 18:07:20 -05:00
else // charmed player
2009-01-21 16:18:57 -06:00
{
if ( pet -> getVictim () && pet -> getVictim () != TargetUnit )
pet -> AttackStop ();
2009-10-17 15:51:44 -07:00
2009-09-10 09:59:16 -07:00
charmInfo -> SetIsCommandAttack ( true );
charmInfo -> SetIsAtStay ( false );
charmInfo -> SetIsFollowing ( false );
charmInfo -> SetIsReturning ( false );
2009-10-17 15:51:44 -07:00
2009-01-21 16:18:57 -06:00
pet -> Attack ( TargetUnit , true );
pet -> SendPetAIReaction ( guid1 );
}
2008-10-11 14:16:25 -05:00
}
break ;
}
case COMMAND_ABANDON : // abandon (hunter pet) or dismiss (summoned pet)
2009-05-06 10:13:33 -05:00
if ( pet -> GetCharmerGUID () == GetPlayer () -> GetGUID ())
2009-05-09 21:59:01 -05:00
_player -> StopCastingCharm ();
2009-05-06 10:13:33 -05:00
else if ( pet -> GetOwnerGUID () == GetPlayer () -> GetGUID ())
{
assert ( pet -> GetTypeId () == TYPEID_UNIT );
2009-08-29 23:20:16 -05:00
if ( pet -> isPet ())
2009-05-06 10:13:33 -05:00
{
if ((( Pet * ) pet ) -> getPetType () == HUNTER_PET )
GetPlayer () -> RemovePet (( Pet * ) pet , PET_SAVE_AS_DELETED );
else
//dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
pet -> setDeathState ( CORPSE );
}
2009-08-29 23:20:16 -05:00
else if ( pet -> HasUnitTypeMask ( UNIT_MASK_MINION ))
2009-05-06 10:13:33 -05:00
{
(( Minion * ) pet ) -> UnSummon ();
}
2008-10-11 14:16:25 -05:00
}
break ;
default :
2009-07-01 18:07:20 -05:00
sLog . outError ( "WORLD: unknown PET flag Action %i and spellid %i." , uint32 ( flag ), spellid );
2008-10-11 14:16:25 -05:00
}
break ;
2009-07-01 18:07:20 -05:00
case ACT_REACTION : // 0x6
2008-10-11 14:16:25 -05:00
switch ( spellid )
{
case REACT_PASSIVE : //passive
2009-09-10 09:59:16 -07:00
pet -> AttackStop ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case REACT_DEFENSIVE : //recovery
case REACT_AGGRESSIVE : //activete
2009-03-05 18:48:56 -06:00
if ( pet -> GetTypeId () == TYPEID_UNIT )
(( Creature * ) pet ) -> SetReactState ( ReactStates ( spellid ) );
2008-10-11 14:16:25 -05:00
break ;
}
break ;
2009-07-01 18:07:20 -05:00
case ACT_DISABLED : // 0x81 spell (disabled), ignore
case ACT_PASSIVE : // 0x01
case ACT_ENABLED : // 0xC1 spell
2008-10-11 14:16:25 -05:00
{
2009-01-21 16:18:57 -06:00
Unit * unit_target = NULL ;
2009-10-17 15:51:44 -07:00
2009-01-21 16:18:57 -06:00
if ( guid2 )
unit_target = ObjectAccessor :: GetUnit ( * _player , guid2 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// do not cast unknown spells
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( spellid );
if ( ! spellInfo )
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "WORLD: unknown PET spell id %i" , spellid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-01-13 18:22:31 +01:00
if ( spellInfo -> StartRecoveryCategory > 0 )
if ((( Creature * ) pet ) -> GetGlobalCooldown () > 0 )
2010-01-13 10:03:09 +01:00
return ;
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < 3 ; ++ i )
2008-10-11 14:16:25 -05:00
{
2009-05-02 11:28:11 -05:00
if ( spellInfo -> EffectImplicitTargetA [ i ] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo -> EffectImplicitTargetA [ i ] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo -> EffectImplicitTargetA [ i ] == TARGET_DEST_DYNOBJ_ENEMY )
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// do not cast not learned spells
if ( ! pet -> HasSpell ( spellid ) || IsPassiveSpell ( spellid ))
return ;
2009-10-17 15:51:44 -07:00
2009-09-10 09:59:16 -07:00
// Clear the flags as if owner clicked 'attack'. AI will reset them
// after AttackStart, even if spell failed
if ( pet -> GetCharmInfo ())
{
pet -> GetCharmInfo () -> SetIsAtStay ( false );
pet -> GetCharmInfo () -> SetIsCommandAttack ( true );
pet -> GetCharmInfo () -> SetIsReturning ( false );
pet -> GetCharmInfo () -> SetIsFollowing ( false );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Spell * spell = new Spell ( pet , spellInfo , false );
2009-10-17 15:51:44 -07:00
2009-03-16 12:00:14 -06:00
SpellCastResult result = spell -> CheckPetCast ( unit_target );
2009-10-17 15:51:44 -07:00
2009-01-21 16:18:57 -06:00
//auto turn to target unless possessed
2009-08-29 23:20:16 -05:00
if ( result == SPELL_FAILED_UNIT_NOT_INFRONT && ! pet -> isPossessed () && ! pet -> IsVehicle ())
2008-10-11 14:16:25 -05:00
{
2009-04-27 18:42:35 -05:00
if ( unit_target )
{
pet -> SetInFront ( unit_target );
if ( unit_target -> GetTypeId () == TYPEID_PLAYER )
2009-12-19 19:46:07 +01:00
pet -> SendUpdateToPlayer ( ( Player * ) unit_target );
2009-04-27 18:42:35 -05:00
}
else if ( Unit * unit_target2 = spell -> m_targets . getUnitTarget ())
{
pet -> SetInFront ( unit_target2 );
if ( unit_target2 -> GetTypeId () == TYPEID_PLAYER )
2009-12-19 19:46:07 +01:00
pet -> SendUpdateToPlayer ( ( Player * ) unit_target2 );
2009-04-27 18:42:35 -05:00
}
if ( Unit * powner = pet -> GetCharmerOrOwner ())
2008-10-11 14:16:25 -05:00
if ( powner -> GetTypeId () == TYPEID_PLAYER )
2009-12-19 19:46:07 +01:00
pet -> SendUpdateToPlayer (( Player * ) powner );
2009-03-16 12:00:14 -06:00
result = SPELL_CAST_OK ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-16 12:00:14 -06:00
if ( result == SPELL_CAST_OK )
2008-10-11 14:16:25 -05:00
{
(( Creature * ) pet ) -> AddCreatureSpellCooldown ( spellid );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
unit_target = spell -> m_targets . getUnitTarget ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//10% chance to play special pet attack talk, else growl
//actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
if ((( Creature * ) pet ) -> isPet () && ((( Pet * ) pet ) -> getPetType () == SUMMON_PET ) && ( pet != unit_target ) && ( urand ( 0 , 100 ) < 10 ))
pet -> SendPetTalk (( uint32 ) PET_TALK_SPECIAL_SPELL );
else
{
pet -> SendPetAIReaction ( guid1 );
}
2009-10-17 15:51:44 -07:00
2009-08-29 23:20:16 -05:00
if ( unit_target && ! GetPlayer () -> IsFriendlyTo ( unit_target ) && ! pet -> isPossessed () && ! pet -> IsVehicle ())
2008-10-11 14:16:25 -05:00
{
2009-01-21 16:18:57 -06:00
// This is true if pet has no target or has target but targets differs.
if ( pet -> getVictim () != unit_target )
{
if ( pet -> getVictim ())
pet -> AttackStop ();
pet -> GetMotionMaster () -> Clear ();
2009-03-06 18:09:01 -06:00
if ((( Creature * ) pet ) -> IsAIEnabled )
2009-01-21 16:18:57 -06:00
(( Creature * ) pet ) -> AI () -> AttackStart ( unit_target );
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
spell -> prepare ( & ( spell -> m_targets ));
}
else
{
2009-08-29 23:20:16 -05:00
if ( pet -> isPossessed () || pet -> IsVehicle ())
2009-06-08 17:25:02 -05:00
Spell :: SendCastResult ( GetPlayer (), spellInfo , 0 , result );
2008-10-11 14:16:25 -05:00
else
pet -> SendPetCastFail ( spellid , result );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! (( Creature * ) pet ) -> HasSpellCooldown ( spellid ))
2009-06-23 14:05:37 +02:00
GetPlayer () -> SendClearCooldown ( spellid , pet );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
spell -> finish ( false );
delete spell ;
2009-10-17 15:51:44 -07:00
2009-09-10 09:59:16 -07:00
// reset specific flags in case of spell fail. AI will reset other flags
if ( pet -> GetCharmInfo ())
pet -> GetCharmInfo () -> SetIsCommandAttack ( false );
2008-10-11 14:16:25 -05:00
}
break ;
}
default :
2009-07-01 18:07:20 -05:00
sLog . outError ( "WORLD: unknown PET flag Action %i and spellid %i." , uint32 ( flag ), spellid );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandlePetNameQuery ( WorldPacket & recv_data )
{
2009-03-09 17:56:51 -06:00
sLog . outDetail ( "HandlePetNameQuery. CMSG_PET_NAME_QUERY" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 petnumber ;
uint64 petguid ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
recv_data >> petnumber ;
recv_data >> petguid ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SendPetNameQuery ( petguid , petnumber );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: SendPetNameQuery ( uint64 petguid , uint32 petnumber )
{
2009-01-24 11:28:00 -06:00
Creature * pet = ObjectAccessor :: GetCreatureOrPetOrVehicle ( * _player , petguid );
2008-10-11 14:16:25 -05:00
if ( ! pet || ! pet -> GetCharmInfo () || pet -> GetCharmInfo () -> GetPetNumber () != petnumber )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
std :: string name = pet -> GetName ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( SMSG_PET_NAME_QUERY_RESPONSE , ( 4 + 4 + name . size () + 1 ));
data << uint32 ( petnumber );
data << name . c_str ();
data << uint32 ( pet -> GetUInt32Value ( UNIT_FIELD_PET_NAME_TIMESTAMP ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( pet -> isPet () && (( Pet * ) pet ) -> GetDeclinedNames () )
{
data << uint8 ( 1 );
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; i < MAX_DECLINED_NAME_CASES ; ++ i )
2008-10-11 14:16:25 -05:00
data << (( Pet * ) pet ) -> GetDeclinedNames () -> name [ i ];
}
else
data << uint8 ( 0 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_player -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandlePetSetAction ( WorldPacket & recv_data )
{
2009-03-09 17:56:51 -06:00
sLog . outDetail ( "HandlePetSetAction. CMSG_PET_SET_ACTION" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint64 petguid ;
uint8 count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
recv_data >> petguid ;
2009-10-17 15:51:44 -07:00
2009-03-21 10:17:24 -06:00
Unit * pet = ObjectAccessor :: GetUnit ( * _player , petguid );
2009-10-17 15:51:44 -07:00
2009-03-21 10:17:24 -06:00
if ( ! pet || pet != _player -> GetFirstControlled ())
2008-10-11 14:16:25 -05:00
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "HandlePetSetAction: Unknown pet or pet owner." );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CharmInfo * charmInfo = pet -> GetCharmInfo ();
if ( ! charmInfo )
{
2009-05-31 16:15:12 -05:00
sLog . outError ( "WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!" , pet -> GetGUIDLow (), pet -> GetTypeId ());
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
count = ( recv_data . size () == 24 ) ? 2 : 1 ;
2009-10-17 15:51:44 -07:00
2009-12-17 18:21:06 +01:00
uint32 position [ 2 ];
uint32 data [ 2 ];
bool move_command = false ;
2009-12-18 13:41:30 -08:00
2009-12-17 18:21:06 +01:00
for ( uint8 i = 0 ; i < count ; ++ i )
{
recv_data >> position [ i ];
recv_data >> data [ i ];
2009-12-18 13:41:30 -08:00
2009-12-17 18:21:06 +01:00
uint8 act_state = UNIT_ACTION_BUTTON_TYPE ( data [ i ]);
2009-12-18 13:41:30 -08:00
2009-05-27 17:02:39 -05:00
//ignore invalid position
2009-12-17 18:21:06 +01:00
if ( position [ i ] >= MAX_UNIT_ACTION_BAR_INDEX )
return ;
2009-12-18 13:41:30 -08:00
2009-12-17 18:21:06 +01:00
// in the normal case, command and reaction buttons can only be moved, not removed
// at moving count ==2, at removing count == 1
// ignore attempt to remove command|reaction buttons (not possible at normal case)
if ( act_state == ACT_COMMAND || act_state == ACT_REACTION )
{
if ( count == 1 )
return ;
2009-12-18 13:41:30 -08:00
2009-12-17 18:21:06 +01:00
move_command = true ;
}
}
2009-12-18 13:41:30 -08:00
2009-12-17 18:25:50 +01:00
// check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness)
2009-12-17 18:21:06 +01:00
if ( move_command )
{
uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE ( data [ 0 ]);
2009-12-17 18:25:50 +01:00
if ( act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION )
{
uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION ( data [ 0 ]);
UnitActionBarEntry const * actionEntry_1 = charmInfo -> GetActionBarEntry ( position [ 1 ]);
if ( ! actionEntry_1 || spell_id_0 != actionEntry_1 -> GetAction () ||
act_state_0 != actionEntry_1 -> GetType ())
return ;
}
2009-12-18 13:41:30 -08:00
2009-12-17 18:21:06 +01:00
uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE ( data [ 1 ]);
2009-12-17 18:25:50 +01:00
if ( act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION )
{
uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION ( data [ 1 ]);
UnitActionBarEntry const * actionEntry_0 = charmInfo -> GetActionBarEntry ( position [ 0 ]);
if ( ! actionEntry_0 || spell_id_1 != actionEntry_0 -> GetAction () ||
act_state_1 != actionEntry_0 -> GetType ())
return ;
}
2009-12-17 18:21:06 +01:00
}
2009-12-18 13:41:30 -08:00
2009-12-17 18:21:06 +01:00
for ( uint8 i = 0 ; i < count ; ++ i )
{
uint32 spell_id = UNIT_ACTION_BUTTON_ACTION ( data [ i ]);
uint8 act_state = UNIT_ACTION_BUTTON_TYPE ( data [ i ]);
2009-12-18 13:41:30 -08:00
2009-12-17 18:21:06 +01:00
sLog . outDetail ( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X" , _player -> GetName (), position [ i ], spell_id , uint32 ( act_state ));
2009-10-17 15:51:44 -07:00
2009-05-27 17:02:39 -05:00
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
2008-12-24 09:58:26 -06:00
if ( ! (( act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE ) && spell_id && ! pet -> HasSpell ( spell_id )))
2008-10-11 14:16:25 -05:00
{
//sign for autocast
if ( act_state == ACT_ENABLED && spell_id )
{
2009-03-28 11:56:45 -06:00
if ( pet -> GetTypeId () == TYPEID_UNIT && (( Creature * ) pet ) -> isPet ())
2008-10-11 14:16:25 -05:00
(( Pet * ) pet ) -> ToggleAutocast ( spell_id , true );
2009-03-28 11:56:45 -06:00
else
charmInfo -> ToggleCreatureAutocast ( spell_id , true );
2008-10-11 14:16:25 -05:00
}
//sign for no/turn off autocast
else if ( act_state == ACT_DISABLED && spell_id )
{
2009-03-28 11:56:45 -06:00
if ( pet -> GetTypeId () == TYPEID_UNIT && (( Creature * ) pet ) -> isPet ())
2008-10-11 14:16:25 -05:00
(( Pet * ) pet ) -> ToggleAutocast ( spell_id , false );
2009-03-28 11:56:45 -06:00
else
charmInfo -> ToggleCreatureAutocast ( spell_id , false );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-17 18:21:06 +01:00
charmInfo -> SetActionBar ( position [ i ], spell_id , ActiveStates ( act_state ));
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandlePetRename ( WorldPacket & recv_data )
{
2009-03-09 17:56:51 -06:00
sLog . outDetail ( "HandlePetRename. CMSG_PET_RENAME" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint64 petguid ;
uint8 isdeclined ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
std :: string name ;
DeclinedName declinedname ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
recv_data >> petguid ;
recv_data >> name ;
recv_data >> isdeclined ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Pet * pet = ObjectAccessor :: GetPet ( petguid );
// check it!
if ( ! pet || ! pet -> isPet () || (( Pet * ) pet ) -> getPetType () != HUNTER_PET ||
pet -> GetByteValue ( UNIT_FIELD_BYTES_2 , 2 ) != UNIT_RENAME_ALLOWED ||
pet -> GetOwnerGUID () != _player -> GetGUID () || ! pet -> GetCharmInfo () )
return ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
PetNameInvalidReason res = ObjectMgr :: CheckPetName ( name );
if ( res != PET_NAME_SUCCESS )
2008-10-11 14:16:25 -05:00
{
2009-07-10 08:25:33 +08:00
SendPetNameInvalid ( res , name , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-11-03 09:53:31 -06:00
if ( objmgr . IsReservedName ( name ))
{
SendPetNameInvalid ( PET_NAME_RESERVED , name , NULL );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pet -> SetName ( name );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Unit * owner = pet -> GetOwner ();
if ( owner && ( owner -> GetTypeId () == TYPEID_PLAYER ) && (( Player * ) owner ) -> GetGroup ())
(( Player * ) owner ) -> SetGroupUpdateFlag ( GROUP_UPDATE_FLAG_PET_NAME );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pet -> SetByteValue ( UNIT_FIELD_BYTES_2 , 2 , UNIT_RENAME_NOT_ALLOWED );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( isdeclined )
{
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; i < MAX_DECLINED_NAME_CASES ; ++ i )
2008-11-03 09:53:31 -06:00
{
2008-10-11 14:16:25 -05:00
recv_data >> declinedname . name [ i ];
2008-11-03 09:53:31 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
std :: wstring wname ;
2008-11-03 09:53:31 -06:00
Utf8toWStr ( name , wname );
2008-10-11 14:16:25 -05:00
if ( ! ObjectMgr :: CheckDeclinedNames ( GetMainPartOfName ( wname , 0 ), declinedname ))
{
2008-11-03 09:53:31 -06:00
SendPetNameInvalid ( PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME , name , & declinedname );
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CharacterDatabase . BeginTransaction ();
if ( isdeclined )
{
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; i < MAX_DECLINED_NAME_CASES ; ++ i )
2008-10-11 14:16:25 -05:00
CharacterDatabase . escape_string ( declinedname . name [ i ]);
CharacterDatabase . PExecute ( "DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'" , _player -> GetGUIDLow (), pet -> GetCharmInfo () -> GetPetNumber ());
CharacterDatabase . PExecute ( "INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')" ,
2008-11-03 09:53:31 -06:00
pet -> GetCharmInfo () -> GetPetNumber (), _player -> GetGUIDLow (), declinedname . name [ 0 ]. c_str (), declinedname . name [ 1 ]. c_str (), declinedname . name [ 2 ]. c_str (), declinedname . name [ 3 ]. c_str (), declinedname . name [ 4 ]. c_str ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CharacterDatabase . escape_string ( name );
2008-11-03 09:53:31 -06:00
CharacterDatabase . PExecute ( "UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'" , name . c_str (), _player -> GetGUIDLow (), pet -> GetCharmInfo () -> GetPetNumber ());
2008-10-11 14:16:25 -05:00
CharacterDatabase . CommitTransaction ();
2009-10-17 15:51:44 -07:00
2009-12-24 10:20:15 +01:00
pet -> SetUInt32Value ( UNIT_FIELD_PET_NAME_TIMESTAMP , time ( NULL ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandlePetAbandon ( WorldPacket & recv_data )
{
uint64 guid ;
recv_data >> guid ; //pet guid
sLog . outDetail ( "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u" , GUID_LOPART ( guid ) );
2009-10-17 15:51:44 -07:00
2009-07-01 18:36:03 -05:00
if ( ! _player -> IsInWorld ())
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// pet/charmed
2009-01-24 11:28:00 -06:00
Creature * pet = ObjectAccessor :: GetCreatureOrPetOrVehicle ( * _player , guid );
2008-10-11 14:16:25 -05:00
if ( pet )
{
if ( pet -> isPet ())
{
if ( pet -> GetGUID () == _player -> GetPetGUID ())
{
uint32 feelty = pet -> GetPower ( POWER_HAPPINESS );
pet -> SetPower ( POWER_HAPPINESS ,( feelty - 50000 ) > 0 ? ( feelty - 50000 ) : 0 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_player -> RemovePet (( Pet * ) pet , PET_SAVE_AS_DELETED );
}
else if ( pet -> GetGUID () == _player -> GetCharmGUID ())
2009-03-20 14:01:46 -06:00
_player -> StopCastingCharm ();
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandlePetUnlearnOpcode ( WorldPacket & recvPacket )
{
sLog . outDetail ( "CMSG_PET_UNLEARN" );
uint64 guid ;
2009-01-20 19:59:43 -06:00
recvPacket >> guid ; // Pet guid
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Pet * pet = _player -> GetPet ();
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
if ( ! pet || pet -> getPetType () != HUNTER_PET || pet -> m_usedTalentCount == 0 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( guid != pet -> GetGUID ())
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s ." , uint32 ( GUID_LOPART ( guid )), GetPlayer () -> GetName () );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CharmInfo * charmInfo = pet -> GetCharmInfo ();
if ( ! charmInfo )
{
2009-05-31 16:15:12 -05:00
sLog . outError ( "WorldSession::HandlePetUnlearnOpcode: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!" , pet -> GetGUIDLow (), pet -> GetTypeId ());
2008-10-11 14:16:25 -05:00
return ;
}
2009-01-20 19:59:43 -06:00
pet -> resetTalents ();
2009-06-11 00:45:59 -05:00
_player -> SendTalentsInfoData ( true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandlePetSpellAutocastOpcode ( WorldPacket & recvPacket )
{
sLog . outDetail ( "CMSG_PET_SPELL_AUTOCAST" );
uint64 guid ;
2009-07-01 18:07:20 -05:00
uint32 spellid ;
2008-10-11 14:16:25 -05:00
uint8 state ; //1 for on, 0 for off
2009-07-01 18:07:20 -05:00
recvPacket >> guid >> spellid >> state ;
2009-10-17 15:51:44 -07:00
2009-03-27 22:47:28 -06:00
if ( ! _player -> GetGuardianPet () && ! _player -> GetCharm ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ObjectAccessor :: FindPlayer ( guid ))
return ;
2009-10-17 15:51:44 -07:00
2009-01-24 11:28:00 -06:00
Creature * pet = ObjectAccessor :: GetCreatureOrPetOrVehicle ( * _player , guid );
2009-10-17 15:51:44 -07:00
2009-03-27 22:47:28 -06:00
if ( ! pet || ( pet != _player -> GetGuardianPet () && pet != _player -> GetCharm ()))
2008-10-11 14:16:25 -05:00
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s ." , uint32 ( GUID_LOPART ( guid )), GetPlayer () -> GetName () );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// do not add not learned spells/ passive spells
2009-03-21 18:05:43 -06:00
if ( ! pet -> HasSpell ( spellid ) || IsAutocastableSpell ( spellid ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CharmInfo * charmInfo = pet -> GetCharmInfo ();
if ( ! charmInfo )
{
2009-05-31 16:15:12 -05:00
sLog . outError ( "WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!" , pet -> GetGUIDLow (), pet -> GetTypeId ());
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-03-28 11:56:45 -06:00
if ( pet -> isPet ())
2008-10-11 14:16:25 -05:00
(( Pet * ) pet ) -> ToggleAutocast ( spellid , state );
2009-03-28 11:56:45 -06:00
else
pet -> GetCharmInfo () -> ToggleCreatureAutocast ( spellid , state );
2009-10-17 15:51:44 -07:00
2009-05-27 17:02:39 -05:00
charmInfo -> SetSpellAutocast ( spellid , state );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-11-03 09:53:31 -06:00
void WorldSession :: HandlePetCastSpellOpcode ( WorldPacket & recvPacket )
2008-10-11 14:16:25 -05:00
{
sLog . outDetail ( "WORLD: CMSG_PET_CAST_SPELL" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint64 guid ;
uint32 spellid ;
2008-12-24 09:58:26 -06:00
uint8 cast_count ;
uint8 unk_flags ; // flags (if 0x02 - some additional data are received)
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
recvPacket >> guid >> cast_count >> spellid >> unk_flags ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
sLog . outDebug ( "WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u" , cast_count , spellid , unk_flags );
2009-10-17 15:51:44 -07:00
2008-11-05 20:51:05 -06:00
// This opcode is also sent from charmed and possessed units (players and creatures)
2009-03-27 22:47:28 -06:00
if ( ! _player -> GetGuardianPet () && ! _player -> GetCharm ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-11-05 20:51:05 -06:00
Unit * caster = ObjectAccessor :: GetUnit ( * _player , guid );
2009-10-17 15:51:44 -07:00
2009-03-27 22:47:28 -06:00
if ( ! caster || ( caster != _player -> GetGuardianPet () && caster != _player -> GetCharm ()))
2008-10-11 14:16:25 -05:00
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "HandlePetCastSpellOpcode: Pet %u isn't pet of player %s ." , uint32 ( GUID_LOPART ( guid )), GetPlayer () -> GetName () );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( spellid );
if ( ! spellInfo )
{
2009-03-09 17:56:51 -06:00
sLog . outError ( "WORLD: unknown PET spell id %i" , spellid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-06-29 20:50:38 +02:00
if ( spellInfo -> StartRecoveryCategory > 0 ) //Check if spell is affected by GCD
if ( caster -> GetTypeId () == TYPEID_UNIT && (( Creature * ) caster ) -> GetGlobalCooldown () > 0 )
{
caster -> SendPetCastFail ( spellid , SPELL_FAILED_NOT_READY );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// do not cast not learned spells
2008-11-05 20:51:05 -06:00
if ( ! caster -> HasSpell ( spellid ) || IsPassiveSpell ( spellid ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SpellCastTargets targets ;
2008-11-05 20:51:05 -06:00
if ( ! targets . read ( & recvPacket , caster ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-11-05 20:51:05 -06:00
caster -> clearUnitState ( UNIT_STAT_FOLLOW );
2009-10-17 15:51:44 -07:00
2009-06-03 23:23:58 -05:00
Spell * spell = new Spell ( caster , spellInfo , spellid == 33395 ); // water elemental can cast freeze as triggered
spell -> m_cast_count = spellid == 33395 ? 0 : cast_count ; // probably pending spell cast
2008-10-11 14:16:25 -05:00
spell -> m_targets = targets ;
2009-10-17 15:51:44 -07:00
2009-09-01 01:11:28 -05:00
// TODO: need to check victim?
SpellCastResult result ;
if ( caster -> m_movedPlayer )
result = spell -> CheckPetCast ( caster -> m_movedPlayer -> GetSelectedUnit ());
else
result = spell -> CheckPetCast ( NULL );
2009-03-16 12:00:14 -06:00
if ( result == SPELL_CAST_OK )
2008-10-11 14:16:25 -05:00
{
2008-11-05 20:51:05 -06:00
if ( caster -> GetTypeId () == TYPEID_UNIT )
2008-10-11 14:16:25 -05:00
{
2008-11-05 20:51:05 -06:00
Creature * pet = ( Creature * ) caster ;
pet -> AddCreatureSpellCooldown ( spellid );
if ( pet -> isPet ())
{
Pet * p = ( Pet * ) pet ;
// 10% chance to play special pet attack talk, else growl
// actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
if ( p -> getPetType () == SUMMON_PET && ( urand ( 0 , 100 ) < 10 ))
pet -> SendPetTalk (( uint32 ) PET_TALK_SPECIAL_SPELL );
else
pet -> SendPetAIReaction ( guid );
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
spell -> prepare ( & ( spell -> m_targets ));
}
else
{
2008-11-05 20:51:05 -06:00
caster -> SendPetCastFail ( spellid , result );
if ( caster -> GetTypeId () == TYPEID_PLAYER )
{
if ( ! (( Player * ) caster ) -> HasSpellCooldown ( spellid ))
2009-06-23 14:05:37 +02:00
GetPlayer () -> SendClearCooldown ( spellid , caster );
2008-11-05 20:51:05 -06:00
}
else
{
if ( ! (( Creature * ) caster ) -> HasSpellCooldown ( spellid ))
2009-06-23 14:05:37 +02:00
GetPlayer () -> SendClearCooldown ( spellid , caster );
2008-11-05 20:51:05 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
spell -> finish ( false );
delete spell ;
}
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
void WorldSession :: SendPetNameInvalid ( uint32 error , const std :: string & name , DeclinedName * declinedName )
2008-11-03 09:53:31 -06:00
{
WorldPacket data ( SMSG_PET_NAME_INVALID , 4 + name . size () + 1 + 1 );
data << uint32 ( error );
data << name ;
if ( declinedName )
{
data << uint8 ( 1 );
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < MAX_DECLINED_NAME_CASES ; ++ i )
2008-11-03 09:53:31 -06:00
data << declinedName -> name [ i ];
}
else
data << uint8 ( 0 );
SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
void WorldSession :: HandlePetLearnTalent ( WorldPacket & recv_data )
{
sLog . outDebug ( "WORLD: CMSG_PET_LEARN_TALENT" );
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
uint64 guid ;
uint32 talent_id , requested_rank ;
recv_data >> guid >> talent_id >> requested_rank ;
2009-10-17 15:51:44 -07:00
2009-03-21 14:53:38 -06:00
_player -> LearnPetTalent ( guid , talent_id , requested_rank );
2009-06-11 00:45:59 -05:00
_player -> SendTalentsInfoData ( true );
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
void WorldSession :: HandleLearnPreviewTalentsPet ( WorldPacket & recv_data )
{
sLog . outDebug ( "CMSG_LEARN_PREVIEW_TALENTS_PET" );
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
uint64 guid ;
recv_data >> guid ;
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
uint32 talentsCount ;
recv_data >> talentsCount ;
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
uint32 talentId , talentRank ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < talentsCount ; ++ i )
2009-06-11 00:45:59 -05:00
{
recv_data >> talentId >> talentRank ;
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
_player -> LearnPetTalent ( guid , talentId , talentRank );
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
_player -> SendTalentsInfoData ( true );
2009-02-18 22:39:00 +01:00
}