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
*
2010-01-16 20:19:18 +03:00
* Copyright (C) 2008-2010 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
*/
2009-10-17 15:51:44 -07:00
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"
2009-05-05 16:56:15 -05:00
#include "SpellAuras.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"
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleMoveWorldportAckOpcode ( WorldPacket & /*recv_data*/ )
{
sLog . outDebug ( "WORLD: got MSG_MOVE_WORLDPORT_ACK." );
HandleMoveWorldportAckOpcode ();
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleMoveWorldportAckOpcode ()
{
2009-04-11 23:07:07 -05:00
// ignore unexpected far teleports
2010-04-07 19:14:10 +02:00
if ( ! GetPlayer () -> IsBeingTeleportedFar ())
2009-04-11 23:07:07 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// get the teleport destination
WorldLocation & loc = GetPlayer () -> GetTeleportDest ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// possible errors in the coordinate validity check
2010-04-07 19:14:10 +02:00
if ( ! MapManager :: IsValidMapCoord ( loc ))
2008-10-02 16:23:55 -05:00
{
LogoutPlayer ( false );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// get the destination map entry, not the current one, this will fix homebind and reset greeting
2009-08-29 14:58:45 -05:00
MapEntry const * mEntry = sMapStore . LookupEntry ( loc . GetMapId ());
InstanceTemplate const * mInstance = objmgr . GetInstanceTemplate ( loc . GetMapId ());
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// reset instance validity, except if going to an instance inside an instance
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> m_InstanceValid == false && ! mInstance )
2008-10-02 16:23:55 -05:00
GetPlayer () -> m_InstanceValid = true ;
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
GetPlayer () -> SetSemaphoreTeleportFar ( false );
2009-10-17 15:51:44 -07:00
2009-08-03 19:48:28 +02:00
Map * oldMap = GetPlayer () -> GetMap ();
2009-08-13 10:01:00 -05:00
assert ( oldMap );
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> IsInWorld ())
2009-08-13 10:01:00 -05:00
{
2009-08-29 14:58:45 -05:00
sLog . outCrash ( "Player is still in world when teleported out of map %u! to new map %u" , oldMap -> GetId (), loc . GetMapId ());
2009-08-13 10:01:00 -05:00
oldMap -> Remove ( GetPlayer (), false );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// relocate the player to the teleport destination
2009-08-29 14:58:45 -05:00
Map * newMap = MapManager :: Instance (). CreateMap ( loc . GetMapId (), GetPlayer (), 0 );
2009-08-01 00:20:32 +02:00
// the CanEnter checks are done in TeleporTo but conditions may change
// while the player is in transit, for example the map may get full
2009-08-01 20:23:23 +02:00
if ( ! newMap || ! newMap -> CanEnter ( GetPlayer ()))
2009-07-18 15:00:36 +02:00
{
2009-08-29 14:58:45 -05:00
sLog . outError ( "Map %d could not be created for player %d, porting player to homebind" , loc . GetMapId (), GetPlayer () -> GetGUIDLow ());
2009-08-03 12:52:31 +02:00
GetPlayer () -> TeleportTo ( GetPlayer () -> m_homebindMapId , GetPlayer () -> m_homebindX , GetPlayer () -> m_homebindY , GetPlayer () -> m_homebindZ , GetPlayer () -> GetOrientation ());
return ;
2009-07-18 15:00:36 +02:00
}
2009-07-19 14:02:52 +02:00
else
2009-08-29 14:58:45 -05:00
GetPlayer () -> Relocate ( & loc );
2009-10-17 15:51:44 -07:00
2009-08-03 12:52:31 +02:00
GetPlayer () -> ResetMap ();
2009-07-18 15:00:36 +02:00
GetPlayer () -> SetMap ( newMap );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
GetPlayer () -> SendInitialPacketsBeforeAddToMap ();
2010-04-07 19:14:10 +02:00
if ( ! GetPlayer () -> GetMap () -> Add ( GetPlayer ()))
2008-10-02 16:23:55 -05:00
{
2009-08-29 14:58:45 -05:00
sLog . outError ( "WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!" , GetPlayer () -> GetName (), GetPlayer () -> GetGUIDLow (), loc . GetMapId ());
2009-08-03 19:48:28 +02:00
GetPlayer () -> ResetMap ();
GetPlayer () -> SetMap ( oldMap );
2009-08-03 12:52:31 +02:00
GetPlayer () -> TeleportTo ( GetPlayer () -> m_homebindMapId , GetPlayer () -> m_homebindX , GetPlayer () -> m_homebindY , GetPlayer () -> m_homebindZ , GetPlayer () -> GetOrientation ());
return ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
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)
2010-04-07 19:14:10 +02:00
if ( _player -> InBattleGround ())
2009-02-13 19:56:55 -06:00
{
2009-06-14 10:19:44 -05:00
// cleanup setting if outdated
2010-04-07 19:14:10 +02:00
if ( ! mEntry -> IsBattleGroundOrArena ())
2009-02-13 19:56:55 -06:00
{
2009-06-14 10:19:44 -05:00
// We're not in BG
_player -> SetBattleGroundId ( 0 , BATTLEGROUND_TYPE_NONE );
2009-02-13 19:56:55 -06:00
// reset destination bg team
_player -> SetBGTeam ( 0 );
}
// join to bg case
2010-04-07 19:14:10 +02:00
else if ( BattleGround * bg = _player -> GetBattleGround ())
2009-02-13 19:56:55 -06:00
{
2010-04-07 19:14:10 +02:00
if ( _player -> IsInvitedForBattleGroundInstance ( _player -> GetBattleGroundId ()))
2009-02-13 19:56:55 -06:00
bg -> AddPlayer ( _player );
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
GetPlayer () -> SendInitialPacketsAfterAddToMap ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// flight fast teleport case
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> GetMotionMaster () -> GetCurrentMovementGeneratorType () == FLIGHT_MOTION_TYPE )
2008-10-02 16:23:55 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! _player -> InBattleGround ())
2008-10-02 16:23:55 -05:00
{
// short preparations to continue flight
FlightPathMovementGenerator * flight = ( FlightPathMovementGenerator * )( GetPlayer () -> GetMotionMaster () -> top ());
flight -> Initialize ( * GetPlayer ());
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// battleground state prepare, stop flight
GetPlayer () -> GetMotionMaster () -> MovementExpired ();
2010-03-17 23:16:35 +01:00
GetPlayer () -> CleanupAfterTaxiFlight ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// 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 ())
{
2010-04-07 19:14:10 +02:00
if ( mEntry -> IsDungeon () )
2008-10-02 16:23:55 -05:00
{
GetPlayer () -> ResurrectPlayer ( 0.5f , false );
GetPlayer () -> SpawnCorpseBones ();
}
}
2009-10-17 15:51:44 -07:00
2010-03-21 19:12:04 +01:00
bool allowMount = ! mEntry -> IsDungeon () || mEntry -> IsBattleGroundOrArena ();
2010-01-16 19:54:57 +03:00
if ( mInstance )
2008-10-02 16:23:55 -05:00
{
2009-12-17 11:31:44 +01:00
Difficulty diff = GetPlayer () -> GetDifficulty ( mEntry -> IsRaid ());
2010-04-07 19:14:10 +02:00
if ( MapDifficulty const * mapDiff = GetMapDifficultyData ( mEntry -> MapID , diff ))
2009-12-17 11:31:44 +01:00
{
2010-01-16 19:54:57 +03:00
if ( mapDiff -> resetTime )
{
if ( uint32 timeReset = sInstanceSaveManager . GetResetTimeFor ( mEntry -> MapID , diff ))
{
uint32 timeleft = timeReset - time ( NULL );
GetPlayer () -> SendInstanceResetWarning ( mEntry -> MapID , diff , timeleft );
}
}
2009-12-17 11:31:44 +01:00
}
2010-03-21 17:34:25 +01:00
allowMount = mInstance -> allowMount ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// mount allow check
2010-03-21 17:34:25 +01:00
if ( ! allowMount )
2009-04-06 13:31:14 +02:00
_player -> RemoveAurasByType ( SPELL_AURA_MOUNTED );
2009-10-17 15:51:44 -07:00
2009-08-26 14:06:12 -05:00
// update zone immediately, otherwise leave channel will cause crash in mtmap
uint32 newzone , newarea ;
GetPlayer () -> GetZoneAndAreaId ( newzone , newarea );
GetPlayer () -> UpdateZone ( newzone , newarea );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// honorless target
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> pvpInfo . inHostileArea )
2010-02-15 18:23:39 +01:00
GetPlayer () -> CastSpell ( GetPlayer (), 2479 , true );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// resummon pet
2009-04-11 14:47:38 -05:00
GetPlayer () -> ResummonPetTemporaryUnSummonedIfAny ();
2009-10-17 15:51:44 -07:00
2009-07-01 18:36:03 -05:00
//lets process all delayed operations on successful teleport
GetPlayer () -> ProcessDelayedOperations ();
2009-04-11 23:07:07 -05:00
}
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
void WorldSession :: HandleMoveTeleportAck ( WorldPacket & recv_data )
{
sLog . outDebug ( "MSG_MOVE_TELEPORT_ACK" );
uint64 guid ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ))
2009-12-17 11:31:44 +01:00
return ;
uint32 flags , time ;
2009-04-11 23:07:07 -05:00
recv_data >> flags >> time ;
2009-06-14 10:19:44 -05:00
DEBUG_LOG ( "Guid " UI64FMTD , guid );
DEBUG_LOG ( "Flags %u, time %u" , flags , time / IN_MILISECONDS );
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
Unit * mover = _player -> m_mover ;
2009-06-14 10:19:44 -05:00
Player * plMover = mover -> GetTypeId () == TYPEID_PLAYER ? ( Player * ) mover : NULL ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! plMover || ! plMover -> IsBeingTeleportedNear ())
2009-04-11 23:07:07 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( guid != plMover -> GetGUID ())
2009-04-11 23:07:07 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
plMover -> SetSemaphoreTeleportNear ( false );
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
uint32 old_zone = plMover -> GetZoneId ();
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
WorldLocation const & dest = plMover -> GetTeleportDest ();
2009-10-17 15:51:44 -07:00
2010-01-18 21:56:15 +02:00
plMover -> SetPosition ( dest , true );
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
uint32 newzone , newarea ;
2009-06-14 10:19:44 -05:00
plMover -> GetZoneAndAreaId ( newzone , newarea );
plMover -> UpdateZone ( newzone , newarea );
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
// new zone
2010-04-07 19:14:10 +02:00
if ( old_zone != newzone )
2009-04-11 23:07:07 -05:00
{
// honorless target
2010-04-07 19:14:10 +02:00
if ( plMover -> pvpInfo . inHostileArea )
2010-02-15 18:23:39 +01:00
plMover -> CastSpell ( plMover , 2479 , true );
2009-04-11 23:07:07 -05:00
}
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
// resummon pet
GetPlayer () -> ResummonPetTemporaryUnSummonedIfAny ();
2009-10-17 15:51:44 -07:00
2009-07-01 18:36:03 -05:00
//lets process all delayed operations on successful teleport
GetPlayer () -> ProcessDelayedOperations ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleMovementOpcodes ( WorldPacket & recv_data )
{
2009-11-03 22:28:04 -08:00
uint16 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);
2009-12-17 11:31:44 +01:00
recv_data . hexlike ();
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
Unit * mover = _player -> m_mover ;
2009-11-03 22:28:04 -08:00
2009-11-04 17:10:43 -08:00
assert ( mover != NULL ); // there must always be a mover
2009-11-03 22:28:04 -08:00
2009-10-18 18:38:46 -07:00
Player * plMover = mover -> GetTypeId () == TYPEID_PLAYER ? ( Player * ) mover : NULL ;
2009-10-17 15:51:44 -07:00
2009-04-11 23:07:07 -05:00
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
2009-11-03 22:28:04 -08:00
if ( plMover && plMover -> IsBeingTeleported ())
2009-08-19 17:19:50 -05:00
{
recv_data . rpos ( recv_data . wpos ()); // prevent warnings spam
2009-01-16 19:47:25 -06:00
return ;
2009-08-19 17:19:50 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/* extract packet */
2009-12-17 11:31:44 +01:00
uint64 guid ;
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ))
2009-12-17 11:31:44 +01:00
return ;
2008-10-02 16:23:55 -05:00
MovementInfo movementInfo ;
2009-12-17 11:31:44 +01:00
movementInfo . guid = guid ;
2008-12-24 09:58:26 -06:00
ReadMovementInfo ( recv_data , & movementInfo );
2008-10-02 16:23:55 -05:00
/*----------------*/
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
/* if (recv_data.size() != recv_data.rpos())
2008-10-02 16:23:55 -05:00
{
2009-07-12 17:52:27 +08:00
sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " 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());
2009-12-17 11:31:44 +01:00
KickPlayer();*/
2009-08-19 17:19:50 -05:00
recv_data . rpos ( recv_data . wpos ()); // prevent warnings spam
2009-12-17 11:31:44 +01:00
/* return;
}*/
2009-10-17 15:51:44 -07:00
2009-11-03 22:28:04 -08:00
if ( ! Trinity :: IsValidMapCoord ( movementInfo . x , movementInfo . y , movementInfo . z , movementInfo . o ))
2009-08-24 19:33:34 -05:00
{
recv_data . rpos ( recv_data . wpos ()); // prevent warnings spam
2008-10-02 16:23:55 -05:00
return ;
2009-08-24 19:33:34 -05:00
}
2009-10-17 15:51:44 -07:00
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)
2009-11-03 22:28:04 -08:00
if ( movementInfo . t_x > 50 || movementInfo . t_y > 50 || movementInfo . t_z > 50 )
2009-08-24 19:33:34 -05:00
{
recv_data . rpos ( recv_data . wpos ()); // prevent warnings spam
2008-10-02 16:23:55 -05:00
return ;
2009-08-24 19:33:34 -05:00
}
2009-10-17 15:51:44 -07:00
2009-11-03 22:28:04 -08:00
if ( ! Trinity :: IsValidMapCoord ( movementInfo . x + movementInfo . t_x , movementInfo . y + movementInfo . t_y ,
movementInfo . z + movementInfo . t_z , movementInfo . o + movementInfo . t_o ))
2009-08-24 19:33:34 -05:00
{
recv_data . rpos ( recv_data . wpos ()); // prevent warnings spam
2008-10-02 16:23:55 -05:00
return ;
2009-08-24 19:33:34 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// if we boarded a transport, add us to it
2009-11-04 17:10:43 -08:00
if ( plMover && ! plMover -> GetTransport ())
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
2009-04-29 00:26:07 -05:00
for ( MapManager :: TransportSet :: const_iterator iter = MapManager :: Instance (). m_Transports . begin (); iter != MapManager :: Instance (). m_Transports . end (); ++ iter )
2008-10-02 16:23:55 -05:00
{
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-10-17 15:51:44 -07:00
2009-11-04 17:10:43 -08:00
if ( ! mover -> GetTransport () && ! mover -> GetVehicle ())
2010-01-13 18:25:46 +01:00
{
GameObject * go = mover -> GetMap () -> GetGameObject ( movementInfo . t_guid );
if ( ! go || go -> GetGoType () != GAMEOBJECT_TYPE_TRANSPORT )
movementInfo . flags &= ~ MOVEMENTFLAG_ONTRANSPORT ;
2010-01-13 10:04:48 +01:00
}
2008-10-02 16:23:55 -05:00
}
2009-11-04 17:10:43 -08:00
else if ( plMover && plMover -> GetTransport ()) // 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
}
2009-10-17 15:51:44 -07:00
2009-06-01 11:07:51 -05:00
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if ( opcode == MSG_MOVE_FALL_LAND && plMover && ! plMover -> isInFlight ())
plMover -> HandleFall ( movementInfo );
2009-10-17 15:51:44 -07:00
2009-06-01 11:07:51 -05:00
if ( plMover && (( movementInfo . flags & MOVEMENTFLAG_SWIMMING ) != 0 ) != plMover -> IsInWater ())
{
// now client not include swimming flag in case jumping under water
2009-11-03 22:28:04 -08:00
plMover -> SetInWater ( ! plMover -> IsInWater () || plMover -> GetBaseMap () -> IsUnderWater ( movementInfo . x , movementInfo . y , movementInfo . z ));
2009-06-01 11:07:51 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/*----------------------*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/* process position-change */
2009-12-17 11:31:44 +01:00
WorldPacket data ( opcode , recv_data . size ());
movementInfo . time = getMSTime ();
movementInfo . guid = mover -> GetGUID ();
WriteMovementInfo ( & data , & movementInfo );
2010-04-04 03:46:38 +03:00
mover -> SendMessageToSet ( & data , _player );
2009-10-17 15:51:44 -07:00
2009-04-23 00:12:29 -05:00
mover -> m_movementInfo = movementInfo ;
2009-10-17 15:51:44 -07:00
2009-11-04 17:10:43 -08:00
// this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
if ( mover -> GetVehicle ())
{
mover -> SetOrientation ( movementInfo . o );
return ;
}
2010-04-04 03:46:38 +03:00
mover -> SetPosition ( movementInfo . x , movementInfo . y , movementInfo . z , movementInfo . o );
2009-11-03 22:28:04 -08:00
if ( plMover ) // nothing is charmed, or player charmed
2008-12-24 09:58:26 -06:00
{
2009-12-17 11:31:44 +01:00
plMover -> UpdateFallInformationIfNeed ( movementInfo , opcode );
2009-10-17 15:51:44 -07:00
2009-11-03 22:28:04 -08:00
if ( movementInfo . z < - 500.0f )
2009-03-24 17:42:22 -06:00
{
2009-11-03 22:28:04 -08:00
if ( plMover -> InBattleGround ()
2009-03-24 17:42:22 -06:00
&& 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
2009-11-03 22:28:04 -08:00
if ( plMover -> isAlive ())
2009-03-24 17:42:22 -06:00
{
plMover -> EnvironmentalDamage ( DAMAGE_FALL_TO_VOID , GetPlayer () -> GetMaxHealth ());
2009-04-11 23:11:37 -05:00
// pl can be alive if GM/etc
2009-11-03 22:28:04 -08:00
if ( ! plMover -> isAlive ())
2009-04-11 23:11:37 -05:00
{
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
plMover -> KillPlayer ();
plMover -> BuildPlayerRepop ();
}
2009-03-24 17:42:22 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-24 17:42:22 -06:00
// cancel the death timer here if started
plMover -> RepopAtGraveyard ();
}
}
}
2010-04-04 03:46:38 +03:00
/*else // creature charmed
2009-03-24 17:42:22 -06:00
{
2010-04-07 19:14:10 +02:00
if (mover->canFly())
2009-06-15 12:02:55 -05:00
{
bool flying = mover->IsFlying();
2010-04-07 19:14:10 +02:00
if (flying != ((mover->GetByteValue(UNIT_FIELD_BYTES_1, 3) & 0x02) ? true : false))
2009-06-15 12:02:55 -05:00
mover->SetFlying(flying);
2010-04-04 03:46:38 +03:00
}
}*/
2009-10-17 15:51:44 -07:00
2009-06-13 09:18:54 -05:00
//sLog.outString("Receive Movement Packet %s:", opcodeTable[recv_data.GetOpcode()]);
//mover->OutMovementInfo();
2008-11-05 20:51:05 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleForceSpeedChangeAck ( WorldPacket & recv_data )
{
2009-12-17 11:31:44 +01:00
uint32 opcode = recv_data . GetOpcode ();
sLog . outDebug ( "WORLD: Recvd %s (%u, 0x%X) opcode" , LookupOpcodeName ( opcode ), opcode , opcode );
2009-12-18 13:41:30 -08:00
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 ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ))
2009-12-17 11:31:44 +01:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// now can skip not our packet
2010-04-07 19:14:10 +02:00
if ( _player -> GetGUID () != guid )
2009-08-19 17:19:50 -05:00
{
recv_data . rpos ( recv_data . wpos ()); // prevent warnings spam
2008-10-02 16:23:55 -05:00
return ;
2009-08-19 17:19:50 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// continue parse packet
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
recv_data >> unk1 ; // counter or moveEvent
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
MovementInfo movementInfo ;
2009-12-17 11:31:44 +01:00
movementInfo . guid = guid ;
2008-12-24 09:58:26 -06:00
ReadMovementInfo ( recv_data , & movementInfo );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
recv_data >> newspeed ;
/*----------------*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// 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 ;
2009-10-17 15:51:44 -07:00
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" };
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
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 ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// 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.
2010-04-07 19:14:10 +02:00
if ( _player -> m_forced_speed_changes [ force_move_type ] > 0 )
2008-10-02 16:23:55 -05:00
{
-- _player -> m_forced_speed_changes [ force_move_type ];
2010-04-07 19:14:10 +02:00
if ( _player -> m_forced_speed_changes [ force_move_type ] > 0 )
2008-10-02 16:23:55 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
if ( ! _player -> GetTransport () && fabs ( _player -> GetSpeed ( move_type ) - newspeed ) > 0.01f )
{
2010-04-07 19:14:10 +02:00
if ( _player -> GetSpeed ( move_type ) > newspeed ) // must be greater - just correct
2008-10-02 16:23:55 -05:00
{
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 ();
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleSetActiveMoverOpcode ( WorldPacket & recv_data )
{
sLog . outDebug ( "WORLD: Recvd CMSG_SET_ACTIVE_MOVER" );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint64 guid ;
recv_data >> guid ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> IsInWorld ())
if ( Unit * mover = ObjectAccessor :: GetUnit ( * GetPlayer (), guid ))
2010-01-13 18:24:23 +01:00
{
GetPlayer () -> SetMover ( mover );
2010-04-07 19:14:10 +02:00
if ( mover != GetPlayer () && mover -> canFly ())
2010-01-13 18:24:23 +01:00
{
WorldPacket data ( SMSG_MOVE_SET_CAN_FLY , 12 );
data . append ( mover -> GetPackGUID ());
data << uint32 ( 0 );
SendPacket ( & data );
}
}
2009-04-23 21:33:42 -05:00
else
2008-12-24 09:58:26 -06:00
{
2009-09-18 14:10:37 -07:00
sLog . outError ( "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " and should be " UI64FMTD , guid , _player -> m_mover -> GetGUID ());
2009-10-17 16:20:24 -07:00
GetPlayer () -> SetMover ( GetPlayer ());
2008-12-24 09:58:26 -06:00
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07: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" );
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
uint64 old_mover_guid ;
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( old_mover_guid ))
2009-12-17 11:31:44 +01:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
/*if (_player->m_mover->GetGUID() == old_mover_guid)
2008-12-24 09:58:26 -06:00
{
2009-09-14 16:49:23 -07:00
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);
2009-08-19 17:19:50 -05:00
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
2008-12-24 09:58:26 -06:00
return;
2009-04-23 21:43:20 -05:00
}*/
2009-10-17 15:51:44 -07:00
2009-12-17 11:31:44 +01:00
MovementInfo mi ;
mi . guid = old_mover_guid ;
ReadMovementInfo ( recv_data , & mi );
2009-12-18 13:41:30 -08:00
2009-12-17 11:31:44 +01:00
//ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);
_player -> m_movementInfo = mi ;
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
void WorldSession :: HandleDismissControlledVehicle ( WorldPacket & recv_data )
{
sLog . outDebug ( "WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE" );
recv_data . hexlike ();
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
uint64 vehicleGUID = _player -> GetCharmGUID ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! vehicleGUID ) // something wrong here...
2009-08-19 17:19:50 -05:00
{
recv_data . rpos ( recv_data . wpos ()); // prevent warnings spam
2008-12-24 09:58:26 -06:00
return ;
2009-08-19 17:19:50 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-17 11:31:44 +01:00
uint64 guid ;
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ))
2009-12-17 11:31:44 +01:00
return ;
MovementInfo mi ;
mi . guid = guid ;
ReadMovementInfo ( recv_data , & mi );
_player -> m_movementInfo = mi ;
2009-12-18 13:41:30 -08:00
2010-04-07 18:09:10 +02:00
/*
2009-12-17 11:31:44 +01:00
ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);*/
2009-04-21 14:05:54 -05:00
_player -> ExitVehicle ();
2008-11-07 16:49:42 -06:00
}
2009-10-17 15:51:44 -07:00
2009-04-17 15:08:58 -05:00
void WorldSession :: HandleChangeSeatsOnControlledVehicle ( WorldPacket & recv_data )
{
sLog . outDebug ( "WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE" );
recv_data . hexlike ();
2009-10-17 15:51:44 -07:00
2010-04-07 18:09:10 +02:00
Unit * vehicle_base = GetPlayer () -> GetVehicleBase ();
2010-04-07 19:14:10 +02:00
if ( ! vehicle_base )
2009-04-21 12:55:26 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-01-15 19:23:59 +02:00
switch ( recv_data . GetOpcode ())
2009-04-25 08:58:16 -05:00
{
2010-01-15 19:23:59 +02:00
case CMSG_REQUEST_VEHICLE_PREV_SEAT :
2009-04-25 08:58:16 -05:00
GetPlayer () -> ChangeSeat ( - 1 , false );
2010-01-15 19:23:59 +02:00
break ;
case CMSG_REQUEST_VEHICLE_NEXT_SEAT :
2009-04-25 08:58:16 -05:00
GetPlayer () -> ChangeSeat ( - 1 , true );
2010-01-15 19:23:59 +02:00
break ;
case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE :
{
uint64 guid ; // current vehicle guid
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ) || vehicle_base -> GetGUID () != guid )
2010-01-15 19:23:59 +02:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-03 16:59:52 +03:00
ReadMovementInfo ( recv_data , & vehicle_base -> m_movementInfo );
2009-10-17 15:51:44 -07:00
2010-01-15 19:23:59 +02:00
uint64 accessory ; // accessory guid
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( accessory ))
2010-01-15 19:23:59 +02:00
return ;
2009-10-17 15:51:44 -07:00
2010-01-15 19:23:59 +02:00
int8 seatId ;
recv_data >> seatId ;
2010-04-07 19:14:10 +02:00
if ( ! accessory )
2010-01-15 19:50:27 +01:00
GetPlayer () -> ChangeSeat ( - 1 , seatId > 0 ); // prev/next
2010-04-07 19:14:10 +02:00
else if ( Unit * vehUnit = Unit :: GetUnit ( * GetPlayer (), accessory ))
2010-04-03 16:59:52 +03:00
{
2010-04-07 19:14:10 +02:00
if ( Vehicle * vehicle = vehUnit -> GetVehicleKit ())
if ( vehicle -> HasEmptySeat ( seatId ))
2010-01-15 19:23:59 +02:00
GetPlayer () -> EnterVehicle ( vehicle , seatId );
2010-04-03 16:59:52 +03:00
}
}
break ;
case CMSG_REQUEST_VEHICLE_SWITCH_SEAT :
{
uint64 guid ; // current vehicle guid
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ) || vehicle_base -> GetGUID () != guid )
2010-04-03 16:59:52 +03:00
return ;
int8 seatId ;
recv_data >> seatId ;
GetPlayer () -> ChangeSeat ( - 1 , seatId > 0 ); // prev/next
2010-01-15 19:23:59 +02:00
}
break ;
2010-04-03 16:59:52 +03:00
default :
break ;
2010-01-15 19:23:59 +02:00
}
2009-04-17 15:08:58 -05:00
}
2009-10-17 15:51:44 -07:00
2010-01-15 19:50:27 +01:00
void WorldSession :: HandleEnterPlayerVehicle ( WorldPacket & data )
{
// Read guid
uint64 guid ;
data >> guid ;
2010-04-07 19:14:10 +02:00
if ( Player * pl = ObjectAccessor :: FindPlayer ( guid ))
2010-01-15 19:50:27 +01:00
{
if ( ! pl -> GetVehicleKit ())
return ;
if ( ! pl -> IsInRaidWith ( _player ))
return ;
2010-04-07 19:14:10 +02:00
if ( ! pl -> IsWithinDistInMap ( _player , INTERACTION_DISTANCE ))
2010-01-15 19:50:27 +01:00
return ;
_player -> EnterVehicle ( pl );
}
}
void WorldSession :: HandleEjectPasenger ( WorldPacket & data )
{
2010-04-07 19:14:10 +02:00
if ( data . GetOpcode () == CMSG_EJECT_PASSENGER )
2010-01-15 19:50:27 +01:00
{
2010-04-07 19:14:10 +02:00
if ( Vehicle * Vv = _player -> GetVehicleKit ())
2010-01-15 19:50:27 +01:00
{
uint64 guid ;
data >> guid ;
2010-04-07 19:14:10 +02:00
if ( Player * Pl = ObjectAccessor :: FindPlayer ( guid ))
2010-01-15 19:50:27 +01:00
Pl -> ExitVehicle ();
}
}
}
2009-04-17 15:08:58 -05:00
void WorldSession :: HandleRequestVehicleExit ( WorldPacket & recv_data )
{
sLog . outDebug ( "WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT" );
recv_data . hexlike ();
2009-04-21 14:05:54 -05:00
GetPlayer () -> ExitVehicle ();
2009-04-17 15:08:58 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleMountSpecialAnimOpcode ( WorldPacket & /*recvdata*/ )
{
//sLog.outDebug("WORLD: Recvd CMSG_MOUNTSPECIAL_ANIM");
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
WorldPacket data ( SMSG_MOUNTSPECIAL_ANIM , 8 );
data << uint64 ( GetPlayer () -> GetGUID ());
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
GetPlayer () -> SendMessageToSet ( & data , false );
}
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
void WorldSession :: HandleMoveKnockBackAck ( WorldPacket & recv_data )
2008-10-02 16:23:55 -05:00
{
sLog . outDebug ( "CMSG_MOVE_KNOCK_BACK_ACK" );
2009-10-17 15:51:44 -07:00
2009-12-17 11:31:44 +01:00
uint64 guid ; // guid - unused
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ))
2009-12-17 11:31:44 +01:00
return ;
2009-08-27 20:14:50 -05:00
recv_data . read_skip < uint32 > (); // unk
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
MovementInfo movementInfo ;
ReadMovementInfo ( recv_data , & movementInfo );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
void WorldSession :: HandleMoveHoverAck ( WorldPacket & recv_data )
2008-10-02 16:23:55 -05:00
{
sLog . outDebug ( "CMSG_MOVE_HOVER_ACK" );
2009-10-17 15:51:44 -07:00
2009-12-17 11:31:44 +01:00
uint64 guid ; // guid - unused
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ))
2009-12-17 11:31:44 +01:00
return ;
2009-08-27 20:14:50 -05:00
recv_data . read_skip < uint32 > (); // unk
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
MovementInfo movementInfo ;
ReadMovementInfo ( recv_data , & movementInfo );
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
recv_data . read_skip < uint32 > (); // unk2
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
void WorldSession :: HandleMoveWaterWalkAck ( WorldPacket & recv_data )
2008-10-02 16:23:55 -05:00
{
sLog . outDebug ( "CMSG_MOVE_WATER_WALK_ACK" );
2009-10-17 15:51:44 -07:00
2009-12-17 11:31:44 +01:00
uint64 guid ; // guid - unused
2010-04-07 19:14:10 +02:00
if ( ! recv_data . readPackGUID ( guid ))
2009-12-17 11:31:44 +01:00
return ;
2009-08-27 20:14:50 -05:00
recv_data . read_skip < uint32 > (); // unk
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
MovementInfo movementInfo ;
ReadMovementInfo ( recv_data , & movementInfo );
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
recv_data . read_skip < uint32 > (); // unk2
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void WorldSession :: HandleSummonResponseOpcode ( WorldPacket & recv_data )
{
2010-04-07 19:14:10 +02:00
if ( ! _player -> isAlive () || _player -> isInCombat () )
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint64 summoner_guid ;
bool agree ;
recv_data >> summoner_guid ;
recv_data >> agree ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
_player -> SummonIfPossible ( agree );
}
2010-04-01 12:56:26 -06:00