2010-10-07 15:35:36 +02:00
/*
2012-01-01 00:32:13 +01:00
* Copyright (C) 2008-2012 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"
2009-05-05 16:56:15 -05:00
#include "SpellAuras.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"
2011-11-29 17:56:00 +01:00
#include "MovementStructures.h"
2009-10-17 15:51:44 -07:00
2012-07-17 19:29:18 +02:00
void WorldSession :: HandleMoveWorldportAckOpcode ( WorldPacket & /*recvPacket*/ )
2008-10-02 16:23:55 -05:00
{
2012-07-17 19:29:18 +02:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "WORLD: got MSG_MOVE_WORLDPORT_ACK." );
2008-10-02 16:23:55 -05:00
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
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 ();
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> IsInWorld ())
2009-08-13 10:01:00 -05:00
{
2012-10-24 13:29:34 +02:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "Player (Name %s) is still in world when teleported from map %u to new map %u" , GetPlayer () -> GetName (). c_str (), oldMap -> GetId (), 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
2011-11-23 12:45:59 -05:00
Map * newMap = sMapMgr -> CreateMap ( loc . GetMapId (), GetPlayer ());
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
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "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 ();
2011-11-11 17:50:26 -05:00
if ( ! GetPlayer () -> GetMap () -> AddPlayerToMap ( GetPlayer ()))
2008-10-02 16:23:55 -05:00
{
2012-10-24 13:29:34 +02:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!" ,
GetPlayer () -> GetName (). c_str (), 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-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
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-08-08 04:37:24 +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
2011-09-15 14:08:17 +02:00
Corpse * corpse = GetPlayer () -> GetCorpse ();
2008-10-02 16:23:55 -05:00
if ( corpse && corpse -> GetType () != CORPSE_BONES && corpse -> GetMapId () == GetPlayer () -> GetMapId ())
{
2010-04-07 22:59:46 +02:00
if ( mEntry -> IsDungeon ())
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
{
2009-12-17 11:31:44 +01:00
Difficulty diff = GetPlayer () -> GetDifficulty ( mEntry -> IsRaid ());
2011-01-24 11:20:30 +01: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 )
{
2011-01-24 11:20:30 +01:00
if ( time_t timeReset = sInstanceSaveMgr -> GetResetTimeFor ( mEntry -> MapID , diff ))
2010-01-16 19:54:57 +03:00
{
2010-08-30 23:07:14 +02:00
uint32 timeleft = uint32 ( timeReset - time ( NULL ));
2010-01-16 19:54:57 +03:00
GetPlayer () -> SendInstanceResetWarning ( mEntry -> MapID , diff , timeleft );
}
}
2009-12-17 11:31:44 +01:00
}
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
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 );
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
2012-07-17 19:29:18 +02:00
void WorldSession :: HandleMoveTeleportAck ( WorldPacket & recvPacket )
2009-04-11 23:07:07 -05:00
{
2012-07-17 19:29:18 +02:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "MSG_MOVE_TELEPORT_ACK" );
2009-12-17 11:31:44 +01:00
2012-07-17 19:29:18 +02:00
ObjectGuid guid ;
2009-12-17 11:31:44 +01:00
uint32 flags , time ;
2012-07-17 19:29:18 +02:00
recvPacket >> flags >> time ;
guid [ 5 ] = recvPacket . ReadBit ();
guid [ 0 ] = recvPacket . ReadBit ();
guid [ 1 ] = recvPacket . ReadBit ();
guid [ 6 ] = recvPacket . ReadBit ();
guid [ 3 ] = recvPacket . ReadBit ();
guid [ 7 ] = recvPacket . ReadBit ();
guid [ 2 ] = recvPacket . ReadBit ();
guid [ 4 ] = recvPacket . ReadBit ();
recvPacket . ReadByteSeq ( guid [ 4 ]);
recvPacket . ReadByteSeq ( guid [ 2 ]);
recvPacket . ReadByteSeq ( guid [ 7 ]);
recvPacket . ReadByteSeq ( guid [ 6 ]);
recvPacket . ReadByteSeq ( guid [ 5 ]);
recvPacket . ReadByteSeq ( guid [ 1 ]);
recvPacket . ReadByteSeq ( guid [ 3 ]);
recvPacket . ReadByteSeq ( guid [ 0 ]);
2012-08-07 13:44:22 -05:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "Guid " UI64FMTD , uint64 ( guid ));
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "Flags %u, time %u" , flags , time / IN_MILLISECONDS );
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
Player * plMover = _player -> m_mover -> 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
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
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
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 );
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
2012-07-17 19:29:18 +02:00
void WorldSession :: HandleMovementOpcodes ( WorldPacket & recvPacket )
2008-10-02 16:23:55 -05:00
{
2012-07-17 19:29:18 +02:00
uint16 opcode = recvPacket . GetOpcode ();
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Unit * mover = _player -> m_mover ;
2009-11-03 22:28:04 -08:00
2012-05-30 08:01:02 +02:00
ASSERT ( mover != NULL ); // 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-08-19 17:19:50 -05:00
{
2012-07-17 19:29:18 +02:00
recvPacket . rfinish (); // 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 */
MovementInfo movementInfo ;
2012-07-17 19:29:18 +02:00
ReadMovementInfo ( recvPacket , & 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
{
2012-08-07 13:44:22 -05:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "HandleMovementOpcodes: guid error" );
2010-09-08 09:46:42 +03:00
return ;
2012-01-10 19:21:01 +01:00
}
2010-08-04 14:39:45 +02:00
if ( ! movementInfo . pos . IsPositionValid ())
2009-08-24 19:33:34 -05:00
{
2012-08-07 13:44:22 -05:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "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
2008-10-02 16:23:55 -05:00
/* handle special cases */
2012-07-14 23:39:12 +02:00
if ( movementInfo . t_guid )
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)
2010-08-04 14:39:45 +02:00
if ( movementInfo . t_pos . GetPositionX () > 50 || movementInfo . t_pos . GetPositionY () > 50 || movementInfo . t_pos . GetPositionZ () > 50 )
2009-08-24 19:33:34 -05:00
{
2012-07-17 19:29:18 +02:00
recvPacket . rfinish (); // 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
2010-08-04 14:39:45 +02:00
if ( ! Trinity :: IsValidMapCoord ( movementInfo . pos . GetPositionX () + movementInfo . t_pos . GetPositionX (), movementInfo . pos . GetPositionY () + movementInfo . t_pos . GetPositionY (),
movementInfo . pos . GetPositionZ () + movementInfo . t_pos . GetPositionZ (), movementInfo . pos . GetOrientation () + movementInfo . t_pos . GetOrientation ()))
2009-08-24 19:33:34 -05:00
{
2012-07-17 19:29:18 +02:00
recvPacket . rfinish (); // 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
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
{
2012-06-02 18:38:02 +02:00
// elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list
for ( MapManager :: TransportSet :: const_iterator iter = sMapMgr -> m_Transports . begin (); iter != sMapMgr -> m_Transports . end (); ++ iter )
2008-10-02 16:23:55 -05:00
{
2012-06-02 18:38:02 +02:00
if (( * iter ) -> GetGUID () == movementInfo . t_guid )
{
plrMover -> m_transport = * iter ;
( * iter ) -> AddPassenger ( plrMover );
break ;
}
}
}
else if ( plrMover -> GetTransport () -> GetGUID () != movementInfo . t_guid )
{
bool foundNewTransport = false ;
plrMover -> m_transport -> RemovePassenger ( plrMover );
for ( MapManager :: TransportSet :: const_iterator iter = sMapMgr -> m_Transports . begin (); iter != sMapMgr -> m_Transports . end (); ++ iter )
{
if (( * iter ) -> GetGUID () == movementInfo . t_guid )
{
foundNewTransport = true ;
plrMover -> m_transport = * iter ;
( * iter ) -> AddPassenger ( plrMover );
break ;
}
}
if ( ! foundNewTransport )
{
plrMover -> m_transport = NULL ;
movementInfo . t_pos . Relocate ( 0.0f , 0.0f , 0.0f , 0.0f );
movementInfo . t_time = 0 ;
movementInfo . t_seat = - 1 ;
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
{
2011-09-15 14:08:17 +02:00
GameObject * go = mover -> GetMap () -> GetGameObject ( movementInfo . t_guid );
2010-01-13 18:25:46 +01:00
if ( ! go || go -> GetGoType () != GAMEOBJECT_TYPE_TRANSPORT )
2012-07-14 23:39:12 +02:00
movementInfo . t_guid = 0 ;
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
2008-10-02 16:23:55 -05:00
{
2012-05-30 08:01:02 +02:00
plrMover -> m_transport -> RemovePassenger ( plrMover );
plrMover -> m_transport = NULL ;
2010-08-04 14:39:45 +02:00
movementInfo . t_pos . Relocate ( 0.0f , 0.0f , 0.0f , 0.0f );
2008-10-02 16:23:55 -05:00
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).
2012-05-30 08:01:02 +02:00
if ( opcode == MSG_MOVE_FALL_LAND && plrMover && ! plrMover -> isInFlight ())
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
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 */
2012-07-17 19:29:18 +02:00
WorldPacket data ( SMSG_PLAYER_MOVE , recvPacket . size ());
2009-12-17 11:31:44 +01:00
movementInfo . time = getMSTime ();
movementInfo . guid = mover -> GetGUID ();
2011-11-29 17:56:00 +01:00
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 ())
{
2010-08-04 14:39:45 +02:00
mover -> SetOrientation ( movementInfo . pos . GetOrientation ());
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
2012-05-30 08:01:02 +02:00
if ( plrMover ) // nothing is charmed, or player charmed
2008-12-24 09:58:26 -06:00
{
2012-05-30 08:01:02 +02:00
plrMover -> UpdateFallInformationIfNeed ( movementInfo , opcode );
2012-11-07 23:21:19 +01:00
2012-09-26 12:10:23 -05:00
AreaTableEntry const * zone = GetAreaEntryByAreaID ( plrMover -> GetAreaId ());
float depth = zone ? zone -> MaxDepth : - 500.0f ;
if ( movementInfo . pos . GetPositionZ () < depth )
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
// TODO: discard movement packets after the player is rooted
2012-05-30 08:01:02 +02:00
if ( plrMover -> isAlive ())
2009-03-24 17:42:22 -06:00
{
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
2012-05-30 08:01:02 +02:00
if ( ! plrMover -> isAlive ())
plrMover -> KillPlayer ();
2009-03-24 17:42:22 -06:00
}
}
}
}
2008-11-05 20:51:05 -06:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleForceSpeedChangeAck ( WorldPacket & recvData )
2008-10-02 16:23:55 -05:00
{
2012-08-05 19:40:30 -05:00
uint32 opcode = recvData . GetOpcode ();
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
2012-08-05 19:40:30 -05:00
recvData . readPackGUID ( guid );
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
{
2012-08-05 19:40:30 -05:00
recvData . rfinish (); // 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
2012-08-05 19:40:30 -05:00
recvData >> 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 ;
2012-08-05 19:40:30 -05:00
ReadMovementInfo ( recvData , & movementInfo );
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> newspeed ;
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 ;
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
2011-09-29 12:43:05 +02:00
switch ( opcode )
2008-10-02 16:23:55 -05:00
{
2012-07-04 18:24:05 +02:00
//case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break;
//case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break;
//case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break;
//case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break;
//case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break;
//case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break;
//case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break;
//case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break;
//case CMSG_MOVE_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 :
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "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
// 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
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value" ,
2012-10-24 13:29:34 +02:00
move_type_name [ move_type ], _player -> GetName (). c_str (), _player -> GetSpeed ( move_type ), newspeed );
2011-04-29 20:47:02 +02:00
_player -> SetSpeed ( move_type , _player -> GetSpeedRate ( move_type ), true );
2008-10-02 16:23:55 -05:00
}
else // must be lesser - cheating
{
2012-08-03 14:20:18 +02:00
sLog -> outDebug ( LOG_FILTER_GENERAL , "Player %s from account id %u kicked for incorrect speed (must be %f instead %f)" ,
2012-10-24 13:29:34 +02:00
_player -> GetName (). c_str (), _player -> GetSession () -> GetAccountId (), _player -> GetSpeed ( move_type ), newspeed );
2008-10-02 16:23:55 -05:00
_player -> GetSession () -> KickPlayer ();
}
}
}
2009-10-17 15:51:44 -07:00
2012-07-19 01:21:41 +02:00
void WorldSession :: HandleSetActiveMoverOpcode ( WorldPacket & recvPacket )
2008-10-02 16:23:55 -05:00
{
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "WORLD: Recvd CMSG_SET_ACTIVE_MOVER" );
2009-10-17 15:51:44 -07:00
2012-07-19 01:21:41 +02:00
ObjectGuid guid ;
guid [ 7 ] = recvPacket . ReadBit ();
guid [ 2 ] = recvPacket . ReadBit ();
guid [ 1 ] = recvPacket . ReadBit ();
guid [ 0 ] = recvPacket . ReadBit ();
guid [ 4 ] = recvPacket . ReadBit ();
guid [ 5 ] = recvPacket . ReadBit ();
guid [ 6 ] = recvPacket . ReadBit ();
guid [ 3 ] = recvPacket . ReadBit ();
recvPacket . ReadByteSeq ( guid [ 3 ]);
recvPacket . ReadByteSeq ( guid [ 2 ]);
recvPacket . ReadByteSeq ( guid [ 4 ]);
recvPacket . ReadByteSeq ( guid [ 0 ]);
recvPacket . ReadByteSeq ( guid [ 5 ]);
recvPacket . ReadByteSeq ( guid [ 1 ]);
recvPacket . ReadByteSeq ( guid [ 6 ]);
recvPacket . ReadByteSeq ( guid [ 7 ]);
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetPlayer () -> IsInWorld ())
2008-12-24 09:58:26 -06:00
{
2012-01-05 18:34:56 -03:00
if ( _player -> m_mover -> GetGUID () != guid )
2012-08-11 17:02:05 +02:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD , uint64 ( guid ), GetLogNameForGuid ( guid ), GUID_ENPART ( guid ), _player -> m_mover -> GetGUID ());
2008-12-24 09:58:26 -06:00
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleMoveNotActiveMover ( WorldPacket & recvData )
2008-11-07 16:49:42 -06:00
{
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "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 ;
2012-08-05 19:40:30 -05:00
recvData . readPackGUID ( old_mover_guid );
2009-10-17 15:51:44 -07:00
2009-12-17 11:31:44 +01:00
MovementInfo mi ;
2012-08-05 19:40:30 -05:00
ReadMovementInfo ( recvData , & mi );
2009-12-18 13:41:30 -08:00
2012-05-30 08:01:02 +02:00
mi . guid = old_mover_guid ;
2009-12-17 11:31:44 +01:00
_player -> m_movementInfo = mi ;
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleMountSpecialAnimOpcode ( WorldPacket & /*recvData*/ )
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
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleMoveKnockBackAck ( WorldPacket & recvData )
2008-10-02 16:23:55 -05:00
{
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "CMSG_MOVE_KNOCK_BACK_ACK" );
2009-10-17 15:51:44 -07:00
2011-09-30 18:24:12 +02:00
uint64 guid ;
2012-08-05 19:40:30 -05:00
recvData . readPackGUID ( guid );
2009-12-17 11:31:44 +01:00
2011-09-30 18:24:12 +02:00
if ( _player -> m_mover -> GetGUID () != guid )
return ;
2012-08-05 19:40:30 -05:00
recvData . read_skip < uint32 > (); // unk
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
MovementInfo movementInfo ;
2012-08-05 19:40:30 -05:00
ReadMovementInfo ( recvData , & movementInfo );
2012-05-30 08:01:02 +02:00
2011-09-30 18:24:12 +02:00
_player -> m_movementInfo = movementInfo ;
2012-01-19 20:11:32 +01:00
WorldPacket data ( SMSG_MOVE_UPDATE_KNOCK_BACK , 66 );
2011-09-30 18:24:12 +02:00
data . appendPackGUID ( guid );
_player -> BuildMovementPacket ( & data );
// knockback specific info
data << movementInfo . j_sinAngle ;
data << movementInfo . j_cosAngle ;
data << movementInfo . j_xyspeed ;
data << movementInfo . j_zspeed ;
_player -> SendMessageToSet ( & data , false );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleMoveHoverAck ( WorldPacket & recvData )
2008-10-02 16:23:55 -05:00
{
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "CMSG_MOVE_HOVER_ACK" );
2009-10-17 15:51:44 -07:00
2009-12-17 11:31:44 +01:00
uint64 guid ; // guid - unused
2012-08-05 19:40:30 -05:00
recvData . readPackGUID ( guid );
2009-12-17 11:31:44 +01:00
2012-08-05 19:40:30 -05:00
recvData . read_skip < uint32 > (); // unk
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
MovementInfo movementInfo ;
2012-08-05 19:40:30 -05:00
ReadMovementInfo ( recvData , & movementInfo );
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData . read_skip < uint32 > (); // unk2
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleMoveWaterWalkAck ( WorldPacket & recvData )
2008-10-02 16:23:55 -05:00
{
2011-02-20 20:16:34 +01:00
sLog -> outDebug ( LOG_FILTER_NETWORKIO , "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
2012-08-05 19:40:30 -05:00
recvData . readPackGUID ( guid );
2009-12-17 11:31:44 +01:00
2012-08-05 19:40:30 -05:00
recvData . read_skip < uint32 > (); // unk
2009-10-17 15:51:44 -07:00
2009-08-27 20:14:50 -05:00
MovementInfo movementInfo ;
2012-08-05 19:40:30 -05:00
ReadMovementInfo ( recvData , & movementInfo );
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData . read_skip < uint32 > (); // unk2
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleSummonResponseOpcode ( WorldPacket & recvData )
2008-10-02 16:23:55 -05:00
{
2010-04-07 22:59:46 +02:00
if ( ! _player -> isAlive () || _player -> isInCombat ())
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-01-14 19:27:14 +00:00
uint64 summonerGuid ;
2008-10-02 16:23:55 -05:00
bool agree ;
2012-08-05 19:40:30 -05:00
recvData >> summonerGuid ;
recvData >> 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
2012-07-14 23:39:12 +02:00
void WorldSession :: ReadMovementInfo ( WorldPacket & data , MovementInfo * mi )
2011-11-29 17:56:00 +01:00
{
2012-07-14 23:39:12 +02:00
bool hasMovementFlags = false ;
bool hasMovementFlags2 = false ;
bool hasTimestamp = false ;
bool hasOrientation = false ;
bool hasTransportData = false ;
bool hasTransportTime2 = false ;
bool hasTransportTime3 = false ;
bool hasPitch = false ;
bool hasFallData = false ;
bool hasFallDirection = false ;
bool hasSplineElevation = false ;
bool hasSpline = false ;
MovementStatusElements * sequence = GetMovementStatusElementsSequence ( data . GetOpcode ());
if ( sequence == NULL )
{
2012-08-07 13:44:22 -05:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "WorldSession::ReadMovementInfo: No movement sequence found for opcode 0x%04X" , uint32 ( data . GetOpcode ()));
2012-07-14 23:39:12 +02:00
return ;
}
ObjectGuid guid ;
ObjectGuid tguid ;
for ( uint32 i = 0 ; i < MSE_COUNT ; ++ i )
{
MovementStatusElements element = sequence [ i ];
if ( element == MSEEnd )
break ;
if ( element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7 )
{
guid [ element - MSEHasGuidByte0 ] = data . ReadBit ();
continue ;
}
if ( element >= MSEHasTransportGuidByte0 &&
element <= MSEHasTransportGuidByte7 )
{
if ( hasTransportData )
tguid [ element - MSEHasTransportGuidByte0 ] = data . ReadBit ();
continue ;
}
if ( element >= MSEGuidByte0 && element <= MSEGuidByte7 )
{
data . ReadByteSeq ( guid [ element - MSEGuidByte0 ]);
continue ;
}
if ( element >= MSETransportGuidByte0 &&
element <= MSETransportGuidByte7 )
{
if ( hasTransportData )
data . ReadByteSeq ( tguid [ element - MSETransportGuidByte0 ]);
continue ;
}
switch ( element )
{
case MSEHasMovementFlags :
hasMovementFlags = ! data . ReadBit ();
break ;
case MSEHasMovementFlags2 :
hasMovementFlags2 = ! data . ReadBit ();
break ;
case MSEHasTimestamp :
hasTimestamp = ! data . ReadBit ();
break ;
case MSEHasOrientation :
hasOrientation = ! data . ReadBit ();
break ;
case MSEHasTransportData :
hasTransportData = data . ReadBit ();
break ;
case MSEHasTransportTime2 :
if ( hasTransportData )
hasTransportTime2 = data . ReadBit ();
break ;
case MSEHasTransportTime3 :
if ( hasTransportData )
hasTransportTime3 = data . ReadBit ();
break ;
case MSEHasPitch :
hasPitch = ! data . ReadBit ();
break ;
case MSEHasFallData :
hasFallData = data . ReadBit ();
break ;
case MSEHasFallDirection :
if ( hasFallData )
hasFallDirection = data . ReadBit ();
break ;
2012-07-16 19:17:16 +02:00
case MSEHasSplineElevation :
2012-07-14 23:39:12 +02:00
hasSplineElevation = ! data . ReadBit ();
break ;
case MSEHasSpline :
hasSpline = data . ReadBit ();
break ;
case MSEMovementFlags :
if ( hasMovementFlags )
mi -> flags = data . ReadBits ( 30 );
break ;
case MSEMovementFlags2 :
if ( hasMovementFlags2 )
mi -> flags2 = data . ReadBits ( 12 );
break ;
case MSETimestamp :
if ( hasTimestamp )
data >> mi -> time ;
break ;
case MSEPositionX :
data >> mi -> pos . m_positionX ;
break ;
case MSEPositionY :
data >> mi -> pos . m_positionY ;
break ;
case MSEPositionZ :
data >> mi -> pos . m_positionZ ;
break ;
case MSEOrientation :
if ( hasOrientation )
2012-08-20 10:44:14 +02:00
mi -> pos . SetOrientation ( data . read < float > ());
2012-07-14 23:39:12 +02:00
break ;
case MSETransportPositionX :
if ( hasTransportData )
data >> mi -> t_pos . m_positionX ;
break ;
case MSETransportPositionY :
if ( hasTransportData )
data >> mi -> t_pos . m_positionY ;
break ;
case MSETransportPositionZ :
if ( hasTransportData )
data >> mi -> t_pos . m_positionZ ;
break ;
case MSETransportOrientation :
if ( hasTransportData )
2012-08-20 10:44:14 +02:00
mi -> pos . SetOrientation ( data . read < float > ());
2012-07-14 23:39:12 +02:00
break ;
case MSETransportSeat :
if ( hasTransportData )
data >> mi -> t_seat ;
break ;
case MSETransportTime :
if ( hasTransportData )
data >> mi -> t_time ;
break ;
case MSETransportTime2 :
if ( hasTransportData && hasTransportTime2 )
data >> mi -> t_time2 ;
break ;
case MSETransportTime3 :
if ( hasTransportData && hasTransportTime3 )
data >> mi -> t_time3 ;
break ;
case MSEPitch :
if ( hasPitch )
data >> mi -> pitch ;
break ;
case MSEFallTime :
if ( hasFallData )
data >> mi -> fallTime ;
break ;
case MSEFallVerticalSpeed :
if ( hasFallData )
data >> mi -> j_zspeed ;
break ;
case MSEFallCosAngle :
2012-07-24 13:35:00 +03:00
if ( hasFallData && hasFallDirection )
2012-07-14 23:39:12 +02:00
data >> mi -> j_cosAngle ;
break ;
case MSEFallSinAngle :
2012-07-24 13:35:00 +03:00
if ( hasFallData && hasFallDirection )
2012-07-14 23:39:12 +02:00
data >> mi -> j_sinAngle ;
break ;
case MSEFallHorizontalSpeed :
2012-07-24 13:35:00 +03:00
if ( hasFallData && hasFallDirection )
2012-07-14 23:39:12 +02:00
data >> mi -> j_xyspeed ;
break ;
2012-07-15 00:45:06 +02:00
case MSESplineElevation :
2012-07-14 23:39:12 +02:00
if ( hasSplineElevation )
data >> mi -> splineElevation ;
break ;
case MSEZeroBit :
case MSEOneBit :
data . ReadBit ();
break ;
default :
ASSERT ( false && "Incorrect sequence element detected at ReadMovementInfo" );
break ;
}
}
mi -> guid = guid ;
mi -> t_guid = tguid ;
if ( hasTransportData && mi -> pos . m_positionX != mi -> t_pos . m_positionX )
2011-11-29 17:56:00 +01:00
if ( GetPlayer () -> GetTransport ())
GetPlayer () -> GetTransport () -> UpdatePosition ( mi );
2012-05-30 08:01:02 +02:00
//! Anti-cheat checks. Please keep them in seperate if() blocks to maintain a clear overview.
//! Might be subject to latency, so just remove improper flags.
#ifdef TRINITY_DEBUG
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
{ \
if (check) \
{ \
sLog->outDebug(LOG_FILTER_UNITS, "WorldSession::ReadMovementInfo: Violation of MovementFlags found (%s). " \
"MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUIDLow(), maskToRemove); \
mi->RemoveMovementFlag((maskToRemove)); \
} \
}
#else
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
if (check) \
mi->RemoveMovementFlag((maskToRemove));
#endif
/*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
It will freeze clients that receive this player's movement info.
*/
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_ROOT ),
MOVEMENTFLAG_ROOT );
//! Cannot hover without SPELL_AURA_HOVER
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_HOVER ) && ! GetPlayer () -> HasAuraType ( SPELL_AURA_HOVER ),
MOVEMENTFLAG_HOVER );
//! Cannot ascend and descend at the same time
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_ASCENDING ) && mi -> HasMovementFlag ( MOVEMENTFLAG_DESCENDING ),
MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING );
//! Cannot move left and right at the same time
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_LEFT ) && mi -> HasMovementFlag ( MOVEMENTFLAG_RIGHT ),
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT );
//! Cannot strafe left and right at the same time
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_STRAFE_LEFT ) && mi -> HasMovementFlag ( MOVEMENTFLAG_STRAFE_RIGHT ),
MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT );
//! Cannot pitch up and down at the same time
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_PITCH_UP ) && mi -> HasMovementFlag ( MOVEMENTFLAG_PITCH_DOWN ),
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN );
//! Cannot move forwards and backwards at the same time
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_FORWARD ) && mi -> HasMovementFlag ( MOVEMENTFLAG_BACKWARD ),
MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD );
//! Cannot walk on water without SPELL_AURA_WATER_WALK
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_WATERWALKING ) && ! GetPlayer () -> HasAuraType ( SPELL_AURA_WATER_WALK ),
MOVEMENTFLAG_WATERWALKING );
//! Cannot feather fall without SPELL_AURA_FEATHER_FALL
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_FALLING_SLOW ) && ! GetPlayer () -> HasAuraType ( SPELL_AURA_FEATHER_FALL ),
MOVEMENTFLAG_FALLING_SLOW );
/*! Cannot fly if no fly auras present. Exception is being a GM.
Note that we check for account level instead of Player::IsGameMaster() because in some
situations it may be feasable to use .gm fly on as a GM without having .gm on,
e.g. aerial combat.
*/
REMOVE_VIOLATING_FLAGS ( mi -> HasMovementFlag ( MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY ) && GetSecurity () == SEC_PLAYER &&
! GetPlayer () -> m_mover -> HasAuraType ( SPELL_AURA_FLY ) &&
! GetPlayer () -> m_mover -> HasAuraType ( SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED ),
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY );
#undef REMOVE_VIOLATING_FLAGS
2011-11-29 17:56:00 +01:00
}
void WorldSession :: WriteMovementInfo ( WorldPacket & data , MovementInfo * mi )
{
2012-07-14 23:39:12 +02:00
bool hasMovementFlags = mi -> GetMovementFlags () != 0 ;
bool hasMovementFlags2 = mi -> GetExtraMovementFlags () != 0 ;
bool hasTimestamp = mi -> time != 0 ;
bool hasOrientation = ! G3D :: fuzzyEq ( mi -> pos . GetOrientation (), 0.0f );
bool hasTransportData = mi -> t_guid != 0 ;
bool hasTransportTime2 = mi -> HasExtraMovementFlag ( MOVEMENTFLAG2_INTERPOLATED_MOVEMENT );
bool hasTransportTime3 = false ;
bool hasPitch = mi -> HasMovementFlag ( MovementFlags ( MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING )) || mi -> HasExtraMovementFlag ( MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING );
bool hasFallData = mi -> HasExtraMovementFlag ( MOVEMENTFLAG2_INTERPOLATED_TURNING );
bool hasFallDirection = mi -> HasMovementFlag ( MOVEMENTFLAG_FALLING );
bool hasSplineElevation = mi -> HasMovementFlag ( MOVEMENTFLAG_SPLINE_ELEVATION );
bool hasSpline = false ;
MovementStatusElements * sequence = GetMovementStatusElementsSequence ( data . GetOpcode ());
if ( ! sequence )
{
2012-08-07 13:44:22 -05:00
sLog -> outError ( LOG_FILTER_NETWORKIO , "WorldSession::WriteMovementInfo: No movement sequence found for opcode 0x%04X" , uint32 ( data . GetOpcode ()));
2012-07-14 23:39:12 +02:00
return ;
}
ObjectGuid guid = mi -> guid ;
ObjectGuid tguid = mi -> t_guid ;
for ( uint32 i = 0 ; i < MSE_COUNT ; ++ i )
{
MovementStatusElements element = sequence [ i ];
2012-07-15 00:45:06 +02:00
if ( element == MSEEnd )
break ;
2012-07-14 23:39:12 +02:00
if ( element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7 )
{
data . WriteBit ( guid [ element - MSEHasGuidByte0 ]);
continue ;
}
if ( element >= MSEHasTransportGuidByte0 &&
element <= MSEHasTransportGuidByte7 )
{
if ( hasTransportData )
data . WriteBit ( tguid [ element - MSEHasTransportGuidByte0 ]);
continue ;
}
if ( element >= MSEGuidByte0 && element <= MSEGuidByte7 )
{
data . WriteByteSeq ( guid [ element - MSEGuidByte0 ]);
continue ;
}
if ( element >= MSETransportGuidByte0 &&
element <= MSETransportGuidByte7 )
{
if ( hasTransportData )
data . WriteByteSeq ( tguid [ element - MSETransportGuidByte0 ]);
continue ;
}
switch ( element )
{
case MSEHasMovementFlags :
data . WriteBit ( ! hasMovementFlags );
break ;
case MSEHasMovementFlags2 :
data . WriteBit ( ! hasMovementFlags2 );
break ;
case MSEHasTimestamp :
data . WriteBit ( ! hasTimestamp );
break ;
case MSEHasOrientation :
data . WriteBit ( ! hasOrientation );
break ;
case MSEHasTransportData :
data . WriteBit ( hasTransportData );
break ;
case MSEHasTransportTime2 :
if ( hasTransportData )
data . WriteBit ( hasTransportTime2 );
break ;
case MSEHasTransportTime3 :
if ( hasTransportData )
data . WriteBit ( hasTransportTime3 );
break ;
case MSEHasPitch :
data . WriteBit ( ! hasPitch );
break ;
case MSEHasFallData :
data . WriteBit ( hasFallData );
break ;
case MSEHasFallDirection :
if ( hasFallData )
data . WriteBit ( hasFallDirection );
break ;
2012-07-16 19:17:16 +02:00
case MSEHasSplineElevation :
2012-07-14 23:39:12 +02:00
data . WriteBit ( ! hasSplineElevation );
break ;
case MSEHasSpline :
data . WriteBit ( hasSpline );
break ;
case MSEMovementFlags :
if ( hasMovementFlags )
data . WriteBits ( mi -> flags , 30 );
break ;
case MSEMovementFlags2 :
if ( hasMovementFlags2 )
data . WriteBits ( mi -> flags2 , 12 );
break ;
case MSETimestamp :
if ( hasTimestamp )
data << mi -> time ;
break ;
case MSEPositionX :
data << mi -> pos . m_positionX ;
break ;
case MSEPositionY :
data << mi -> pos . m_positionY ;
break ;
case MSEPositionZ :
data << mi -> pos . m_positionZ ;
break ;
case MSEOrientation :
if ( hasOrientation )
2012-08-20 10:44:14 +02:00
data << mi -> pos . GetOrientation ();
2012-07-14 23:39:12 +02:00
break ;
case MSETransportPositionX :
if ( hasTransportData )
data << mi -> t_pos . m_positionX ;
break ;
case MSETransportPositionY :
if ( hasTransportData )
data << mi -> t_pos . m_positionY ;
break ;
case MSETransportPositionZ :
if ( hasTransportData )
data << mi -> t_pos . m_positionZ ;
break ;
case MSETransportOrientation :
if ( hasTransportData )
2012-08-20 10:44:14 +02:00
data << mi -> t_pos . GetOrientation ();
2012-07-14 23:39:12 +02:00
break ;
case MSETransportSeat :
if ( hasTransportData )
data << mi -> t_seat ;
break ;
case MSETransportTime :
if ( hasTransportData )
data << mi -> t_time ;
break ;
case MSETransportTime2 :
if ( hasTransportData && hasTransportTime2 )
data << mi -> t_time2 ;
break ;
case MSETransportTime3 :
if ( hasTransportData && hasTransportTime3 )
data << mi -> t_time3 ;
break ;
case MSEPitch :
if ( hasPitch )
data << mi -> pitch ;
break ;
case MSEFallTime :
if ( hasFallData )
data << mi -> fallTime ;
break ;
case MSEFallVerticalSpeed :
if ( hasFallData )
data << mi -> j_zspeed ;
break ;
case MSEFallCosAngle :
2012-07-24 13:35:00 +03:00
if ( hasFallData && hasFallDirection )
2012-07-14 23:39:12 +02:00
data << mi -> j_cosAngle ;
break ;
case MSEFallSinAngle :
2012-07-24 13:35:00 +03:00
if ( hasFallData && hasFallDirection )
2012-07-14 23:39:12 +02:00
data << mi -> j_sinAngle ;
break ;
case MSEFallHorizontalSpeed :
2012-07-24 13:35:00 +03:00
if ( hasFallData && hasFallDirection )
2012-07-14 23:39:12 +02:00
data << mi -> j_xyspeed ;
break ;
2012-07-15 00:45:06 +02:00
case MSESplineElevation :
2012-07-14 23:39:12 +02:00
if ( hasSplineElevation )
data << mi -> splineElevation ;
break ;
case MSEZeroBit :
data . WriteBit ( 0 );
break ;
case MSEOneBit :
data . WriteBit ( 1 );
break ;
default :
ASSERT ( false && "Incorrect sequence element detected at ReadMovementInfo" );
break ;
}
}
2012-07-04 22:20:21 +02:00
}