diff options
Diffstat (limited to 'src/game/MovementHandler.cpp')
-rw-r--r-- | src/game/MovementHandler.cpp | 510 |
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; |