void WorldSession::HandleBattlefieldListOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Recvd CMSG_BATTLEFIELD_LIST Message"); uint32 mapId; recv_data >> mapId; BattleGroundTypeId bgTypeId = GetBattleGroundTypeIdByMapId(mapId); if (bgTypeId == BATTLEGROUND_TYPE_NONE) { sLog.outError("Battleground: invalid bgtype received."); return; } WorldPacket data; sBattleGroundMgr.BuildBattleGroundListPacket(&data, _player->GetObjectGuid(), _player, BattleGroundTypeId(bgTypeId)); SendPacket(&data); }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recv_data) { ObjectGuid guid; uint32 instanceId; uint32 mapId; uint8 joinAsGroup; bool isPremade = false; Group* grp; recv_data >> guid; // battlemaster guid recv_data >> mapId; recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group BattleGroundTypeId bgTypeId = GetBattleGroundTypeIdByMapId(mapId); if (bgTypeId == BATTLEGROUND_TYPE_NONE) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId, _player->GetGUIDLow()); return; } DEBUG_LOG("WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from %s", guid.GetString().c_str()); // can do this, since it's battleground, not arena BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId); // ignore if player is already in BG if (_player->InBattleGround()) return; Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if (!unit->isBattleMaster()) // it's not battlemaster return; // get bg instance or bg template if instance not found BattleGround* bg = NULL; if (instanceId) bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); if (!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } BattleGroundBracketId bgBracketId = _player->GetBattleGroundBracketIdFromLevel(bgTypeId); // check queue conditions if (!joinAsGroup) { // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(0xFFFFFFFE); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam()); isPremade = sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH) && (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { SendBattleGroundJoinError(err); return; } } // 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 BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (joinAsGroup) { DEBUG_LOG("Battleground: the following players are joining as group:"); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bgBracketId, isPremade); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; // this should never happen uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName()); } DEBUG_LOG("Battleground: group end"); } else { GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bgBracketId, isPremade); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(bgQueueTypeId, bgTypeId, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); }
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); uint8 action; // enter battle 0x1, leave queue 0x0 uint32 mapId; recv_data >> mapId >> action; BattleGroundTypeId bgTypeId = GetBattleGroundTypeIdByMapId(mapId); if (bgTypeId == BATTLEGROUND_TYPE_NONE) { sLog.outError("BattlegroundHandler: invalid bg map (%u) received.", mapId); return; } if (!_player->InBattleGroundQueue()) { sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player->GetGUIDLow()); return; } //get GroupQueueInfo from BattleGroundQueue BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId); BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function GroupQueueInfo ginfo; if (!bgQueue.GetPlayerGroupInfoData(_player->GetObjectGuid(), &ginfo)) { sLog.outError("BattlegroundHandler: itrplayerstatus not found."); return; } // if action == 1, then instanceId is required if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) { sLog.outError("BattlegroundHandler: instance not found."); return; } BattleGround* bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); // bg template might and must be used in case of leaving queue, when instance is not created yet if (!bg && action == 0) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) { sLog.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); return; } //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it if (action == 1) { //if player is trying to enter battleground 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; DEBUG_LOG("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 (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID()); action = 0; } } uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); WorldPacket data; switch (action) { case 1: // port to battleground if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) return; // cheating? // resurrect the player if (!_player->isAlive()) { _player->ResurrectPlayer(1.0f); _player->SpawnCorpseBones(); } // stop taxi flight at port if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->m_taxi.ClearTaxiDestinations(); } sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); _player->GetSession()->SendPacket(&data); // remove battleground queue status from BGmgr bgQueue.RemovePlayer(_player->GetObjectGuid(), false); // this is still needed here if battleground "jumping" shouldn't add deserter debuff // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new if (BattleGround* currentBg = _player->GetBattleGround()) currentBg->RemovePlayerAtLeave(_player->GetObjectGuid(), false, true); // set the destination instance id _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId); // set the destination team _player->SetBGTeam(ginfo.GroupTeam); // bg->HandleBeforeTeleportToBattleGround(_player); sBattleGroundMgr.SendToBattleGround(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); // add only in HandleMoveWorldPortAck() // bg->AddPlayer(_player,team); DEBUG_LOG("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 _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); bgQueue.RemovePlayer(_player->GetObjectGuid(), true); // player left queue, we should update it sBattleGroundMgr.ScheduleQueueUpdate(bgQueueTypeId, bgTypeId, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); SendPacket(&data); DEBUG_LOG("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); break; } }
void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) { uint64 guid; uint32 instanceId; uint32 mapId; uint8 joinAsGroup; Group * grp; recv_data >> guid; // battlemaster guid recv_data >> mapId; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group BattleGroundTypeId bgTypeId = GetBattleGroundTypeIdByMapId(mapId); if(bgTypeId == BATTLEGROUND_TYPE_NONE) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId,_player->GetGUIDLow()); return; } DEBUG_LOG( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid))); // can do this, since it's battleground, not arena uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId); // ignore if player is already in BG if(_player->InBattleGround()) return; Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if(!unit->isBattleMaster()) // it's not battlemaster return; // get bg instance or bg template if instance not found BattleGround *bg = NULL; if(instanceId) bg = sBattleGroundMgr.GetBattleGround(instanceId); if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } BattleGroundBracketId bgBracketId = _player->GetBattleGroundBracketIdFromLevel(); // check queueing conditions if(!joinAsGroup) { // check Deserter debuff if( !_player->CanJoinToBattleground() ) { WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << (uint32) 0xFFFFFFFE; _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if(!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if(!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { SendBattleGroundJoinError(err); return; } } // 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 if(joinAsGroup /* && _player->GetGroup()*/) { DEBUG_LOG("Battleground: the following players are joining as group:"); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, bgBracketId); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; // this should never happen uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } DEBUG_LOG("Battleground: group end"); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundBracketIdFromLevel()); if(!ginfo->IsInvitedToBGInstanceGUID) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); SendPacket(&data); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, bgBracketId); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundBracketIdFromLevel()); if(!ginfo->IsInvitedToBGInstanceGUID) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } }
void WorldSession::HandleBattleFieldPortOpcode( WorldPacket &recv_data ) { DEBUG_LOG( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); uint8 action; // enter battle 0x1, leave queue 0x0 uint32 mapId; recv_data >> mapId >> action; BattleGroundTypeId bgTypeId = GetBattleGroundTypeIdByMapId(mapId); if(bgTypeId == BATTLEGROUND_TYPE_NONE) { 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()) { // 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) continue; BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundBracketIdFromLevel()].find(_player->GetGUID()); // if the player is not in queue, continue if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundBracketIdFromLevel()].end()) continue; // no group information, this should never happen if(!itrPlayerStatus->second.GroupInfo) continue; BattleGround * bg = NULL; // get possibly needed data from groupinfo BattleGroundTypeId bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId; uint8 status = 0; if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) { // not invited to bg, get template bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); status = STATUS_WAIT_QUEUE; } else { // get the bg we're invited to bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID); 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()) 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); SendPacket(&data); } } return; } // get the bg what we were invited to BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId); BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundBracketIdFromLevel()].find(_player->GetGUID()); if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundBracketIdFromLevel()].end()) { sLog.outError("Battleground: itrplayerstatus not found."); return; } uint32 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); // bg template might and must be used in case of leaving queue, when instance is not created yet if(!bg && action == 0) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if(!bg) { sLog.outError("Battleground: bg not found for type id %u.",bgTypeId); return; } bgTypeId = bg->GetTypeID(); if(_player->InBattleGroundQueue()) { uint32 queueSlot = 0; uint32 team = 0; // get the team info from the queue BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundBracketIdFromLevel()].find(_player->GetGUID()); if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundBracketIdFromLevel()].end() && pitr->second.GroupInfo ) { team = pitr->second.GroupInfo->Team; } else { sLog.outError("Battleground: Invalid player queue info!"); return; } WorldPacket data; switch(action) { case 1: // port to battleground if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) return; // cheating? // resurrect the player if(!_player->isAlive()) { _player->ResurrectPlayer(1.0f); _player->SpawnCorpseBones(); } // stop taxi flight at port if(_player->isInFlight()) { _player->GetMotionMaster()->MovementExpired(); _player->m_taxi.ClearTaxiDestinations(); } _player->RemoveFromGroup(); queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); _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 if( BattleGround *currentBg = _player->GetBattleGround() ) currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); // set the destination instance id _player->SetBattleGroundId(bg->GetInstanceID()); // set the destination team _player->SetBGTeam(team); // bg->HandleBeforeTeleportToBattleGround(_player); sBattleGroundMgr.SendToBattleGround(_player, instanceId); // add only in HandleMoveWorldPortAck() // bg->AddPlayer(_player,team); DEBUG_LOG("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); _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); 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->GetBattleGroundBracketIdFromLevel()); SendPacket(&data); DEBUG_LOG("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); break; } } }
void WorldSession::HandleBattleFieldPortOpcode( WorldPacket &recv_data ) { DEBUG_LOG( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); uint8 action; // enter battle 0x1, leave queue 0x0 uint32 mapId; recv_data >> mapId >> action; BattleGroundTypeId bgTypeId = GetBattleGroundTypeIdByMapId(mapId); if (bgTypeId == BATTLEGROUND_TYPE_NONE) { 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()) { // update all queues, send invitation info if player is invited, queue info if queued for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) { BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); if (!bgQueueTypeId) continue; 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 uint8 status = 0; if (!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) { // not invited to bg, get template bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); status = STATUS_WAIT_QUEUE; } else { // get the bg we're invited to bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId); status = STATUS_WAIT_JOIN; } // 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, i, status, INVITE_ACCEPT_WAIT_TIME, 0); SendPacket(&data); } } return; } // get the bg what we were invited to BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId); 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; } uint32 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, bgTypeId); // bg template might and must be used in case of leaving queue, when instance is not created yet if (!bg && action == 0) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) { sLog.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); return; } if (_player->InBattleGroundQueue()) { //we must use temporary variables, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function! uint32 team = itrPlayerStatus->second.GroupInfo->Team; //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it if (action == 1) { //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 ) { case 1: // port to battleground if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) return; // cheating? // resurrect the player if (!_player->isAlive()) { _player->ResurrectPlayer(1.0f); _player->SpawnCorpseBones(); } // stop taxi flight at port if (_player->IsTaxiFlying()) { _player->GetMotionMaster()->MovementExpired(); _player->m_taxi.ClearTaxiDestinations(); } sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); _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 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(), bgTypeId); // set the destination team _player->SetBGTeam(team); // bg->HandleBeforeTeleportToBattleGround(_player); sBattleGroundMgr.SendToBattleGround(_player, instanceId, bgTypeId); // add only in HandleMoveWorldPortAck() // bg->AddPlayer(_player,team); DEBUG_LOG("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 _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); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); // player left queue, we should update it sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); SendPacket(&data); DEBUG_LOG("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); break; } } }