2010-10-07 15:35:36 +02:00
/*
2017-01-01 16:21:30 +01:00
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
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"
2015-05-08 00:03:15 +02:00
#include "Garrison.h"
2008-10-02 16:23:55 -05:00
#include "MapManager.h"
2010-06-07 16:21:52 -06:00
#include "Transport.h"
2010-08-08 04:37:24 +02:00
#include "Battleground.h"
2008-10-02 16:23:55 -05:00
#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
2009-02-09 22:08:06 -06:00
#include "ObjectMgr.h"
2014-06-09 21:08:19 +02:00
#include "Vehicle.h"
2016-06-13 18:00:55 +02:00
#include "InstancePackets.h"
2014-11-14 22:54:12 +00:00
#include "MovementPackets.h"
2009-10-17 15:51:44 -07:00
2013-09-26 20:03:39 +02:00
#define MOVEMENT_PACKET_TIME_DELAY 0
2015-04-01 01:44:10 +02:00
void WorldSession :: HandleMoveWorldportAckOpcode ( WorldPackets :: Movement :: WorldPortResponse & /*packet*/ )
2008-10-02 16:23:55 -05:00
{
2016-08-06 12:34:38 +02:00
HandleMoveWorldportAck ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2016-08-06 12:34:38 +02:00
void WorldSession :: HandleMoveWorldportAck ()
2008-10-02 16:23:55 -05:00
{
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
2015-05-01 15:44:43 +02:00
bool seamlessTeleport = GetPlayer () -> IsBeingTeleportedSeamlessly ();
2011-04-09 11:28:39 +03:00
GetPlayer () -> SetSemaphoreTeleportFar ( false );
2008-10-02 16:23:55 -05:00
// get the teleport destination
2012-10-24 13:29:34 +02:00
WorldLocation const & 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 ());
2011-04-28 22:16:13 +02:00
InstanceTemplate const * mInstance = sObjectMgr -> 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
2011-09-15 14:08:17 +02:00
Map * oldMap = GetPlayer () -> GetMap ();
2013-04-27 19:56:40 +02:00
Map * newMap = sMapMgr -> CreateMap ( loc . GetMapId (), GetPlayer ());
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> IsInWorld ())
2009-08-13 10:01:00 -05:00
{
2014-09-14 16:14:12 +02:00
TC_LOG_ERROR ( "network" , "%s %s is still in world when teleported from map %s (%u) to new map %s (%u)" , GetPlayer () -> GetGUID (). ToString (). c_str (), GetPlayer () -> GetName (). c_str (), oldMap -> GetMapName (), oldMap -> GetId (), newMap ? newMap -> GetMapName () : "Unknown" , loc . GetMapId ());
2011-11-11 17:50:26 -05:00
oldMap -> RemovePlayerFromMap ( GetPlayer (), false );
2009-08-13 10:01:00 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// relocate the player to the teleport destination
2015-12-31 19:51:07 +01:00
// the CannotEnter checks are done in TeleporTo but conditions may change
2009-08-01 00:20:32 +02:00
// while the player is in transit, for example the map may get full
2015-12-31 19:51:07 +01:00
if ( ! newMap || newMap -> CannotEnter ( GetPlayer ()))
2009-07-18 15:00:36 +02:00
{
2014-10-22 23:31:10 +02:00
TC_LOG_ERROR ( "network" , "Map %d (%s) could not be created for %s (%s), porting player to homebind" , loc . GetMapId (), newMap ? newMap -> GetMapName () : "Unknown" , GetPlayer () -> GetGUID (). ToString (). c_str (), GetPlayer () -> GetName (). c_str ());
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
}
2013-11-21 16:13:13 +01:00
float z = loc . GetPositionZ ();
if ( GetPlayer () -> HasUnitMovementFlag ( MOVEMENTFLAG_HOVER ))
z += GetPlayer () -> GetFloatValue ( UNIT_FIELD_HOVERHEIGHT );
2015-05-01 15:44:43 +02:00
2013-11-21 16:13:13 +01:00
GetPlayer () -> Relocate ( loc . GetPositionX (), loc . GetPositionY (), z , loc . GetOrientation ());
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
2016-06-13 18:00:55 +02:00
WorldPackets :: Movement :: ResumeToken resumeToken ;
resumeToken . SequenceIndex = _player -> m_movementCounter ;
resumeToken . Reason = seamlessTeleport ? 2 : 1 ;
SendPacket ( resumeToken . Write ());
2015-05-01 15:44:43 +02:00
if ( ! seamlessTeleport )
GetPlayer () -> SendInitialPacketsBeforeAddToMap ();
if ( ! GetPlayer () -> GetMap () -> AddPlayerToMap ( GetPlayer (), ! seamlessTeleport ))
2008-10-02 16:23:55 -05:00
{
2014-10-22 23:31:10 +02:00
TC_LOG_ERROR ( "network" , "WORLD: failed to teleport player %s (%s) to map %d (%s) because of unknown reason!" ,
GetPlayer () -> GetName (). c_str (), GetPlayer () -> GetGUID (). ToString (). c_str (), loc . GetMapId (), newMap ? newMap -> GetMapName () : "Unknown" );
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-08-08 04:37:24 +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-08-08 04:37:24 +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
2010-08-08 04:37:24 +02:00
_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
2011-09-15 14:08:17 +02:00
else if ( Battleground * bg = _player -> GetBattleground ())
2009-02-13 19:56:55 -06:00
{
2010-08-08 04:37:24 +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
2015-05-01 15:44:43 +02:00
if ( ! seamlessTeleport )
GetPlayer () -> SendInitialPacketsAfterAddToMap ();
else
2015-05-08 00:03:15 +02:00
{
2015-05-01 15:44:43 +02:00
GetPlayer () -> UpdateVisibilityForPlayer ();
2015-05-08 00:03:15 +02:00
if ( Garrison * garrison = GetPlayer () -> GetGarrison ())
garrison -> SendRemoteInfo ();
}
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-08-08 04:37:24 +02:00
if ( ! _player -> InBattleground ())
2008-10-02 16:23:55 -05:00
{
2015-05-01 15:44:43 +02:00
if ( ! seamlessTeleport )
{
// short preparations to continue flight
FlightPathMovementGenerator * flight = ( FlightPathMovementGenerator * )( GetPlayer () -> GetMotionMaster () -> top ());
flight -> Initialize ( GetPlayer ());
}
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
// 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
2015-12-31 19:51:07 +01:00
if ( mEntry -> IsDungeon () && ! GetPlayer () -> IsAlive ())
if ( GetPlayer () -> GetCorpseLocation (). GetMapId () == mEntry -> ID )
2008-10-02 16:23:55 -05:00
{
2011-04-29 20:47:02 +02:00
GetPlayer () -> ResurrectPlayer ( 0.5f , false );
2008-10-02 16:23:55 -05:00
GetPlayer () -> SpawnCorpseBones ();
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02: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
{
2015-12-31 19:51:07 +01:00
// check if this instance has a reset time and send it to player if so
2015-01-10 01:35:47 +01:00
Difficulty diff = GetPlayer () -> GetDifficultyID ( mEntry );
2016-04-25 22:03:34 +02:00
if ( MapDifficultyEntry const * mapDiff = sDB2Manager . GetMapDifficultyData ( mEntry -> ID , diff ))
2009-12-17 11:31:44 +01:00
{
2016-04-25 22:03:34 +02:00
if ( mapDiff -> GetRaidDuration ())
2010-01-16 19:54:57 +03:00
{
2014-11-05 23:33:56 +02:00
if ( time_t timeReset = sInstanceSaveMgr -> GetResetTimeFor ( mEntry -> ID , diff ))
2010-01-16 19:54:57 +03:00
{
2010-08-30 23:07:14 +02:00
uint32 timeleft = uint32 ( timeReset - time ( NULL ));
2015-07-08 23:32:04 +02:00
GetPlayer () -> SendInstanceResetWarning ( mEntry -> ID , diff , timeleft , true );
2010-01-16 19:54:57 +03:00
}
}
2009-12-17 11:31:44 +01:00
}
2015-12-31 19:51:07 +01:00
// check if instance is valid
if ( ! GetPlayer () -> CheckInstanceValidity ( false ))
GetPlayer () -> m_InstanceValid = false ;
// instance mounting is handled in InstanceTemplate
2011-04-28 22:16:13 +02: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
2013-02-26 17:14:13 +01:00
if ( GetPlayer () -> pvpInfo . IsHostile )
2010-02-15 18:23:39 +01:00
GetPlayer () -> CastSpell ( GetPlayer (), 2479 , true );
2010-09-18 19:08:18 -07:00
2010-07-31 13:55:23 +02:00
// in friendly area
2011-04-29 20:47:02 +02:00
else if ( GetPlayer () -> IsPvP () && ! GetPlayer () -> HasFlag ( PLAYER_FLAGS , PLAYER_FLAGS_IN_PVP ))
2010-07-31 13:55:23 +02:00
GetPlayer () -> UpdatePvP ( false , false );
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
2016-06-13 18:00:55 +02:00
void WorldSession :: HandleSuspendTokenResponse ( WorldPackets :: Movement :: SuspendTokenResponse & /*suspendTokenResponse*/ )
{
if ( ! _player -> IsBeingTeleportedFar ())
return ;
WorldLocation const & loc = GetPlayer () -> GetTeleportDest ();
if ( sMapStore . AssertEntry ( loc . GetMapId ()) -> IsDungeon ())
{
WorldPackets :: Instance :: UpdateLastInstance updateLastInstance ;
updateLastInstance . MapID = loc . GetMapId ();
SendPacket ( updateLastInstance . Write ());
}
WorldPackets :: Movement :: NewWorld packet ;
packet . MapID = loc . GetMapId ();
packet . Pos . Relocate ( loc );
packet . Reason = ! _player -> IsBeingTeleportedSeamlessly () ? NEW_WORLD_NORMAL : NEW_WORLD_SEAMLESS ;
SendPacket ( packet . Write ());
if ( _player -> IsBeingTeleportedSeamlessly ())
2016-08-06 12:34:38 +02:00
HandleMoveWorldportAck ();
2016-06-13 18:00:55 +02:00
}
2014-11-30 23:33:16 +02:00
void WorldSession :: HandleMoveTeleportAck ( WorldPackets :: Movement :: MoveTeleportAck & packet )
2009-04-11 23:07:07 -05:00
{
2014-11-30 23:33:16 +02:00
TC_LOG_DEBUG ( "network" , "CMSG_MOVE_TELEPORT_ACK: Guid: %s, Sequence: %u, Time: %u" , packet . MoverGUID . ToString (). c_str (), packet . AckIndex , packet . MoveTime );
2009-10-17 15:51:44 -07:00
2016-08-20 12:43:04 +02:00
Player * plMover = _player -> m_unitMovedByMe -> ToPlayer ();
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
2014-11-30 23:33:16 +02:00
if ( packet . MoverGUID != 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
2011-10-10 17:08:01 -04:00
plMover -> UpdatePosition ( 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
2013-02-26 17:14:13 +01:00
if ( plMover -> pvpInfo . IsHostile )
2010-02-15 18:23:39 +01:00
plMover -> CastSpell ( plMover , 2479 , true );
2010-09-18 19:08:18 -07:00
2010-07-31 13:55:23 +02:00
// in friendly area
2011-04-29 20:47:02 +02:00
else if ( plMover -> IsPvP () && ! plMover -> HasFlag ( PLAYER_FLAGS , PLAYER_FLAGS_IN_PVP ))
2010-07-31 13:55:23 +02:00
plMover -> UpdatePvP ( false , false );
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
2014-11-14 22:54:12 +00:00
void WorldSession :: HandleMovementOpcodes ( WorldPackets :: Movement :: ClientPlayerMovement & packet )
2008-10-02 16:23:55 -05:00
{
2014-11-14 22:54:12 +00:00
OpcodeClient opcode = packet . GetOpcode ();
2009-10-17 15:51:44 -07:00
2016-08-20 12:43:04 +02:00
Unit * mover = _player -> m_unitMovedByMe ;
2009-11-03 22:28:04 -08:00
2014-11-14 22:54:12 +00:00
ASSERT ( mover != nullptr ); // there must always be a mover
2009-11-03 22:28:04 -08:00
2012-05-30 08:01:02 +02:00
Player * plrMover = mover -> ToPlayer ();
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
2012-05-30 08:01:02 +02:00
if ( plrMover && plrMover -> IsBeingTeleported ())
2009-01-16 19:47:25 -06:00
return ;
2015-04-04 23:49:14 +02:00
GetPlayer () -> ValidateMovementInfo ( & packet . movementInfo );
2009-10-17 15:51:44 -07:00
2014-11-14 22:54:12 +00:00
MovementInfo & movementInfo = packet . movementInfo ;
2009-10-17 15:51:44 -07:00
2010-09-08 09:46:42 +03:00
// prevent tampered movement data
2011-11-29 17:56:00 +01:00
if ( movementInfo . guid != mover -> GetGUID ())
2012-01-10 19:21:01 +01:00
{
2013-11-08 11:12:17 +01:00
TC_LOG_ERROR ( "network" , "HandleMovementOpcodes: guid error" );
2010-09-08 09:46:42 +03:00
return ;
2012-01-10 19:21:01 +01:00
}
2015-04-04 23:49:14 +02:00
2010-08-04 14:39:45 +02:00
if ( ! movementInfo . pos . IsPositionValid ())
2009-08-24 19:33:34 -05:00
{
2013-11-08 11:12:17 +01:00
TC_LOG_ERROR ( "network" , "HandleMovementOpcodes: Invalid Position" );
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
2014-09-06 03:20:39 +02:00
// stop some emotes at player move
if ( plrMover && ( plrMover -> GetUInt32Value ( UNIT_NPC_EMOTESTATE ) != 0 ))
plrMover -> SetUInt32Value ( UNIT_NPC_EMOTESTATE , EMOTE_ONESHOT_NONE );
2008-10-02 16:23:55 -05:00
/* handle special cases */
2014-10-21 20:27:00 +02:00
if ( ! movementInfo . transport . guid . IsEmpty ())
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)
2013-06-18 18:15:33 +02:00
if ( movementInfo . transport . pos . GetPositionX () > 50 || movementInfo . transport . pos . GetPositionY () > 50 || movementInfo . transport . pos . GetPositionZ () > 50 )
2009-08-24 19:33:34 -05:00
{
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
2013-06-18 18:15:33 +02:00
if ( ! Trinity :: IsValidMapCoord ( movementInfo . pos . GetPositionX () + movementInfo . transport . pos . GetPositionX (), movementInfo . pos . GetPositionY () + movementInfo . transport . pos . GetPositionY (),
movementInfo . pos . GetPositionZ () + movementInfo . transport . pos . GetPositionZ (), movementInfo . pos . GetOrientation () + movementInfo . transport . pos . GetOrientation ()))
2009-08-24 19:33:34 -05:00
{
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
2012-06-02 18:38:02 +02:00
if ( plrMover )
2008-10-02 16:23:55 -05:00
{
2012-06-02 18:38:02 +02:00
if ( ! plrMover -> GetTransport ())
2008-10-02 16:23:55 -05:00
{
2013-10-16 18:37:29 +02:00
if ( Transport * transport = plrMover -> GetMap () -> GetTransport ( movementInfo . transport . guid ))
transport -> AddPassenger ( plrMover );
2012-06-02 18:38:02 +02:00
}
2013-06-18 18:15:33 +02:00
else if ( plrMover -> GetTransport () -> GetGUID () != movementInfo . transport . guid )
2012-06-02 18:38:02 +02:00
{
2014-06-13 11:16:17 +02:00
plrMover -> GetTransport () -> RemovePassenger ( plrMover );
2013-10-16 18:37:29 +02:00
if ( Transport * transport = plrMover -> GetMap () -> GetTransport ( movementInfo . transport . guid ))
transport -> AddPassenger ( plrMover );
2014-06-13 11:16:17 +02:00
else
2013-06-18 21:04:31 +02:00
movementInfo . ResetTransport ();
2008-10-02 16:23:55 -05:00
}
}
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
{
2013-06-18 18:15:33 +02:00
GameObject * go = mover -> GetMap () -> GetGameObject ( movementInfo . transport . guid );
2010-01-13 18:25:46 +01:00
if ( ! go || go -> GetGoType () != GAMEOBJECT_TYPE_TRANSPORT )
2016-06-12 00:11:00 +02:00
movementInfo . transport . Reset ();
2010-01-13 10:04:48 +01:00
}
2008-10-02 16:23:55 -05:00
}
2012-05-30 08:01:02 +02:00
else if ( plrMover && plrMover -> GetTransport ()) // if we were on a transport, leave
plrMover -> m_transport -> RemovePassenger ( plrMover );
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).
2014-11-06 02:59:59 +01:00
if ( opcode == CMSG_MOVE_FALL_LAND && plrMover && ! plrMover -> IsInFlight ())
2012-05-30 08:01:02 +02:00
plrMover -> HandleFall ( movementInfo );
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
if ( plrMover && (( movementInfo . flags & MOVEMENTFLAG_SWIMMING ) != 0 ) != plrMover -> IsInWater ())
2009-06-01 11:07:51 -05:00
{
// now client not include swimming flag in case jumping under water
2012-05-30 08:01:02 +02:00
plrMover -> SetInWater ( ! plrMover -> IsInWater () || plrMover -> GetBaseMap () -> IsUnderWater ( movementInfo . pos . GetPositionX (), movementInfo . pos . GetPositionY (), movementInfo . pos . GetPositionZ ()));
2009-06-01 11:07:51 -05:00
}
2009-10-17 15:51:44 -07:00
2013-09-26 20:03:39 +02:00
uint32 mstime = getMSTime ();
2008-10-02 16:23:55 -05:00
/*----------------------*/
2013-10-26 14:39:00 +02:00
if ( m_clientTimeDelay == 0 )
2013-09-26 20:03:39 +02:00
m_clientTimeDelay = mstime - movementInfo . time ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/* process position-change */
2013-09-26 20:03:39 +02:00
movementInfo . time = movementInfo . time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY ;
2012-12-29 15:20:57 -05:00
movementInfo . guid = mover -> GetGUID ();
mover -> m_movementInfo = movementInfo ;
2009-10-17 15:51:44 -07:00
2014-06-09 21:08:19 +02:00
// Some vehicles allow the passenger to turn by himself
if ( Vehicle * vehicle = mover -> GetVehicle ())
2009-11-04 17:10:43 -08:00
{
2014-06-09 21:08:19 +02:00
if ( VehicleSeatEntry const * seat = vehicle -> GetSeatForPassenger ( mover ))
{
2016-01-31 19:25:51 +01:00
if ( seat -> Flags [ 0 ] & VEHICLE_SEAT_FLAG_ALLOW_TURNING )
2014-06-09 21:08:19 +02:00
{
if ( movementInfo . pos . GetOrientation () != mover -> GetOrientation ())
{
mover -> SetOrientation ( movementInfo . pos . GetOrientation ());
mover -> RemoveAurasWithInterruptFlags ( AURA_INTERRUPT_FLAG_TURNING );
}
}
}
2009-11-04 17:10:43 -08:00
return ;
}
2011-10-10 17:08:01 -04:00
mover -> UpdatePosition ( movementInfo . pos );
2010-04-04 03:46:38 +03:00
2015-01-18 23:56:01 +01:00
WorldPackets :: Movement :: MoveUpdate moveUpdate ;
moveUpdate . movementInfo = & mover -> m_movementInfo ;
mover -> SendMessageToSet ( moveUpdate . Write (), _player );
2013-04-03 18:51:43 +02:00
2012-05-30 08:01:02 +02:00
if ( plrMover ) // nothing is charmed, or player charmed
2008-12-24 09:58:26 -06:00
{
2014-01-16 20:44:03 +01:00
if ( plrMover -> IsSitState () && ( movementInfo . flags & ( MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING )))
plrMover -> SetStandState ( UNIT_STAND_STATE_STAND );
2012-05-30 08:01:02 +02:00
plrMover -> UpdateFallInformationIfNeed ( movementInfo , opcode );
2012-11-07 23:21:19 +01:00
2016-02-09 00:14:58 +01:00
if ( movementInfo . pos . GetPositionZ () < plrMover -> GetMap () -> GetMinHeight ( movementInfo . pos . GetPositionX (), movementInfo . pos . GetPositionY ()))
2009-03-24 17:42:22 -06:00
{
2012-05-30 08:01:02 +02:00
if ( ! ( plrMover -> GetBattleground () && plrMover -> GetBattleground () -> HandlePlayerUnderMap ( _player )))
2009-03-24 17:42:22 -06:00
{
// NOTE: this is actually called many times while falling
// even after the player has been teleported away
2013-03-08 21:41:30 +01:00
/// @todo discard movement packets after the player is rooted
2013-06-11 19:54:27 -02:30
if ( plrMover -> IsAlive ())
2009-03-24 17:42:22 -06:00
{
2016-02-09 00:14:58 +01:00
plrMover -> SetFlag ( PLAYER_FLAGS , PLAYER_FLAGS_IS_OUT_OF_BOUNDS );
2012-05-30 08:01:02 +02:00
plrMover -> EnvironmentalDamage ( DAMAGE_FALL_TO_VOID , GetPlayer () -> GetMaxHealth ());
2011-11-07 11:18:00 -06:00
// player can be alive if GM/etc
2011-09-30 18:40:09 +02:00
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
2013-06-11 19:54:27 -02:30
if ( ! plrMover -> IsAlive ())
2012-05-30 08:01:02 +02:00
plrMover -> KillPlayer ();
2009-03-24 17:42:22 -06:00
}
}
}
2014-11-15 11:37:08 +01:00
}
2008-11-05 20:51:05 -06:00
}
2009-10-17 15:51:44 -07:00
2015-03-15 16:50:43 +01:00
void WorldSession :: HandleForceSpeedChangeAck ( WorldPackets :: Movement :: MovementSpeedAck & packet )
2008-10-02 16:23:55 -05:00
{
2009-10-17 15:51:44 -07:00
2015-04-05 01:39:32 +02:00
GetPlayer () -> ValidateMovementInfo ( & packet . Ack . movementInfo );
2015-04-04 23:49:14 +02:00
2008-10-02 16:23:55 -05:00
// now can skip not our packet
2015-04-05 01:39:32 +02:00
if ( _player -> GetGUID () != packet . Ack . movementInfo . guid )
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
/*----------------*/
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 ;
2009-10-17 15:51:44 -07:00
2013-04-03 20:13:33 +02:00
static char const * const move_type_name [ MAX_MOVE_TYPE ] =
{
"Walk" ,
"Run" ,
"RunBack" ,
"Swim" ,
"SwimBack" ,
"TurnRate" ,
"Flight" ,
"FlightBack" ,
"PitchRate"
};
2009-10-17 15:51:44 -07:00
2015-04-05 01:39:32 +02:00
OpcodeClient opcode = packet . GetOpcode ();
2015-03-15 16:50:43 +01:00
switch ( opcode )
2008-10-02 16:23:55 -05:00
{
2015-04-01 01:44:10 +02:00
2013-04-03 20:13:33 +02:00
case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK : move_type = MOVE_WALK ; break ;
case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK : move_type = MOVE_RUN ; break ;
case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK : move_type = MOVE_RUN_BACK ; break ;
case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK : move_type = MOVE_SWIM ; break ;
2015-04-01 11:13:10 +02:00
case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK : move_type = MOVE_SWIM_BACK ; break ;
case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK : move_type = MOVE_TURN_RATE ; break ;
2013-04-03 20:13:33 +02:00
case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK : move_type = MOVE_FLIGHT ; break ;
2015-04-01 11:13:10 +02:00
case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK : move_type = MOVE_FLIGHT_BACK ; break ;
case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK : move_type = MOVE_PITCH_RATE ; break ;
2015-04-01 01:44:10 +02:00
2008-10-02 16:23:55 -05:00
default :
2015-03-15 16:50:43 +01:00
TC_LOG_ERROR ( "network" , "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u" , opcode );
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
// skip all forced speed changes except last and unexpected
2013-04-03 20:13:33 +02:00
// 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 [ move_type ] > 0 )
2008-10-02 16:23:55 -05:00
{
2013-04-03 20:13:33 +02:00
-- _player -> m_forced_speed_changes [ move_type ];
if ( _player -> m_forced_speed_changes [ move_type ] > 0 )
2008-10-02 16:23:55 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2015-03-15 16:50:43 +01:00
if ( ! _player -> GetTransport () && std :: fabs ( _player -> GetSpeed ( move_type ) - packet . Speed ) > 0.01f )
2008-10-02 16:23:55 -05:00
{
2015-03-15 16:50:43 +01:00
if ( _player -> GetSpeed ( move_type ) > packet . Speed ) // must be greater - just correct
2008-10-02 16:23:55 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "network" , "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value" ,
2015-03-15 16:50:43 +01:00
move_type_name [ move_type ], _player -> GetName (). c_str (), _player -> GetSpeed ( move_type ), packet . Speed );
2016-04-16 01:36:32 +02:00
_player -> SetSpeedRate ( move_type , _player -> GetSpeedRate ( move_type ));
2008-10-02 16:23:55 -05:00
}
else // must be lesser - cheating
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "misc" , "Player %s from account id %u kicked for incorrect speed (must be %f instead %f)" ,
2015-03-15 16:50:43 +01:00
_player -> GetName (). c_str (), _player -> GetSession () -> GetAccountId (), _player -> GetSpeed ( move_type ), packet . Speed );
2008-10-02 16:23:55 -05:00
_player -> GetSession () -> KickPlayer ();
}
}
}
2009-10-17 15:51:44 -07:00
2015-03-20 15:41:13 +01:00
void WorldSession :: HandleSetActiveMoverOpcode ( WorldPackets :: Movement :: SetActiveMover & packet )
2008-10-02 16:23:55 -05:00
{
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> IsInWorld ())
2016-08-20 12:43:04 +02:00
if ( _player -> m_unitMovedByMe -> GetGUID () != packet . ActiveMover )
TC_LOG_DEBUG ( "network" , "HandleSetActiveMoverOpcode: incorrect mover guid: mover is %s and should be %s" , packet . ActiveMover . ToString (). c_str (), _player -> m_unitMovedByMe -> GetGUID (). ToString (). c_str ());
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2015-04-05 01:39:32 +02:00
void WorldSession :: HandleMoveKnockBackAck ( WorldPackets :: Movement :: MovementAckMessage & movementAck )
2008-10-02 16:23:55 -05:00
{
2015-04-05 01:39:32 +02:00
GetPlayer () -> ValidateMovementInfo ( & movementAck . Ack . movementInfo );
2009-10-17 15:51:44 -07:00
2016-08-20 12:43:04 +02:00
if ( _player -> m_unitMovedByMe -> GetGUID () != movementAck . Ack . movementInfo . guid )
2012-12-25 21:49:48 -05:00
return ;
2015-04-05 01:39:32 +02:00
_player -> m_movementInfo = movementAck . Ack . movementInfo ;
2011-09-30 18:24:12 +02:00
2015-04-04 23:49:14 +02:00
WorldPackets :: Movement :: MoveUpdateKnockBack updateKnockBack ;
updateKnockBack . movementInfo = & _player -> m_movementInfo ;
_player -> SendMessageToSet ( updateKnockBack . Write (), false );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2015-04-12 19:43:59 +02:00
void WorldSession :: HandleMovementAckMessage ( WorldPackets :: Movement :: MovementAckMessage & movementAck )
2008-10-02 16:23:55 -05:00
{
2015-04-12 19:43:59 +02:00
GetPlayer () -> ValidateMovementInfo ( & movementAck . Ack . movementInfo );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2015-07-16 22:01:22 +02:00
void WorldSession :: HandleSummonResponseOpcode ( WorldPackets :: Movement :: SummonResponse & packet )
2008-10-02 16:23:55 -05:00
{
2013-06-11 19:54:27 -02:30
if ( ! _player -> IsAlive () || _player -> IsInCombat ())
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2015-07-16 22:01:22 +02:00
_player -> SummonIfPossible ( packet . Accept );
2008-10-02 16:23:55 -05:00
}
2013-04-09 17:24:39 +02:00
2015-04-05 01:39:32 +02:00
void WorldSession :: HandleSetCollisionHeightAck ( WorldPackets :: Movement :: MoveSetCollisionHeightAck & setCollisionHeightAck )
2013-04-09 17:24:39 +02:00
{
2015-04-05 01:39:32 +02:00
GetPlayer () -> ValidateMovementInfo ( & setCollisionHeightAck . Data . movementInfo );
2013-04-09 17:24:39 +02:00
}
2015-04-12 19:43:59 +02:00
void WorldSession :: HandleMoveTimeSkippedOpcode ( WorldPackets :: Movement :: MoveTimeSkipped & /*moveTimeSkipped*/ )
{
}
2015-08-30 19:26:33 +02:00
2015-09-19 17:39:01 +02:00
void WorldSession :: HandleMoveSplineDoneOpcode ( WorldPackets :: Movement :: MoveSplineDone & moveSplineDone )
2015-08-30 19:26:33 +02:00
{
2015-09-19 17:39:01 +02:00
MovementInfo movementInfo = moveSplineDone . movementInfo ;
2015-08-30 19:26:33 +02:00
_player -> ValidateMovementInfo ( & movementInfo );
// in taxi flight packet received in 2 case:
// 1) end taxi path in far (multi-node) flight
// 2) switch from one map to other in case multim-map taxi path
// we need process only (1)
uint32 curDest = GetPlayer () -> m_taxi . GetTaxiDestination ();
if ( curDest )
{
TaxiNodesEntry const * curDestNode = sTaxiNodesStore . LookupEntry ( curDest );
// far teleport case
if ( curDestNode && curDestNode -> MapID != GetPlayer () -> GetMapId ())
{
if ( GetPlayer () -> GetMotionMaster () -> GetCurrentMovementGeneratorType () == FLIGHT_MOTION_TYPE )
{
// short preparations to continue flight
FlightPathMovementGenerator * flight = ( FlightPathMovementGenerator * )( GetPlayer () -> GetMotionMaster () -> top ());
flight -> SetCurrentNodeAfterTeleport ();
TaxiPathNodeEntry const * node = flight -> GetPath ()[ flight -> GetCurrentNode ()];
flight -> SkipCurrentNode ();
GetPlayer () -> TeleportTo ( curDestNode -> MapID , node -> Loc . X , node -> Loc . Y , node -> Loc . Z , GetPlayer () -> GetOrientation ());
}
}
return ;
}
// at this point only 1 node is expected (final destination)
if ( GetPlayer () -> m_taxi . GetPath (). size () != 1 )
return ;
GetPlayer () -> CleanupAfterTaxiFlight ();
GetPlayer () -> SetFallInformation ( 0 , GetPlayer () -> GetPositionZ ());
if ( GetPlayer () -> pvpInfo . IsHostile )
GetPlayer () -> CastSpell ( GetPlayer (), 2479 , true );
}