diff options
Diffstat (limited to 'src/game/MovementHandler.cpp')
| -rw-r--r-- | src/game/MovementHandler.cpp | 342 | 
1 files changed, 115 insertions, 227 deletions
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 2eb3bab12e7..8ada92957ec 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 @@ -31,6 +31,7 @@  #include "BattleGround.h"  #include "WaypointMovementGenerator.h"  #include "InstanceSaveMgr.h" +#include "ObjectMgr.h"  void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ )  { @@ -87,6 +88,27 @@ void WorldSession::HandleMoveWorldportAckOpcode()          }          return;      } + +    //this will set player's team ... so IT MUST BE CALLED BEFORE SendInitialPacketsAfterAddToMap() +    // 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 seting if outdated +        if(!mEntry->IsBattleGroundOrArena()) +        { +            _player->SetBattleGroundId(0);                          // We're not in BG. +            // 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 @@ -131,34 +153,6 @@ void WorldSession::HandleMoveWorldportAckOpcode()      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()); -                } -            } -        } -    } -      // honorless target      if(GetPlayer()->pvpInfo.inHostileArea)          GetPlayer()->CastSpell(GetPlayer(), 2479, true); @@ -178,64 +172,15 @@ void WorldSession::HandleMoveWorldportAckOpcode()  void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )  { -    CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4); +    uint32 opcode = recv_data.GetOpcode(); +    sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); + +    if(GetPlayer()->GetDontMove()) +        return;      /* extract packet */      MovementInfo movementInfo; -    uint32 MovementFlags; - -    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; - -    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; -    } - -    if(MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) -    { -        // recheck -        CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - -        recv_data >> movementInfo.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 >> movementInfo.fallTime;                     // duration of last jump (when in jump duration from jump begin to now) - -    if(MovementFlags & MOVEMENTFLAG_JUMPING) -    { -        // recheck -        CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4); - -        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 -    } - -    if(MovementFlags & MOVEMENTFLAG_SPLINE) -    { -        // recheck -        CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - -        recv_data >> movementInfo.u_unk1;                   // unknown -    } +    ReadMovementInfo(recv_data, &movementInfo);      /*----------------*/      if(recv_data.size() != recv_data.rpos()) @@ -248,22 +193,8 @@ 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) @@ -282,9 +213,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )              {                  if ((*iter)->GetGUID() == movementInfo.t_guid)                  { -                    // unmount before boarding -                    GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); -                      GetPlayer()->m_transport = (*iter);                      (*iter)->AddPassenger(GetPlayer());                      break; @@ -301,13 +229,14 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )          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()) +    if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())          GetPlayer()->HandleFallDamage(movementInfo); -    if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) +    if(((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->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) ); @@ -316,100 +245,54 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )      /*----------------------*/      /* 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()); +    Unit *mover = _player->m_mover; +    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(_player->m_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); - -    // Remove possession if possessed unit enters a transport -    if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) +    if(!_player->GetCharmGUID())                            // nothing is charmed      { -        GetPlayer()->Uncharm(); -        return; +        _player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); +        _player->m_movementInfo = movementInfo; +        _player->SetUnitMovementFlags(movementInfo.flags);      } - -    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) +    else      { -        Player* plr = (Player*)pos_unit; - -        if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) -            plr->HandleFallDamage(movementInfo); - -        if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != plr->IsInWater()) +        if(mover->GetTypeId() != TYPEID_PLAYER)             // unit, creature, pet, vehicle...          { -            // Now client not include swimming flag in case jumping under water -            plr->SetInWater( !plr->IsInWater() || plr->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); +            if(Map *map = mover->GetMap()) +                map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); +            mover->SetUnitMovementFlags(movementInfo.flags);          } - -        plr->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o, false); -        plr->m_movementInfo = movementInfo; - -        if(plr->isMovingOrTurning()) -            plr->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - -        if(movementInfo.z < -500.0f) +        else                                                // player          { -            GetPlayer()->Uncharm(); -            plr->HandleFallUnderMap(); +            ((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); +            ((Player*)mover)->m_movementInfo = movementInfo; +            ((Player*)mover)->SetUnitMovementFlags(movementInfo.flags);          }      } -    else // Possessed unit is a creature -    { -        Map* map = MapManager::Instance().GetMap(pos_unit->GetMapId(), pos_unit); -        map->CreatureRelocation((Creature*)pos_unit, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); -    } + +    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::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 +303,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 >> 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 >> unk1;                                      // counter or moveEvent -        recv_data >> u_unk1;                                // unknown -    } +    MovementInfo movementInfo; +    ReadMovementInfo(recv_data, &movementInfo);      // recheck      CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); @@ -473,7 +319,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 +332,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; @@ -520,20 +367,61 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)  void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data)  {      sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); +    recv_data.hexlike(); -    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(_player->m_mover->GetGUID() != guid) +    { +        sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, _player->m_mover->GetGUID(), guid); +        return; +    }  } -void WorldSession::HandleNotActiveMoverOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)  {      sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); +    recv_data.hexlike(); + +    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; +    } + +    MovementInfo mi; +    ReadMovementInfo(recv_data, &mi); +    _player->m_movementInfo = mi; +} + +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; + +    MovementInfo mi; +    ReadMovementInfo(recv_data, &mi); +    _player->m_movementInfo = mi; + +    // using charm guid, because we don't have vehicle guid... +    if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) +    { +        _player->ExitVehicle(vehicle); +        vehicle->Dismiss(); +    }  }  void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/)  | 
