diff options
Diffstat (limited to 'src/game/BattleGroundHandler.cpp')
| -rw-r--r-- | src/game/BattleGroundHandler.cpp | 352 | 
1 files changed, 160 insertions, 192 deletions
diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index b1522c939f7..6dc1d9785a3 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.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 @@ -25,7 +25,6 @@  #include "Player.h"  #include "ObjectMgr.h"  #include "WorldSession.h" -#include "MapManager.h"  #include "ObjectAccessor.h"  #include "Object.h"  #include "Chat.h" @@ -53,7 +52,7 @@ void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data )      // Stop the npc if moving      unit->StopMoving(); -    uint32 bgTypeId = objmgr.GetBattleMasterBG(unit->GetEntry()); +    BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(unit->GetEntry());      if(!_player->GetBGAccessByLevel(bgTypeId))      { @@ -65,7 +64,7 @@ void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data )      SendBattlegGroundList(guid, bgTypeId);  } -void WorldSession::SendBattlegGroundList( uint64 guid, uint32 bgTypeId ) +void WorldSession::SendBattlegGroundList( uint64 guid, BattleGroundTypeId bgTypeId )  {      WorldPacket data;      sBattleGroundMgr.BuildBattleGroundListPacket(&data, guid, _player, bgTypeId); @@ -77,26 +76,29 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )      CHECK_PACKET_SIZE(recv_data, 8+4+4+1);      uint64 guid; -    uint32 bgTypeId; +    uint32 bgTypeId_;      uint32 instanceId;      uint8 joinAsGroup; +    bool isPremade = false;      Group * grp;      recv_data >> guid;                                      // battlemaster guid -    recv_data >> bgTypeId;                                  // battleground type id (DBC id) +    recv_data >> bgTypeId_;                                 // battleground type id (DBC id)      recv_data >> instanceId;                                // instance id, 0 if First Available selected      recv_data >> joinAsGroup;                               // join as group -    if(bgTypeId >= MAX_BATTLEGROUND_TYPES) +    if(!sBattlemasterListStore.LookupEntry(bgTypeId_))      { -        sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow()); +        sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow());          return;      } +    BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); +      sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid);      // can do this, since it's battleground, not arena -    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0); +    BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0);      // ignore if player is already in BG      if(_player->InBattleGround()) @@ -110,9 +112,9 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )          return;      // get bg instance or bg template if instance not found -    BattleGround * bg = 0; +    BattleGround * bg = NULL;      if(instanceId) -        BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); +        BattleGround *bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));      if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))      { @@ -127,7 +129,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )          if( !_player->CanJoinToBattleground() )          {              WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); -            data << (uint32) 0xFFFFFFFE; +            data << uint32(0xFFFFFFFE);              _player->GetSession()->SendPacket(&data);              return;          } @@ -146,6 +148,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )          if(!grp)              return;          uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); +        isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam());          if (err != BG_JOIN_ERR_OK)          {              SendBattleGroundOrArenaJoinError(err); @@ -155,10 +158,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )      // if we're here, then the conditions to join a bg are met. We can proceed in joining.      // _player->GetGroup() was already checked, grp is already initialized +    GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0); +    uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));      if(joinAsGroup /* && _player->GetGroup()*/)      {          sLog.outDebug("Battleground: the following players are joining as group:"); -        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);          for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())          {              Player *member = itr->getSource(); @@ -171,7 +175,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )              WorldPacket data;                                                              // send status packet (in queue) -            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); +            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType);              member->GetSession()->SendPacket(&data);              sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);              member->GetSession()->SendPacket(&data); @@ -179,7 +183,6 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )              sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());          }          sLog.outDebug("Battleground: group end"); -        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());      }      else      { @@ -190,14 +193,15 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )          WorldPacket data;                                                              // send status packet (in queue) -        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); +        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType);          SendPacket(&data); -        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);          sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); -        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());          sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());      } +    sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); +    if(!ginfo->IsInvitedToBGInstanceGUID) +        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);  }  void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv_data*/ ) @@ -270,19 +274,15 @@ void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data )      uint32 bgTypeId;      recv_data >> bgTypeId;                                  // id from DBC -    if(bgTypeId >= MAX_BATTLEGROUND_TYPES) +    BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); +    if(!bl)      {          sLog.outError("Battleground: invalid bgtype received.");          return;      } -    BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); - -    if(!bl) -        return; -      WorldPacket data; -    sBattleGroundMgr.BuildBattleGroundListPacket(&data, _player->GetGUID(), _player, bgTypeId); +    sBattleGroundMgr.BuildBattleGroundListPacket(&data, _player->GetGUID(), _player, BattleGroundTypeId(bgTypeId));      SendPacket( &data );  } @@ -295,45 +295,40 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )      uint8 type;                                             // arenatype if arena      uint8 unk2;                                             // unk, can be 0x0 (may be if was invited?) and 0x1      uint32 instanceId; -    uint32 bgTypeId;                                        // type id from dbc +    uint32 bgTypeId_;                                       // type id from dbc      uint16 unk;                                             // 0x1F90 constant?      uint8 action;                                           // enter battle 0x1, leave queue 0x0 -    recv_data >> type >> unk2 >> bgTypeId >> unk >> action; +    recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action; -    if(bgTypeId >= MAX_BATTLEGROUND_TYPES) +    if( !sBattlemasterListStore.LookupEntry(bgTypeId_) )      { -        sLog.outError("Battleground: invalid bgtype received."); +        sLog.outError("Battleground: invalid bgtype (%u) received.", bgTypeId_);          // update battleground slots for the player to fix his UI and sent data.          // this is a HACK, I don't know why the client starts sending invalid packets in the first place.          // it usually happens with extremely high latency (if debugging / stepping in the code for example) -        if(_player->InBattleGroundQueue()) +        if( _player->InBattleGroundQueue() )          {              // update all queues, send invitation info if player is invited, queue info if queued              for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)              { -                uint32 queue_id = _player->GetBattleGroundQueueId(i); -                if(!queue_id) +                BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); +                if( !bgQueueTypeId )                      continue; -                BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); -                // if the player is not in queue, contine -                if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) -                    continue; - -                // no group information, this should never happen -                if(!itrPlayerStatus->second.GroupInfo) +                BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); +                BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; +                BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); +                // if the player is not in queue, continue or no group information - this should never happen +                if( itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo )                      continue;                  BattleGround * bg = NULL; -                  // get possibly needed data from groupinfo -                bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId;                  uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;                  uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;                  uint8 status = 0; - -                if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) +                if( !itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID )                  {                      // not invited to bg, get template                      bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); @@ -342,93 +337,91 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )                  else                  {                      // get the bg we're invited to -                    BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID); +                    BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId);                      status = STATUS_WAIT_JOIN;                  } -                // if bg not found, then continue -                if(!bg) -                    continue; - -                // don't invite if already in the instance -                if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) +                // if bg not found, then continue, don't invite if already in the instance +                if( !bg || (_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) )                      continue;                  // re - invite player with proper data                  WorldPacket data; -                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted); +                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype);                  SendPacket(&data);              }          }          return;      } -    uint32 bgQueueTypeId = 0; -    // get the bg what we were invited to -    BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; -    bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type); -    itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); - -    if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) +    //get GroupQueueInfo from BattleGroundQueue +    BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); +    BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type); +    BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; +    BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); +    if( itrPlayerStatus == qpMap.end() )      {          sLog.outError("Battleground: itrplayerstatus not found.");          return;      } -    instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; -    // if action == 1, then instanceId is _required_ -    if(!instanceId && action == 1) +    instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; +    // if action == 1, then instanceId is required +    if( !instanceId && action == 1 )      {          sLog.outError("Battleground: instance not found.");          return;      } -    BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); +    BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId);      // bg template might and must be used in case of leaving queue, when instance is not created yet -    if(!bg && action == 0) +    if( !bg && action == 0 )          bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - -    if(!bg) +    if( !bg )      { -        sLog.outError("Battleground: bg not found."); +        sLog.outError("Battleground: bg_template not found for type id %u.", bgTypeId);          return;      } -    bgTypeId = bg->GetTypeID(); - -    if(_player->InBattleGroundQueue()) +    if( _player->InBattleGroundQueue() )      { -        uint32 queueSlot = 0; -        uint32 team = 0; -        uint32 arenatype = 0; -        uint32 israted = 0; -        uint32 rating = 0; -        uint32 opponentsRating = 0; -        // get the team info from the queue -        BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); -        if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end() -            && pitr->second.GroupInfo ) +        //we must use temporary variables, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function! +        uint32 team = itrPlayerStatus->second.GroupInfo->Team; +        uint32 arenaType = itrPlayerStatus->second.GroupInfo->ArenaType; +        uint32 isRated = itrPlayerStatus->second.GroupInfo->IsRated; +        uint32 rating = itrPlayerStatus->second.GroupInfo->ArenaTeamRating; +        uint32 opponentsRating = itrPlayerStatus->second.GroupInfo->OpponentsTeamRating; + +        //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it +        if( action == 1 && arenaType == 0)          { -            team = pitr->second.GroupInfo->Team; -            arenatype = pitr->second.GroupInfo->ArenaType; -            israted = pitr->second.GroupInfo->IsRated; -            rating = pitr->second.GroupInfo->ArenaTeamRating; -            opponentsRating = pitr->second.GroupInfo->OpponentsTeamRating; -        } -        else -        { -            sLog.outError("Battleground: Invalid player queue info!"); -            return; +            //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue +            if( !_player->CanJoinToBattleground() ) +            { +                //send bg command result to show nice message +                WorldPacket data2(SMSG_GROUP_JOINED_BATTLEGROUND, 4); +                data2 << uint32(0xFFFFFFFE); +                _player->GetSession()->SendPacket(&data2); +                action = 0; +                sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); +            } +            //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue +            if( _player->getLevel() > bg->GetMaxLevel() ) +            { +                sLog.outError("Battleground: Player %s (%u) has level higher than maxlevel of battleground! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); +                action = 0; +            }          } +        uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);          WorldPacket data; -        switch(action) +        switch( action )          { -            case 1:                                     // port to battleground -                if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) -                    return;                                     // cheating? +            case 1:                                         // port to battleground +                if( !_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId) ) +                    return;                                 // cheating?                  // resurrect the player -                if(!_player->isAlive()) +                if( !_player->isAlive() )                  {                      _player->ResurrectPlayer(1.0f);                      _player->SpawnCorpseBones(); @@ -439,49 +432,48 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )                      _player->GetMotionMaster()->MovementExpired();                      _player->m_taxi.ClearTaxiDestinations();                  } +                //TODO FIX ME this call must be removed!                  _player->RemoveFromGroup(); -                queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); -                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + +                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType());                  _player->GetSession()->SendPacket(&data);                  // remove battleground queue status from BGmgr                  sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);                  // this is still needed here if battleground "jumping" shouldn't add deserter debuff -                // also this required to prevent stuck at old battleground after SetBattleGroundId set to new +                // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new                  if( BattleGround *currentBg = _player->GetBattleGround() )                      currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);                  // set the destination instance id -                _player->SetBattleGroundId(bg->GetInstanceID()); +                _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId);                  // set the destination team                  _player->SetBGTeam(team);                  // bg->HandleBeforeTeleportToBattleGround(_player); -                sBattleGroundMgr.SendToBattleGround(_player, instanceId); +                sBattleGroundMgr.SendToBattleGround(_player, instanceId, bgTypeId);                  // add only in HandleMoveWorldPortAck()                  // bg->AddPlayer(_player,team); -                sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); +                sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);                  break; -            case 0:                                     // leave queue -                queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); -                /* -                if player leaves rated arena match before match start, it is counted as he played but he lost -                */ -                if (israted) +            case 0:                                         // leave queue +                // if player leaves rated arena match before match start, it is counted as he played but he lost +                if( isRated )                  {                      ArenaTeam * at = objmgr.GetArenaTeamById(team); -                    if (at) +                    if( at )                      {                          sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating);                          at->MemberLost(_player, opponentsRating);                          at->SaveToDB();                      }                  } -                _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs -                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); +                _player->RemoveBattleGroundQueueId(bgQueueTypeId);  // must be called this way, because if you move this call to queue->removeplayer, it causes bugs +                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);                  sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); -                // player left queue, we should update it, maybe now his group fits in -                sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(),arenatype,israted,rating); +                // player left queue, we should update it - do not update Arena Queue +                if( !arenaType ) +                    sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenaType, isRated, rating);                  SendPacket(&data); -                sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId); +                sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);                  break;              default:                  sLog.outError("Battleground port: unknown action %u", action); @@ -520,81 +512,56 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )      sLog.outDebug( "WORLD: Battleground status" );      WorldPacket data; - -    // TODO: we must put player back to battleground in case disconnect (< 5 minutes offline time) or teleport player on login(!) from battleground map to entry point -    if(_player->InBattleGround()) +    // we must update all queues here +    BattleGround *bg = NULL; +    for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)      { -        BattleGround *bg = _player->GetBattleGround(); -        if(bg) +        BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); +        if( !bgQueueTypeId ) +            continue; +        BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); +        uint8 arenaType = BattleGroundMgr::BGArenaType(bgQueueTypeId); +        if( bgTypeId == _player->GetBattleGroundTypeId() )          { -            uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); -            uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); -            if((bg->GetStatus() <= STATUS_IN_PROGRESS)) +            bg = _player->GetBattleGround(); +            //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena +            //so i must use bg pointer to get that information +            if( bg && bg->GetArenaType() == arenaType )              { -                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); +                // this line is checked, i only don't know if GetStartTime is changing itself after bg end! +                // send status in BattleGround +                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType);                  SendPacket(&data); -            } -            for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) -            { -                uint32 queue_id = _player->GetBattleGroundQueueId(i);       // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong -                uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); -                uint8 isRated = 0; -                if (i == queueSlot || !queue_id)                            // we need to get the instance ids -                    continue; -                BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); -                if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) -                    continue; -                if(itrPlayerStatus->second.GroupInfo) -                { -                    arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; -                    isRated = itrPlayerStatus->second.GroupInfo->IsRated; -                } -                BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); //  try this -                if(bg2) -                { -                    //in this call is small bug, this call should be filled by player's waiting time in queue -                    //this call nulls all timers for client : -                    sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated); -                    SendPacket(&data); -                } +                continue;              }          } -    } -    else -    { -        // we should update all queues? .. i'm not sure if this code is correct -        for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) +        //we are sending update to player about queue - he can be invited there! +        //get GroupQueueInfo for queue status +        BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; +        BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); +        if( itrPlayerStatus == qpMap.end() ) +            continue; +        if( itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID )          { -            uint32 queue_id = _player->GetBattleGroundQueueId(i); -            if(!queue_id) +            bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId); +            if( !bg )                  continue; -            uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); -            uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); -            uint8 isRated = 0; -            BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); -            BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); -            if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) -                continue; -            if(itrPlayerStatus->second.GroupInfo) -            { -                arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; -                isRated = itrPlayerStatus->second.GroupInfo->IsRated; -            } -            if(bg && queue_id) -            { -                sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); -                SendPacket(&data); -            } +            uint32 remainingTime = getMSTimeDiff(getMSTime(), itrPlayerStatus->second.GroupInfo->RemoveInviteTime); +            // send status invited to BattleGround +            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType); +            SendPacket(&data);          } -    } -/*    else              // not sure if it needed... -    { -        for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) +        else          { -            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0); +            BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); +            if( !bg ) +                continue; +            uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); +            // send status in BattleGround Queue +            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(itrPlayerStatus->second.GroupInfo->JoinTime, getMSTime()), arenaType);              SendPacket(&data);          } -    }*/ +    }  }  void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) @@ -655,12 +622,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )          return;      uint64 guid;                                            // arena Battlemaster guid -    uint8 type;                                             // 2v2, 3v3 or 5v5 +    uint8 arenaslot;                                        // 2v2, 3v3 or 5v5      uint8 asGroup;                                          // asGroup      uint8 isRated;                                          // isRated      Group * grp; -    recv_data >> guid >> type >> asGroup >> isRated; +    recv_data >> guid >> arenaslot >> asGroup >> isRated;      Creature *unit = ObjectAccessor::GetCreature(*_player, guid);      if(!unit) @@ -672,7 +639,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )      uint8 arenatype = 0;      uint32 arenaRating = 0; -    switch(type) +    switch(arenaslot)      {          case 0:              arenatype = ARENA_TYPE_2v2; @@ -684,7 +651,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )              arenatype = ARENA_TYPE_5v5;              break;          default: -            sLog.outError("Unknown arena type %u at HandleBattleGroundArenaJoin()", type); +            sLog.outError("Unknown arena slot %u at HandleBattleGroundArenaJoin()", arenaslot);              return;      } @@ -696,8 +663,8 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )          return;      } -    uint8 bgTypeId = bg->GetTypeID(); -    uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); +    BattleGroundTypeId bgTypeId = bg->GetTypeID(); +    BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype);      // check queueing conditions      if(!asGroup) @@ -716,7 +683,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )          // no group found, error          if(!grp)              return; -        uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type); +        uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot);          if (err != BG_JOIN_ERR_OK)          {              SendBattleGroundOrArenaJoinError(err); @@ -728,7 +695,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )      if(isRated)      { -        ateamId = _player->GetArenaTeamId(type); +        ateamId = _player->GetArenaTeamId(arenaslot);          // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)          ArenaTeam * at = objmgr.GetArenaTeamById(ateamId);          if(!at) @@ -746,7 +713,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )              Player *member = itr->getSource();              // calc avg personal rating -            avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5); +            avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaslot*6) + 5);          }          if( arenatype ) @@ -757,12 +724,13 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )              arenaRating = avg_pers_rating;      } +    GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); +    uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));      if(asGroup)      { -        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId);          sLog.outDebug("Battleground: arena join as group start");          if(isRated) -            sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype); +            sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype);          for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())          {              Player *member = itr->getSource(); @@ -775,7 +743,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )              WorldPacket data;              // send status packet (in queue) -            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); +            sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype);              member->GetSession()->SendPacket(&data);              sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);              member->GetSession()->SendPacket(&data); @@ -783,7 +751,8 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )              sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());          }          sLog.outDebug("Battleground: arena join as group end"); -        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); +        if(isRated) +            sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);      }      else      { @@ -794,13 +763,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )          WorldPacket data;          // send status packet (in queue) -        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); +        sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype);          SendPacket(&data); -        GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating);          sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); -        sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating);          sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());      } +    sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);  }  void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data )  | 
