aboutsummaryrefslogtreecommitdiff
path: root/src/game/MovementHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/MovementHandler.cpp')
-rw-r--r--src/game/MovementHandler.cpp510
1 files changed, 251 insertions, 259 deletions
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
index 2eb3bab12e7..7d7733763cd 100644
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
* 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
@@ -23,14 +23,16 @@
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
-#include "World.h"
#include "Corpse.h"
#include "Player.h"
+#include "Vehicle.h"
+#include "SpellAuras.h"
#include "MapManager.h"
#include "Transports.h"
#include "BattleGround.h"
#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
+#include "ObjectMgr.h"
void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ )
{
@@ -40,11 +42,15 @@ void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ )
void WorldSession::HandleMoveWorldportAckOpcode()
{
+ // ignore unexpected far teleports
+ if(!GetPlayer()->IsBeingTeleportedFar())
+ return;
+
// get the teleport destination
WorldLocation &loc = GetPlayer()->GetTeleportDest();
// possible errors in the coordinate validity check
- if(!MapManager::IsValidMapCoord(loc.mapid,loc.x,loc.y,loc.z,loc.o))
+ if(!MapManager::IsValidMapCoord(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation))
{
LogoutPlayer(false);
return;
@@ -58,44 +64,60 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if(GetPlayer()->m_InstanceValid == false && !mInstance)
GetPlayer()->m_InstanceValid = true;
- GetPlayer()->SetSemaphoreTeleport(false);
+ GetPlayer()->SetSemaphoreTeleportFar(false);
// relocate the player to the teleport destination
GetPlayer()->SetMapId(loc.mapid);
- GetPlayer()->Relocate(loc.x, loc.y, loc.z, loc.o);
+ GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation);
// since the MapId is set before the GetInstance call, the InstanceId must be set to 0
// to let GetInstance() determine the proper InstanceId based on the player's binds
GetPlayer()->SetInstanceId(0);
- // check this before Map::Add(player), because that will create the instance save!
- bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty()) == NULL);
-
GetPlayer()->SendInitialPacketsBeforeAddToMap();
// the CanEnter checks are done in TeleporTo but conditions may change
// while the player is in transit, for example the map may get full
if(!GetPlayer()->GetMap()->Add(GetPlayer()))
{
- sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o);
+ sLog.outDebug("WORLD: teleport of player %s (%d) to location %d, %f, %f, %f, %f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation);
// teleport the player home
- GetPlayer()->SetDontMove(false);
if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()))
{
// the player must always be able to teleport home
- sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d,%f,%f,%f,%f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
+ sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d, %f, %f, %f, %f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
assert(false);
}
return;
}
+
+ // battleground state prepare (in case join to BG), at relogin/tele player not invited
+ // only add to bg group and object, if the player was invited (else he entered through command)
+ if(_player->InBattleGround())
+ {
+ // cleanup setting if outdated
+ if(!mEntry->IsBattleGroundOrArena())
+ {
+ // We're not in BG
+ _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE);
+ // reset destination bg team
+ _player->SetBGTeam(0);
+ }
+ // join to bg case
+ else if(BattleGround *bg = _player->GetBattleGround())
+ {
+ if(_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId()))
+ bg->AddPlayer(_player);
+ }
+ }
+
GetPlayer()->SendInitialPacketsAfterAddToMap();
// flight fast teleport case
- if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE)
+ if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
{
if(!_player->InBattleGround())
{
// short preparations to continue flight
- GetPlayer()->SetDontMove(false);
FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
flight->Initialize(*GetPlayer());
return;
@@ -118,124 +140,85 @@ void WorldSession::HandleMoveWorldportAckOpcode()
}
}
- if(mEntry->IsRaid() && mInstance)
+ if((mEntry->IsRaid() || (mEntry->IsNonRaidDungeon() && mEntry->SupportsHeroicMode() && GetPlayer()->IsHeroic())) && mInstance)
{
- if(reset_notify)
- {
- uint32 timeleft = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL);
- GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), timeleft); // greeting at the entrance of the resort raid instance
- }
+ uint32 timeleft = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL);
+ GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty(), timeleft);
}
// mount allow check
if(!mEntry->IsMountAllowed())
- _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
-
- // battleground state prepare
- // only add to bg group and object, if the player was invited (else he entered through command)
- if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId()))
- {
- BattleGround *bg = _player->GetBattleGround();
- if(bg)
- {
- bg->AddPlayer(_player);
- if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg
- {
- // get the team this way, because arenas might 'override' the teams.
- uint32 team = bg->GetPlayerTeam(_player->GetGUID());
- if(!team)
- team = _player->GetTeam();
- if(!bg->GetBgRaid(team)) // first player joined
- {
- Group *group = new Group;
- bg->SetBgRaid(team, group);
- group->Create(_player->GetGUIDLow(), _player->GetName());
- }
- else // raid already exist
- {
- bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName());
- }
- }
- }
- }
+ _player->RemoveAurasByType(SPELL_AURA_MOUNTED);
// honorless target
if(GetPlayer()->pvpInfo.inHostileArea)
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
// resummon pet
- if(GetPlayer()->m_temporaryUnsummonedPetNumber)
- {
- Pet* NewPet = new Pet;
- if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true))
- delete NewPet;
-
- GetPlayer()->m_temporaryUnsummonedPetNumber = 0;
- }
-
- GetPlayer()->SetDontMove(false);
+ GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
}
-void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
+void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
{
- CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4);
+ CHECK_PACKET_SIZE(recv_data, 8+4);
- /* extract packet */
- MovementInfo movementInfo;
- uint32 MovementFlags;
+ sLog.outDebug("MSG_MOVE_TELEPORT_ACK");
+ uint64 guid;
+ uint32 flags, time;
- recv_data >> MovementFlags;
- recv_data >> movementInfo.unk1;
- recv_data >> movementInfo.time;
- recv_data >> movementInfo.x;
- recv_data >> movementInfo.y;
- recv_data >> movementInfo.z;
- recv_data >> movementInfo.o;
+ recv_data >> guid;
+ recv_data >> flags >> time;
+ DEBUG_LOG("Guid " UI64FMTD, guid);
+ DEBUG_LOG("Flags %u, time %u", flags, time/IN_MILISECONDS);
- if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4);
-
- recv_data >> movementInfo.t_guid;
- recv_data >> movementInfo.t_x;
- recv_data >> movementInfo.t_y;
- recv_data >> movementInfo.t_z;
- recv_data >> movementInfo.t_o;
- recv_data >> movementInfo.t_time;
- }
+ Unit *mover = _player->m_mover;
+ Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
- if(MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
+ if(!plMover || !plMover->IsBeingTeleportedNear())
+ return;
- recv_data >> movementInfo.s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up
- }
+ if(guid != plMover->GetGUID())
+ return;
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
+ plMover->SetSemaphoreTeleportNear(false);
- recv_data >> movementInfo.fallTime; // duration of last jump (when in jump duration from jump begin to now)
+ uint32 old_zone = plMover->GetZoneId();
- if(MovementFlags & MOVEMENTFLAG_JUMPING)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4);
+ WorldLocation const& dest = plMover->GetTeleportDest();
- recv_data >> movementInfo.j_unk; // constant, but different when jumping in water and on land?
- recv_data >> movementInfo.j_sinAngle; // sin of angle between orientation0 and players orientation
- recv_data >> movementInfo.j_cosAngle; // cos of angle between orientation0 and players orientation
- recv_data >> movementInfo.j_xyspeed; // speed of xy movement
- }
+ plMover->SetPosition(dest.coord_x, dest.coord_y, dest.coord_z, dest.orientation, true);
- if(MovementFlags & MOVEMENTFLAG_SPLINE)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
+ uint32 newzone, newarea;
+ plMover->GetZoneAndAreaId(newzone, newarea);
+ plMover->UpdateZone(newzone, newarea);
- recv_data >> movementInfo.u_unk1; // unknown
+ // new zone
+ if(old_zone != newzone)
+ {
+ // honorless target
+ if(plMover->pvpInfo.inHostileArea)
+ plMover->CastSpell(plMover, 2479, true);
}
+
+ // resummon pet
+ GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
+}
+
+void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
+{
+ uint32 opcode = recv_data.GetOpcode();
+ //sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
+
+ Unit *mover = _player->m_mover;
+ Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL;
+
+ // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
+ if(plMover && plMover->IsBeingTeleported())
+ return;
+
+ /* extract packet */
+ MovementInfo movementInfo;
+ ReadMovementInfo(recv_data, &movementInfo);
/*----------------*/
if(recv_data.size() != recv_data.rpos())
@@ -248,168 +231,133 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
return;
- // Handle possessed unit movement separately
- Unit* pos_unit = GetPlayer()->GetCharm();
- if (pos_unit && pos_unit->isPossessed()) // can be charmed but not possessed
- {
- HandlePossessedMovement(recv_data, movementInfo, MovementFlags);
- return;
- }
-
- if (GetPlayer()->GetDontMove())
- return;
-
- //Save movement flags
- GetPlayer()->SetUnitMovementFlags(MovementFlags);
-
/* handle special cases */
- if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
+ if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 )
return;
- if( !Trinity::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y+movementInfo.t_y,
- movementInfo.z+movementInfo.t_z, movementInfo.o+movementInfo.t_o) )
+ if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y,
+ movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o) )
return;
// if we boarded a transport, add us to it
- if (!GetPlayer()->m_transport)
+ if (plMover && !plMover->m_transport)
{
// elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
- for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
+ for (MapManager::TransportSet::const_iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
{
- // unmount before boarding
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
-
- GetPlayer()->m_transport = (*iter);
- (*iter)->AddPassenger(GetPlayer());
+ plMover->m_transport = (*iter);
+ (*iter)->AddPassenger(plMover);
break;
}
}
}
+
+ if(!mover->GetTransport() && !mover->m_Vehicle)
+ movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
}
- else if (GetPlayer()->m_transport) // if we were on a transport, leave
+ else if (plMover && plMover->m_transport) // if we were on a transport, leave
{
- GetPlayer()->m_transport->RemovePassenger(GetPlayer());
- GetPlayer()->m_transport = NULL;
+ plMover->m_transport->RemovePassenger(plMover);
+ plMover->m_transport = NULL;
movementInfo.t_x = 0.0f;
movementInfo.t_y = 0.0f;
movementInfo.t_z = 0.0f;
movementInfo.t_o = 0.0f;
movementInfo.t_time = 0;
+ movementInfo.t_seat = -1;
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
- if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())
- GetPlayer()->HandleFallDamage(movementInfo);
+ if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
+ plMover->HandleFall(movementInfo);
- if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater())
+ if (plMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plMover->IsInWater())
{
// now client not include swimming flag in case jumping under water
- GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
+ plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
}
/*----------------------*/
/* process position-change */
- recv_data.put<uint32>(5, getMSTime()); // offset flags(4) + unk(1)
- WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size()));
- data.append(GetPlayer()->GetPackGUID());
+ recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2)
+ WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size()));
+ data.append(mover->GetPackGUID()); // use mover guid
data.append(recv_data.contents(), recv_data.size());
GetPlayer()->SendMessageToSet(&data, false);
- GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
- GetPlayer()->m_movementInfo = movementInfo;
- if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND)
- GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z);
-
- if(GetPlayer()->isMovingOrTurning())
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- if(movementInfo.z < -500.0f)
- GetPlayer()->HandleFallUnderMap();
-}
-
-void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags)
-{
- // Whatever the client is controlling, it will send the GUID of the original player.
- // If current player is controlling, it must be handled like the controlled player sent these opcodes
-
- Unit* pos_unit = GetPlayer()->GetCharm();
-
- if (pos_unit->GetTypeId() == TYPEID_PLAYER && ((Player*)pos_unit)->GetDontMove())
- return;
-
- //Save movement flags
- pos_unit->SetUnitMovementFlags(MovementFlags);
+ mover->m_movementInfo = movementInfo;
- // Remove possession if possessed unit enters a transport
- if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
+ if(plMover) // nothing is charmed, or player charmed
{
- GetPlayer()->Uncharm();
- return;
- }
-
- recv_data.put<uint32>(5, getMSTime());
- WorldPacket data(recv_data.GetOpcode(), pos_unit->GetPackGUID().size()+recv_data.size());
- data.append(pos_unit->GetPackGUID());
- data.append(recv_data.contents(), recv_data.size());
- // Send the packet to self but not to the possessed player; for creatures the first bool is irrelevant
- pos_unit->SendMessageToSet(&data, true, false);
-
- // Possessed is a player
- if (pos_unit->GetTypeId() == TYPEID_PLAYER)
- {
- Player* plr = (Player*)pos_unit;
-
- if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND)
- plr->HandleFallDamage(movementInfo);
-
- if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != plr->IsInWater())
- {
- // Now client not include swimming flag in case jumping under water
- plr->SetInWater( !plr->IsInWater() || plr->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
- }
-
- plr->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o, false);
- plr->m_movementInfo = movementInfo;
-
- if(plr->isMovingOrTurning())
- plr->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+ plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ plMover->UpdateFallInformationIfNeed(movementInfo, recv_data.GetOpcode());
if(movementInfo.z < -500.0f)
{
- GetPlayer()->Uncharm();
- plr->HandleFallUnderMap();
+ if(plMover->InBattleGround()
+ && plMover->GetBattleGround()
+ && plMover->GetBattleGround()->HandlePlayerUnderMap(_player))
+ {
+ // do nothing, the handle already did if returned true
+ }
+ else
+ {
+ // NOTE: this is actually called many times while falling
+ // even after the player has been teleported away
+ // TODO: discard movement packets after the player is rooted
+ if(plMover->isAlive())
+ {
+ plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
+ // pl can be alive if GM/etc
+ if(!plMover->isAlive())
+ {
+ // change the death state to CORPSE to prevent the death timer from
+ // starting in the next player update
+ plMover->KillPlayer();
+ plMover->BuildPlayerRepop();
+ }
+ }
+
+ // cancel the death timer here if started
+ plMover->RepopAtGraveyard();
+ }
}
}
- else // Possessed unit is a creature
+ else // creature charmed
{
- Map* map = MapManager::Instance().GetMap(pos_unit->GetMapId(), pos_unit);
- map->CreatureRelocation((Creature*)pos_unit, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ uint32 entry = mover->GetEntry();
+ if(mover->m_Vehicle)
+ return;
+ mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+
+ /*if(mover->canFly())
+ {
+ bool flying = mover->IsFlying();
+ if(flying != ((mover->GetByteValue(UNIT_FIELD_BYTES_1, 3) & 0x02) ? true : false))
+ mover->SetFlying(flying);
+ }*/
}
+
+ //sLog.outString("Receive Movement Packet %s:", opcodeTable[recv_data.GetOpcode()]);
+ //mover->OutMovementInfo();
}
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
{
- CHECK_PACKET_SIZE(recv_data, 8+4+4+1+4+4+4+4+4);
+ //sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode());
+
+ CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4);
/* extract packet */
uint64 guid;
- uint8 unkB;
- uint32 unk1, flags, time, fallTime;
- float x, y, z, orientation;
-
- uint64 t_GUID;
- float t_x, t_y, t_z, t_o;
- uint32 t_time;
- float s_pitch;
- float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed;
- float u_unk1;
+ uint32 unk1;
float newspeed;
recv_data >> guid;
@@ -420,47 +368,10 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
// continue parse packet
- recv_data >> unk1;
- recv_data >> flags >> unkB >> time;
- recv_data >> x >> y >> z >> orientation;
- if (flags & MOVEMENTFLAG_ONTRANSPORT)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4);
-
- recv_data >> t_GUID;
- recv_data >> t_x >> t_y >> t_z >> t_o >> t_time;
- }
- if (flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up
- }
-
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now)
-
- if ((flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING))
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4);
+ recv_data >> unk1; // counter or moveEvent
- recv_data >> j_unk1; // ?constant, but different when jumping in water and on land?
- recv_data >> j_sinAngle >> j_cosAngle; // sin + cos of angle between orientation0 and players orientation
- recv_data >> j_xyspeed; // speed of xy movement
- }
-
- if(flags & MOVEMENTFLAG_SPLINE)
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
-
- recv_data >> u_unk1; // unknown
- }
+ MovementInfo movementInfo;
+ ReadMovementInfo(recv_data, &movementInfo);
// recheck
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
@@ -473,7 +384,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
UnitMoveType move_type;
UnitMoveType force_move_type;
- static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack" };
+ static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" };
uint16 opcode = recv_data.GetOpcode();
switch(opcode)
@@ -486,6 +397,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
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;
+ case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break;
default:
sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode);
return;
@@ -521,19 +433,99 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
- CHECK_PACKET_SIZE(recv_data,8);
+ CHECK_PACKET_SIZE(recv_data, 8);
uint64 guid;
recv_data >> guid;
- WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement
- data << uint32(0x00000000); // on blizz it increments periodically
- SendPacket(&data);
+ if(guid == GetPlayer()->m_mover->GetGUID())
+ return;
+
+ if(Unit *mover = ObjectAccessor::GetUnit(*GetPlayer(), guid))
+ GetPlayer()->SetMover(mover);
+ else
+ {
+ sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, guid, _player->m_mover->GetGUID());
+ GetPlayer()->SetMover(GetPlayer());
+ }
}
-void WorldSession::HandleNotActiveMoverOpcode(WorldPacket& /*recv_data*/)
+void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
+
+ CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8);
+
+ uint64 old_mover_guid;
+ recv_data >> old_mover_guid;
+
+ /*if(_player->m_mover->GetGUID() == old_mover_guid)
+ {
+ sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid);
+ return;
+ }*/
+
+ ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);
+}
+
+void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE");
+ recv_data.hexlike();
+
+ uint64 vehicleGUID = _player->GetCharmGUID();
+
+ if(!vehicleGUID) // something wrong here...
+ return;
+
+ ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);
+ _player->ExitVehicle();
+}
+
+void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
+ recv_data.hexlike();
+
+ if(!GetPlayer()->m_Vehicle)
+ return;
+
+ if(recv_data.GetOpcode() == CMSG_REQUEST_VEHICLE_PREV_SEAT)
+ {
+ GetPlayer()->ChangeSeat(-1, false);
+ return;
+ }
+ else if(recv_data.GetOpcode() == CMSG_REQUEST_VEHICLE_NEXT_SEAT)
+ {
+ GetPlayer()->ChangeSeat(-1, true);
+ return;
+ }
+ else if(recv_data.GetOpcode() == CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE)
+ ReadMovementInfo(recv_data, &GetPlayer()->m_Vehicle->m_movementInfo);
+
+ CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1);
+ uint64 guid;
+ if(!recv_data.readPackGUID(guid))
+ return;
+
+ CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1);
+ int8 seatId;
+ recv_data >> seatId;
+
+ if(!guid)
+ GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next
+ else if(Vehicle *vehicle = ObjectAccessor::GetVehicle(guid))
+ {
+ if(vehicle->HasEmptySeat(seatId))
+ GetPlayer()->EnterVehicle(vehicle, seatId);
+ }
+}
+
+void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT");
+ recv_data.hexlike();
+ GetPlayer()->ExitVehicle();
}
void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/)
@@ -588,7 +580,7 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& /*recv_data*/)
void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data)
{
- CHECK_PACKET_SIZE(recv_data,8+1);
+ CHECK_PACKET_SIZE(recv_data, 8+1);
if(!_player->isAlive() || _player->isInCombat() )
return;