2008-10-02 16:23:55 -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-02 16:23:55 -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-28 11:38:28 -06:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-02 16:23:55 -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-28 11:38:28 -06:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-02 16:23:55 -05:00
*/
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "Corpse.h"
#include "Player.h"
2009-03-09 17:06:13 -06:00
#include "Vehicle.h"
2008-10-02 16:23:55 -05:00
#include "MapManager.h"
#include "Transports.h"
#include "BattleGround.h"
#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
2009-02-09 22:08:06 -06:00
#include "ObjectMgr.h"
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleMoveWorldportAckOpcode ( WorldPacket & /*recv_data*/ )
{
sLog . outDebug ( "WORLD: got MSG_MOVE_WORLDPORT_ACK." );
HandleMoveWorldportAckOpcode ();
}
void WorldSession :: HandleMoveWorldportAckOpcode ()
{
// get the teleport destination
WorldLocation & loc = GetPlayer () -> GetTeleportDest ();
// possible errors in the coordinate validity check
if ( ! MapManager :: IsValidMapCoord ( loc . mapid , loc . x , loc . y , loc . z , loc . o ))
{
LogoutPlayer ( false );
return ;
}
// get the destination map entry, not the current one, this will fix homebind and reset greeting
MapEntry const * mEntry = sMapStore . LookupEntry ( loc . mapid );
InstanceTemplate const * mInstance = objmgr . GetInstanceTemplate ( loc . mapid );
// reset instance validity, except if going to an instance inside an instance
if ( GetPlayer () -> m_InstanceValid == false && ! mInstance )
GetPlayer () -> m_InstanceValid = true ;
GetPlayer () -> SetSemaphoreTeleport ( false );
// relocate the player to the teleport destination
GetPlayer () -> SetMapId ( loc . mapid );
GetPlayer () -> Relocate ( loc . x , loc . y , loc . z , loc . o );
// since the MapId is set before the GetInstance call, the InstanceId must be set to 0
// to let GetInstance() determine the proper InstanceId based on the player's binds
GetPlayer () -> SetInstanceId ( 0 );
// check this before Map::Add(player), because that will create the instance save!
bool reset_notify = ( GetPlayer () -> GetBoundInstance ( GetPlayer () -> GetMapId (), GetPlayer () -> GetDifficulty ()) == NULL );
GetPlayer () -> SendInitialPacketsBeforeAddToMap ();
// the CanEnter checks are done in TeleporTo but conditions may change
// while the player is in transit, for example the map may get full
2008-11-28 11:38:28 -06:00
if ( ! GetPlayer () -> GetMap () -> Add ( GetPlayer ()))
2008-10-02 16:23:55 -05:00
{
sLog . outDebug ( "WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed" , GetPlayer () -> GetName (), GetPlayer () -> GetGUIDLow (), loc . mapid , loc . x , loc . y , loc . z , loc . o );
// teleport the player home
GetPlayer () -> SetDontMove ( false );
if ( ! GetPlayer () -> TeleportTo ( GetPlayer () -> m_homebindMapId , GetPlayer () -> m_homebindX , GetPlayer () -> m_homebindY , GetPlayer () -> m_homebindZ , GetPlayer () -> GetOrientation ()))
{
// the player must always be able to teleport home
sLog . outError ( "WORLD: failed to teleport player %s (%d) to homebind location %d,%f,%f,%f,%f!" , GetPlayer () -> GetName (), GetPlayer () -> GetGUIDLow (), GetPlayer () -> m_homebindMapId , GetPlayer () -> m_homebindX , GetPlayer () -> m_homebindY , GetPlayer () -> m_homebindZ , GetPlayer () -> GetOrientation ());
assert ( false );
}
return ;
}
2009-02-13 19:56:55 -06:00
// battleground state prepare (in case join to BG), at relogin/tele player not invited
// only add to bg group and object, if the player was invited (else he entered through command)
if ( _player -> InBattleGround ())
{
// cleanup seting if outdated
if ( ! mEntry -> IsBattleGroundOrArena ())
{
2009-02-27 12:57:33 -06:00
_player -> SetBattleGroundId ( 0 , BATTLEGROUND_TYPE_NONE ); // We're not in BG.
2009-02-13 19:56:55 -06:00
// reset destination bg team
_player -> SetBGTeam ( 0 );
}
// join to bg case
else if ( BattleGround * bg = _player -> GetBattleGround ())
{
if ( _player -> IsInvitedForBattleGroundInstance ( _player -> GetBattleGroundId ()))
bg -> AddPlayer ( _player );
}
}
2008-10-02 16:23:55 -05:00
GetPlayer () -> SendInitialPacketsAfterAddToMap ();
// flight fast teleport case
if ( GetPlayer () -> GetMotionMaster () -> GetCurrentMovementGeneratorType () == FLIGHT_MOTION_TYPE )
{
if ( ! _player -> InBattleGround ())
{
// short preparations to continue flight
GetPlayer () -> SetDontMove ( false );
FlightPathMovementGenerator * flight = ( FlightPathMovementGenerator * )( GetPlayer () -> GetMotionMaster () -> top ());
flight -> Initialize ( * GetPlayer ());
return ;
}
// battleground state prepare, stop flight
GetPlayer () -> GetMotionMaster () -> MovementExpired ();
GetPlayer () -> m_taxi . ClearTaxiDestinations ();
}
// resurrect character at enter into instance where his corpse exist after add to map
Corpse * corpse = GetPlayer () -> GetCorpse ();
if ( corpse && corpse -> GetType () != CORPSE_BONES && corpse -> GetMapId () == GetPlayer () -> GetMapId ())
{
if ( mEntry -> IsDungeon () )
{
GetPlayer () -> ResurrectPlayer ( 0.5f , false );
GetPlayer () -> SpawnCorpseBones ();
GetPlayer () -> SaveToDB ();
}
}
if ( mEntry -> IsRaid () && mInstance )
{
if ( reset_notify )
{
uint32 timeleft = sInstanceSaveManager . GetResetTimeFor ( GetPlayer () -> GetMapId ()) - time ( NULL );
GetPlayer () -> SendInstanceResetWarning ( GetPlayer () -> GetMapId (), timeleft ); // greeting at the entrance of the resort raid instance
}
}
// mount allow check
if ( ! mEntry -> IsMountAllowed ())
_player -> RemoveSpellsCausingAura ( SPELL_AURA_MOUNTED );
// honorless target
if ( GetPlayer () -> pvpInfo . inHostileArea )
GetPlayer () -> CastSpell ( GetPlayer (), 2479 , true );
// resummon pet
if ( GetPlayer () -> m_temporaryUnsummonedPetNumber )
{
Pet * NewPet = new Pet ;
if ( ! NewPet -> LoadPetFromDB ( GetPlayer (), 0 , GetPlayer () -> m_temporaryUnsummonedPetNumber , true ))
delete NewPet ;
GetPlayer () -> m_temporaryUnsummonedPetNumber = 0 ;
}
GetPlayer () -> SetDontMove ( false );
}
void WorldSession :: HandleMovementOpcodes ( WorldPacket & recv_data )
{
2008-12-24 09:58:26 -06:00
uint32 opcode = recv_data . GetOpcode ();
2009-03-23 15:26:13 -06:00
//sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
2008-10-02 16:23:55 -05:00
2009-01-16 19:47:25 -06:00
if ( GetPlayer () -> GetDontMove ())
return ;
2008-10-02 16:23:55 -05:00
/* extract packet */
MovementInfo movementInfo ;
2008-12-24 09:58:26 -06:00
ReadMovementInfo ( recv_data , & movementInfo );
2008-10-02 16:23:55 -05:00
/*----------------*/
if ( recv_data . size () != recv_data . rpos ())
{
sLog . outError ( "MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is %u bytes larger than it should be. Kicked as cheater." , _player -> GetName (), _player -> GetGUIDLow (), _player -> GetSession () -> GetAccountId (), recv_data . GetOpcode (), recv_data . size () - recv_data . rpos ());
KickPlayer ();
return ;
}
2008-10-14 11:57:03 -05:00
if ( ! Trinity :: IsValidMapCoord ( movementInfo . x , movementInfo . y , movementInfo . z , movementInfo . o ))
2008-10-02 16:23:55 -05:00
return ;
2009-03-24 17:42:22 -06:00
Unit * mover = _player -> m_mover ;
Player * plMover = mover -> GetTypeId () == TYPEID_PLAYER ? ( Player * ) mover : NULL ;
2008-10-02 16:23:55 -05:00
/* handle special cases */
2008-12-24 09:58:26 -06:00
if ( movementInfo . flags & MOVEMENTFLAG_ONTRANSPORT )
2008-10-02 16:23:55 -05:00
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if ( movementInfo . t_x > 50 || movementInfo . t_y > 50 || movementInfo . t_z > 50 )
return ;
2008-10-14 11:57:03 -05:00
if ( ! Trinity :: IsValidMapCoord ( movementInfo . x + movementInfo . t_x , movementInfo . y + movementInfo . t_y ,
2008-10-02 16:23:55 -05:00
movementInfo . z + movementInfo . t_z , movementInfo . o + movementInfo . t_o ) )
return ;
// if we boarded a transport, add us to it
2009-03-24 17:43:58 -06:00
if ( plMover && ! plMover -> m_transport )
2008-10-02 16:23:55 -05:00
{
// elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
for ( MapManager :: TransportSet :: iterator iter = MapManager :: Instance (). m_Transports . begin (); iter != MapManager :: Instance (). m_Transports . end (); ++ iter )
{
if (( * iter ) -> GetGUID () == movementInfo . t_guid )
{
2009-03-24 17:42:22 -06:00
plMover -> m_transport = ( * iter );
( * iter ) -> AddPassenger ( plMover );
2008-10-02 16:23:55 -05:00
break ;
}
}
}
}
2009-03-24 17:42:22 -06:00
else if ( plMover && plMover -> m_transport ) // if we were on a transport, leave
2008-10-02 16:23:55 -05:00
{
2009-03-24 17:42:22 -06:00
plMover -> m_transport -> RemovePassenger ( plMover );
plMover -> m_transport = NULL ;
2008-10-02 16:23:55 -05:00
movementInfo . t_x = 0.0f ;
movementInfo . t_y = 0.0f ;
movementInfo . t_z = 0.0f ;
movementInfo . t_o = 0.0f ;
movementInfo . t_time = 0 ;
2008-12-24 09:58:26 -06:00
movementInfo . t_seat = - 1 ;
2008-10-02 16:23:55 -05:00
}
2008-12-12 11:21:28 -06:00
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
2009-03-24 17:42:22 -06:00
if ( opcode == MSG_MOVE_FALL_LAND && plMover && ! plMover -> isInFlight ())
plMover -> HandleFall ( movementInfo );
2008-10-02 16:23:55 -05:00
2009-03-24 17:42:22 -06:00
if ( plMover && (( movementInfo . flags & MOVEMENTFLAG_SWIMMING ) != 0 ) != plMover -> IsInWater ())
2008-10-02 16:23:55 -05:00
{
// now client not include swimming flag in case jumping under water
2009-03-24 17:42:22 -06:00
plMover -> SetInWater ( ! plMover -> IsInWater () || plMover -> GetBaseMap () -> IsUnderWater ( movementInfo . x , movementInfo . y , movementInfo . z ) );
2008-10-02 16:23:55 -05:00
}
/*----------------------*/
/* process position-change */
2008-12-24 09:58:26 -06:00
recv_data . put < uint32 > ( 6 , getMSTime ()); // fix time, offset flags(4) + unk(2)
WorldPacket data ( recv_data . GetOpcode (), ( mover -> GetPackGUID (). size () + recv_data . size ()));
2009-03-24 09:44:08 -06:00
data . append ( mover -> GetPackGUID ()); // use mover guid
2008-10-02 16:23:55 -05:00
data . append ( recv_data . contents (), recv_data . size ());
GetPlayer () -> SendMessageToSet ( & data , false );
2009-03-24 17:42:22 -06:00
if ( plMover ) // nothing is charmed, or player charmed
2008-12-24 09:58:26 -06:00
{
2009-03-24 17:42:22 -06:00
plMover -> SetPosition ( movementInfo . x , movementInfo . y , movementInfo . z , movementInfo . o );
plMover -> m_movementInfo = movementInfo ;
plMover -> SetUnitMovementFlags ( movementInfo . flags );
plMover -> UpdateFallInformationIfNeed ( movementInfo , recv_data . GetOpcode ());
2008-12-24 09:58:26 -06:00
2009-03-24 17:42:22 -06:00
if ( plMover -> isMovingOrTurning ())
plMover -> RemoveSpellsCausingAura ( SPELL_AURA_FEIGN_DEATH );
2008-10-02 16:23:55 -05:00
2009-03-24 17:42:22 -06:00
if ( movementInfo . z < - 500.0f )
{
if ( plMover -> InBattleGround ()
&& plMover -> GetBattleGround ()
&& plMover -> GetBattleGround () -> HandlePlayerUnderMap ( _player ))
{
// do nothing, the handle already did if returned true
}
else
{
// NOTE: this is actually called many times while falling
// even after the player has been teleported away
// TODO: discard movement packets after the player is rooted
if ( plMover -> isAlive ())
{
plMover -> EnvironmentalDamage ( DAMAGE_FALL_TO_VOID , GetPlayer () -> GetMaxHealth ());
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
plMover -> KillPlayer ();
plMover -> BuildPlayerRepop ();
}
2008-10-02 16:23:55 -05:00
2009-03-24 17:42:22 -06:00
// cancel the death timer here if started
plMover -> RepopAtGraveyard ();
}
}
}
else // creature charmed
{
if ( Map * map = mover -> GetMap ())
map -> CreatureRelocation (( Creature * ) mover , movementInfo . x , movementInfo . y , movementInfo . z , movementInfo . o );
mover -> SetUnitMovementFlags ( movementInfo . flags );
}
2008-11-05 20:51:05 -06:00
}
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleForceSpeedChangeAck ( WorldPacket & recv_data )
{
2009-03-23 15:26:13 -06:00
//sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode());
2008-12-24 09:58:26 -06:00
CHECK_PACKET_SIZE ( recv_data , recv_data . rpos () + 8 + 4 );
2008-10-02 16:23:55 -05:00
/* extract packet */
uint64 guid ;
2008-12-24 09:58:26 -06:00
uint32 unk1 ;
2008-10-02 16:23:55 -05:00
float newspeed ;
recv_data >> guid ;
// now can skip not our packet
if ( _player -> GetGUID () != guid )
return ;
// continue parse packet
2008-12-24 09:58:26 -06:00
recv_data >> unk1 ; // counter or moveEvent
2008-10-02 16:23:55 -05:00
2008-12-24 09:58:26 -06:00
MovementInfo movementInfo ;
ReadMovementInfo ( recv_data , & movementInfo );
2008-10-02 16:23:55 -05:00
// recheck
CHECK_PACKET_SIZE ( recv_data , recv_data . rpos () + 4 );
recv_data >> newspeed ;
/*----------------*/
// client ACK send one packet for mounted/run case and need skip all except last from its
// in other cases anti-cheat check can be fail in false case
UnitMoveType move_type ;
UnitMoveType force_move_type ;
2008-12-24 09:58:26 -06:00
static char const * move_type_name [ MAX_MOVE_TYPE ] = { "Walk" , "Run" , "RunBack" , "Swim" , "SwimBack" , "TurnRate" , "Flight" , "FlightBack" , "PitchRate" };
2008-10-02 16:23:55 -05:00
uint16 opcode = recv_data . GetOpcode ();
switch ( opcode )
{
2008-12-12 11:21:28 -06:00
case CMSG_FORCE_WALK_SPEED_CHANGE_ACK : move_type = MOVE_WALK ; force_move_type = MOVE_WALK ; break ;
case CMSG_FORCE_RUN_SPEED_CHANGE_ACK : move_type = MOVE_RUN ; force_move_type = MOVE_RUN ; break ;
case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK : move_type = MOVE_RUN_BACK ; force_move_type = MOVE_RUN_BACK ; break ;
case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK : move_type = MOVE_SWIM ; force_move_type = MOVE_SWIM ; break ;
case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK : move_type = MOVE_SWIM_BACK ; force_move_type = MOVE_SWIM_BACK ; break ;
case CMSG_FORCE_TURN_RATE_CHANGE_ACK : move_type = MOVE_TURN_RATE ; force_move_type = MOVE_TURN_RATE ; break ;
case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK : move_type = MOVE_FLIGHT ; force_move_type = MOVE_FLIGHT ; break ;
case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK : move_type = MOVE_FLIGHT_BACK ; force_move_type = MOVE_FLIGHT_BACK ; break ;
2008-12-24 09:58:26 -06:00
case CMSG_FORCE_PITCH_RATE_CHANGE_ACK : move_type = MOVE_PITCH_RATE ; force_move_type = MOVE_PITCH_RATE ; break ;
2008-10-02 16:23:55 -05:00
default :
sLog . outError ( "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u" , opcode );
return ;
}
// skip all forced speed changes except last and unexpected
// in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both.
if ( _player -> m_forced_speed_changes [ force_move_type ] > 0 )
{
-- _player -> m_forced_speed_changes [ force_move_type ];
if ( _player -> m_forced_speed_changes [ force_move_type ] > 0 )
return ;
}
if ( ! _player -> GetTransport () && fabs ( _player -> GetSpeed ( move_type ) - newspeed ) > 0.01f )
{
if ( _player -> GetSpeed ( move_type ) > newspeed ) // must be greater - just correct
{
sLog . outError ( "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value" ,
move_type_name [ move_type ], _player -> GetName (), _player -> GetSpeed ( move_type ), newspeed );
_player -> SetSpeed ( move_type , _player -> GetSpeedRate ( move_type ), true );
}
else // must be lesser - cheating
{
sLog . outBasic ( "Player %s from account id %u kicked for incorrect speed (must be %f instead %f)" ,
_player -> GetName (), _player -> GetSession () -> GetAccountId (), _player -> GetSpeed ( move_type ), newspeed );
_player -> GetSession () -> KickPlayer ();
}
}
}
void WorldSession :: HandleSetActiveMoverOpcode ( WorldPacket & recv_data )
{
sLog . outDebug ( "WORLD: Recvd CMSG_SET_ACTIVE_MOVER" );
2008-12-24 09:58:26 -06:00
recv_data . hexlike ();
2008-10-02 16:23:55 -05:00
2008-12-24 09:58:26 -06:00
CHECK_PACKET_SIZE ( recv_data , 8 );
2008-10-02 16:23:55 -05:00
uint64 guid ;
recv_data >> guid ;
2008-12-24 09:58:26 -06:00
if ( _player -> m_mover -> GetGUID () != guid )
{
sLog . outError ( "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT , _player -> m_mover -> GetGUID (), guid );
return ;
}
2008-10-02 16:23:55 -05:00
}
2008-12-24 09:58:26 -06:00
void WorldSession :: HandleMoveNotActiveMover ( WorldPacket & recv_data )
2008-11-07 16:49:42 -06:00
{
sLog . outDebug ( "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER" );
2008-12-24 09:58:26 -06:00
recv_data . hexlike ();
CHECK_PACKET_SIZE ( recv_data , recv_data . rpos () + 8 );
uint64 old_mover_guid ;
recv_data >> old_mover_guid ;
if ( _player -> m_mover -> GetGUID () == old_mover_guid )
{
sLog . outError ( "HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT , _player -> m_mover -> GetGUID (), _player -> GetGUID (), old_mover_guid );
return ;
}
MovementInfo mi ;
ReadMovementInfo ( recv_data , & mi );
_player -> m_movementInfo = mi ;
}
void WorldSession :: HandleDismissControlledVehicle ( WorldPacket & recv_data )
{
sLog . outDebug ( "WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE" );
recv_data . hexlike ();
uint64 vehicleGUID = _player -> GetCharmGUID ();
if ( ! vehicleGUID ) // something wrong here...
return ;
MovementInfo mi ;
ReadMovementInfo ( recv_data , & mi );
_player -> m_movementInfo = mi ;
// using charm guid, because we don't have vehicle guid...
if ( Vehicle * vehicle = ObjectAccessor :: GetVehicle ( vehicleGUID ))
{
_player -> ExitVehicle ( vehicle );
vehicle -> Dismiss ();
}
2008-11-07 16:49:42 -06:00
}
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleMountSpecialAnimOpcode ( WorldPacket & /*recvdata*/ )
{
//sLog.outDebug("WORLD: Recvd CMSG_MOUNTSPECIAL_ANIM");
WorldPacket data ( SMSG_MOUNTSPECIAL_ANIM , 8 );
data << uint64 ( GetPlayer () -> GetGUID ());
GetPlayer () -> SendMessageToSet ( & data , false );
}
void WorldSession :: HandleMoveKnockBackAck ( WorldPacket & /*recv_data*/ )
{
// CHECK_PACKET_SIZE(recv_data,?);
sLog . outDebug ( "CMSG_MOVE_KNOCK_BACK_ACK" );
// Currently not used but maybe use later for recheck final player position
// (must be at call same as into "recv_data >> x >> y >> z >> orientation;"
/*
uint32 flags, time;
float x, y, z, orientation;
uint64 guid;
uint32 sequence;
uint32 ukn1;
float xdirection,ydirection,hspeed,vspeed;
recv_data >> guid;
recv_data >> sequence;
recv_data >> flags >> time;
recv_data >> x >> y >> z >> orientation;
recv_data >> ukn1; //unknown
recv_data >> vspeed >> xdirection >> ydirection >> hspeed;
// skip not personal message;
if(GetPlayer()->GetGUID()!=guid)
return;
// check code
*/
}
void WorldSession :: HandleMoveHoverAck ( WorldPacket & /*recv_data*/ )
{
sLog . outDebug ( "CMSG_MOVE_HOVER_ACK" );
}
void WorldSession :: HandleMoveWaterWalkAck ( WorldPacket & /*recv_data*/ )
{
sLog . outDebug ( "CMSG_MOVE_WATER_WALK_ACK" );
}
void WorldSession :: HandleSummonResponseOpcode ( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE ( recv_data , 8 + 1 );
if ( ! _player -> isAlive () || _player -> isInCombat () )
return ;
uint64 summoner_guid ;
bool agree ;
recv_data >> summoner_guid ;
recv_data >> agree ;
_player -> SummonIfPossible ( agree );
}
2009-02-17 20:07:49 -06:00