bool WorldSession::HandleMovementInfo(MovementInfo &movementInfo, const uint16 opcode, const size_t packSize, Unit *mover) { ASSERT(mover != NULL); if (movementInfo.guid != mover->GetGUID() || !movementInfo.pos.IsPositionValid()) return false; Player* plrMover = mover->ToPlayer(); if (plrMover && plrMover->IsBeingTeleported()) return false; if (plrMover && plrMover->HasUnitState(UNIT_STATE_CONTROLLED_BY_SERVER) && !CanMovementBeProcessed(opcode)) return false; movementInfo.Sanitize(mover); if (movementInfo.t_guid) { if (movementInfo.t_pos.GetPositionX() > 50.0f || movementInfo.t_pos.GetPositionY() > 50.0f || movementInfo.t_pos.GetPositionZ() > 50.0f) return false; // moved out of transport size 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()) ) return false; // just bad coords if (plrMover) { if (!plrMover->GetTransport()) // didn't have transport. now have { for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == movementInfo.t_guid) { plrMover->m_transport = *iter; (*iter)->AddPassenger(plrMover); break; } } } else if (plrMover->GetTransport()->GetGUID() != movementInfo.t_guid) // changes transport { 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; } } else if (movementInfo.pos.m_positionX != movementInfo.t_pos.m_positionX) plrMover->GetTransport()->UpdatePosition(&movementInfo); } if (!mover->GetTransport() && !mover->GetVehicle()) { GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) movementInfo.t_guid = 0; } } else if (plrMover && plrMover->GetTransport()) // had transport, no loger have { plrMover->m_transport->RemovePassenger(plrMover); plrMover->m_transport = NULL; movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); movementInfo.t_time = 0; movementInfo.t_seat = -1; } if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->isInFlight()) plrMover->HandleFall(movementInfo); if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } if (plrMover) sAnticheatMgr->StartHackDetection(plrMover, movementInfo, opcode); WorldPacket data(movementInfo.GetSMSGOpcodeForCMSG(Opcodes(opcode)), packSize); movementInfo.time = getMSTime(); movementInfo.guid = mover->GetGUID(); movementInfo.WriteToPacket(data); _player->SendMessageToSet(&data, _player); mover->m_movementInfo = movementInfo; if (mover->GetVehicle()) // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() { mover->SetOrientation(movementInfo.pos.GetOrientation()); return true; } // Remove pet when starting to fly if (plrMover && plrMover->IsFlying()) plrMover->UnsummonPetTemporaryIfAny(); mover->UpdatePosition(movementInfo.pos); if (plrMover) { plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); float underMapValueZ, upperLimitValueZ; bool check = false; switch (plrMover->GetMapId()) { case 617: // Dalaran Arena underMapValueZ = 3.0f; upperLimitValueZ = 30.0f; break; case 562: // Blades Edge Arena underMapValueZ = -1.0f; upperLimitValueZ = 22.0f; break; case 559: // Nagrand Arena underMapValueZ = -1.0f; upperLimitValueZ = 21.0f; break; case 572: // Ruins of Lordaeron underMapValueZ = -1.0f; upperLimitValueZ = 45.0f; break; case 618: // Ring of Valor underMapValueZ = 28.0f; upperLimitValueZ = 60.0f; break; case 566: // Eye of the storm underMapValueZ = 1000.0f; upperLimitValueZ = MAX_HEIGHT; break; default: AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId()); underMapValueZ = zone ? zone->MaxDepth : -500.0f; upperLimitValueZ = MAX_HEIGHT; break; } check = movementInfo.pos.GetPositionZ() < underMapValueZ || movementInfo.pos.GetPositionZ() > upperLimitValueZ; if (check && plrMover->isAlive() && !(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player))) { plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); if (!plrMover->isAlive()) plrMover->KillPlayer(); // prevent death timer plrMover->RepopAtGraveyard(); } } return true; }
void WorldSession::HandleMovementSpeedChangeAck(WorldPacket& recvPacket) { UnitMoveType moveType; bool updatePacketNotKnown = false; switch (recvPacket.GetOpcode()) { case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: moveType = MOVE_WALK; break; case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: moveType = MOVE_RUN; break; case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: moveType = MOVE_RUN_BACK; break; case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: moveType = MOVE_SWIM; break; case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: moveType = MOVE_SWIM_BACK; break; case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: moveType = MOVE_TURN_RATE; updatePacketNotKnown = true; break; case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: moveType = MOVE_FLIGHT; break; case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: moveType = MOVE_FLIGHT_BACK; updatePacketNotKnown = true; break; case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: moveType = MOVE_PITCH_RATE; updatePacketNotKnown = true; break; default: sLog->outInfo(LOG_FILTER_BAD_OPCODE_HANDLER, "WorldSession::HandleMovementSpeedChangeAck for unknown opcode: %s", GetOpcodeNameForLogging(recvPacket.GetOpcode()).c_str()); return; } MovementInfo info; info.ReadFromPacket(recvPacket); // skip old result if (_player->m_forced_speed_changes[moveType] != info.ackCount) { recvPacket.rfinish(); return; } if (!_player->GetTransport() && fabs(_player->GetSpeed(moveType) - info.ackSpeed) > 0.01f) { if (_player->GetSpeed(moveType) > info.ackSpeed) _player->SetSpeed(moveType, _player->GetSpeedRate(moveType), true); recvPacket.rfinish(); return; } // TODO: Find all structure (remove me) if (updatePacketNotKnown) { WorldPacket data; switch (moveType) { case MOVE_TURN_RATE: data.Initialize(SMSG_MOVE_SET_TURN_RATE, 1 + 8 + 4 + 4); info.WriteToPacket(data); _player->SendMessageToSet(&data, _player); break; case MOVE_FLIGHT_BACK: data.Initialize(SMSG_MOVE_SET_FLIGHT_BACK_SPEED, 1 + 8 + 4 + 4); info.WriteToPacket(data); _player->SendMessageToSet(&data, _player); break; case MOVE_PITCH_RATE: data.Initialize(SMSG_MOVE_SET_PITCH_RATE, 1 + 8 + 4 + 4); info.WriteToPacket(data); _player->SendMessageToSet(&data, _player); break; default: break; } } HandleMovementInfo(info, recvPacket.GetOpcode(), recvPacket.size()-4, _player->m_mover); }
void WorldSession::HandleMoveTeleportAck(WorldPacket& recvPacket) { sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_MOVE_TELEPORT_ACK"); ObjectGuid guid; uint32 ackCount = recvPacket.read<uint32>(); recvPacket.read_skip<uint32>(); // should be new position in kind of struction 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]); // Skip old result if (_player->m_movement_ack[ACK_TELEPORT] != ackCount) return; Player* plMover = _player->m_mover->ToPlayer(); if (!plMover || !plMover->IsBeingTeleportedNear() || guid != plMover->GetGUID()) return; plMover->SetSemaphoreTeleportNear(false); uint32 old_zone = plMover->GetZoneId(); WorldLocation const& dest = plMover->GetTeleportDest(); plMover->UpdatePosition(dest, true); WorldPacket data(SMSG_MOVE_UPDATE_TELEPORT); MovementInfo info = MovementInfo(plMover->m_movementInfo); info.pos.Relocate(dest.m_positionX, dest.m_positionY, dest.m_positionZ, dest.m_orientation); info.guid = plMover->GetGUID(); info.time = getMSTime(); info.WriteToPacket(data); _player->SendMessageToSet(&data, _player); uint32 newzone, newarea; plMover->GetZoneAndAreaId(newzone, newarea); plMover->UpdateZone(newzone, newarea); if (old_zone != newzone) { if (plMover->pvpInfo.inHostileArea) plMover->CastSpell(plMover, 2479, true); // honorless target else if (plMover->IsPvP() && !plMover->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) plMover->UpdatePvP(false, false); } GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); GetPlayer()->ProcessDelayedOperations(); }