diff options
author | Brian <runningnak3d@gmail.com> | 2010-02-15 07:55:01 -0700 |
---|---|---|
committer | Brian <runningnak3d@gmail.com> | 2010-02-15 07:55:01 -0700 |
commit | 51dae1505d30fa1c2216f76284cc76bf3e3c45d1 (patch) | |
tree | 40f81c1204bd4f53413af19a6f7b40b4ed5b2169 | |
parent | b9a4bd8a26ec74a1dede6129764db85a3b6710aa (diff) | |
parent | 3dd6fdedf739ac87fa9da9a294bdc9ffdca28441 (diff) |
* Merge
--HG--
branch : trunk
-rw-r--r-- | src/game/BattleGround.cpp | 56 | ||||
-rw-r--r-- | src/game/BattleGround.h | 26 | ||||
-rw-r--r-- | src/game/BattleGroundEY.cpp | 4 | ||||
-rw-r--r-- | src/game/BattleGroundHandler.cpp | 312 | ||||
-rw-r--r-- | src/game/BattleGroundMgr.cpp | 460 | ||||
-rw-r--r-- | src/game/BattleGroundMgr.h | 46 | ||||
-rw-r--r-- | src/game/ChatHandler.cpp | 103 | ||||
-rw-r--r-- | src/game/DBCEnums.h | 9 | ||||
-rw-r--r-- | src/game/DBCStores.cpp | 34 | ||||
-rw-r--r-- | src/game/DBCStores.h | 3 | ||||
-rw-r--r-- | src/game/DBCStructure.h | 13 | ||||
-rw-r--r-- | src/game/DBCfmt.h | 1 | ||||
-rw-r--r-- | src/game/Group.cpp | 12 | ||||
-rw-r--r-- | src/game/Group.h | 2 | ||||
-rw-r--r-- | src/game/MapInstanced.cpp | 8 | ||||
-rw-r--r-- | src/game/Player.cpp | 25 | ||||
-rw-r--r-- | src/game/Player.h | 2 | ||||
-rw-r--r-- | src/game/Unit.cpp | 41 | ||||
-rw-r--r-- | src/game/WorldSession.h | 1 | ||||
-rw-r--r-- | src/scripts/northrend/storm_peaks.cpp | 2 | ||||
-rw-r--r-- | src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp | 8 | ||||
-rw-r--r-- | src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp | 8 |
22 files changed, 614 insertions, 562 deletions
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index aebe9bd28b1..b45a9961671 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -135,7 +135,7 @@ BattleGround::BattleGround() m_ClientInstanceID = 0; m_EndTime = 0; m_LastResurrectTime = 0; - m_QueueId = QUEUE_ID_MAX_LEVEL_19; + m_BracketId = BG_BRACKET_ID_FIRST; m_InvitedAlliance = 0; m_InvitedHorde = 0; m_ArenaType = 0; @@ -503,11 +503,13 @@ void BattleGround::SendPacketToAll(WorldPacket *packet) { for (BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { + if (itr->second.OfflineRemoveTime) + continue; Player *plr = objmgr.GetPlayer(itr->first); if (plr) plr->GetSession()->SendPacket(packet); else - sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); + sLog.outError("BattleGround:SendPacketToAll: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); } } @@ -515,11 +517,12 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player * { for (BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { + if (itr->second.OfflineRemoveTime) + continue; Player *plr = objmgr.GetPlayer(itr->first); - if (!plr) { - sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); + sLog.outError("BattleGround:SendPacketToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); continue; } @@ -547,11 +550,13 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) for (BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { + if (itr->second.OfflineRemoveTime) + continue; Player *plr = objmgr.GetPlayer(itr->first); if (!plr) { - sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); + sLog.outError("BattleGround:PlaySoundToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); continue; } @@ -570,11 +575,13 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) { for (BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { + if (itr->second.OfflineRemoveTime) + continue; Player *plr = objmgr.GetPlayer(itr->first); if (!plr) { - sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); + sLog.outError("BattleGround:CastSpellOnTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); continue; } @@ -606,11 +613,13 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID) { for (BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { + if (itr->second.OfflineRemoveTime) + continue; Player *plr = objmgr.GetPlayer(itr->first); if (!plr) { - sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); + sLog.outError("BattleGround:RewardHonorToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); continue; } @@ -631,11 +640,13 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, for (BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { + if (itr->second.OfflineRemoveTime) + continue; Player *plr = objmgr.GetPlayer(itr->first); if (!plr) { - sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); + sLog.outError("BattleGround:RewardReputationToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); continue; } @@ -722,10 +733,9 @@ void BattleGround::EndBattleGround(uint32 winner) for (BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { - Player *plr = objmgr.GetPlayer(itr->first); uint32 team = itr->second.Team; - if (!plr) + if (itr->second.OfflineRemoveTime) { //if rated arena match - make member lost! if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team) @@ -735,9 +745,11 @@ void BattleGround::EndBattleGround(uint32 winner) else loser_arena_team->OfflineMemberLost(itr->first, winner_rating); } - sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first)); continue; } + Player *plr = objmgr.GetPlayer(itr->first); + if (!plr) + sLog.outError("BattleGround:EndBattleGround Player (GUID: %u) not found!", GUID_LOPART(itr->first)); // should remove spirit of redemption if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) @@ -1077,7 +1089,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac { // a player has left the battleground, so there are free slots -> add to queue AddToBGFreeSlotQueue(); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId()); + sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, GetBracketId()); } // Let others know WorldPacket data; @@ -1104,7 +1116,6 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac // this method is called when no players remains in battleground void BattleGround::Reset() { - SetQueueId(QUEUE_ID_MAX_LEVEL_19); SetWinner(WINNER_NONE); SetStatus(STATUS_WAIT_QUEUE); SetStartTime(0); @@ -1279,16 +1290,15 @@ void BattleGround::EventPlayerLoggedOut(Player* player) m_Players[player->GetGUID()].OfflineRemoveTime = sWorld.GetGameTime() + MAX_OFFLINE_TIME; if (GetStatus() == STATUS_IN_PROGRESS) { - if (isBattleGround()) - EventPlayerDroppedFlag(player); - else - { - //1 player is logging out, if it is the last, then end arena! + // drop flag and handle other cleanups + RemovePlayer(player, player->GetGUID()); + + // 1 player is logging out, if it is the last, then end arena! + if (isArena()) if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam()))) EndBattleGround(GetOtherTeam(player->GetTeam())); - } - return; } + player->LeaveBattleground(); } @@ -1919,3 +1929,9 @@ bool BattleGround::IsTeamScoreInRange(uint32 team, uint32 minScore, uint32 maxSc uint32 score = (m_TeamScores[team_idx] < 0) ? 0 : uint32(m_TeamScores[team_idx]); return score >= minScore && score <= maxScore; } + +void BattleGround::SetBracket( PvPDifficultyEntry const* bracketEntry ) +{ + m_BracketId = bracketEntry->GetBracketId(); + SetLevelRange(bracketEntry->minLevel,bracketEntry->maxLevel); +} diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 67dcfaa5b88..b82884771d5 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -23,6 +23,7 @@ #include "Common.h" #include "SharedDefines.h" +#include "DBCEnums.h" class Creature; class GameObject; @@ -31,6 +32,7 @@ class Player; class WorldPacket; class BattleGroundMap; +struct PvPDifficultyEntry; struct WorldSafeLocsEntry; enum BattleGroundSounds @@ -166,19 +168,6 @@ enum BattleGroundQueueTypeId MAX_BATTLEGROUND_QUEUE_TYPES }; -enum BGQueueIdBasedOnLevel // queue_id for level ranges -{ - QUEUE_ID_MAX_LEVEL_19 = 0, - QUEUE_ID_MAX_LEVEL_29 = 1, - QUEUE_ID_MAX_LEVEL_39 = 2, - QUEUE_ID_MAX_LEVEL_49 = 3, - QUEUE_ID_MAX_LEVEL_59 = 4, - QUEUE_ID_MAX_LEVEL_69 = 5, - QUEUE_ID_MAX_LEVEL_79 = 6, - QUEUE_ID_MAX_LEVEL_80 = 7 -}; -#define MAX_BATTLEGROUND_QUEUES 8 - enum ScoreType { SCORE_KILLING_BLOWS = 1, @@ -325,7 +314,7 @@ class BattleGround // Get methods: char const* GetName() const { return m_Name; } BattleGroundTypeId GetTypeID() const { return m_TypeID; } - BGQueueIdBasedOnLevel GetQueueId() const { return m_QueueId; } + BattleGroundBracketId GetBracketId() const { return m_BracketId; } uint32 GetInstanceID() const { return m_InstanceID; } BattleGroundStatus GetStatus() const { return m_Status; } uint32 GetClientInstanceID() const { return m_ClientInstanceID; } @@ -351,12 +340,7 @@ class BattleGround void SetName(char const* Name) { m_Name = Name; } void SetTypeID(BattleGroundTypeId TypeID) { m_TypeID = TypeID; } //here we can count minlevel and maxlevel for players - void SetQueueId(BGQueueIdBasedOnLevel ID) - { - m_QueueId = ID; - uint8 diff = (m_TypeID == BATTLEGROUND_AV) ? 1 : 0; - this->SetLevelRange((ID + 1) * 10 + diff, (ID + 2) * 10 - ((diff + 1) % 2)); - } + void SetBracket(PvPDifficultyEntry const* bracketEntry); void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } void SetStatus(BattleGroundStatus Status) { m_Status = Status; } void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; } @@ -588,7 +572,7 @@ class BattleGround uint32 m_StartTime; int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself uint32 m_LastResurrectTime; - BGQueueIdBasedOnLevel m_QueueId; + BattleGroundBracketId m_BracketId; uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 624bf6aa801..e20ee99efc9 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -153,7 +153,7 @@ void BattleGroundEY::CheckSomeoneJoinedPoint() Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[EY_POINTS_MAX][j]); if (!plr) { - sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[EY_POINTS_MAX][j])); + sLog.outError("BattleGroundEY:CheckSomeoneJoinedPoint: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[EY_POINTS_MAX][j])); ++j; continue; } @@ -193,7 +193,7 @@ void BattleGroundEY::CheckSomeoneLeftPoint() Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[i][j]); if (!plr) { - sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j])); + sLog.outError("BattleGroundEY:CheckSomeoneLeftPoint Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j])); //move not existed player to "free space" - this will cause many error showing in log, but it is a very important bug m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 7e77f3fff20..0f82c2404ab 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -112,6 +112,11 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) return; } + // expected bracket entry + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + return; + // check queueing conditions if (!joinAsGroup) { @@ -137,7 +142,7 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) // no group found, error if (!grp) return; - uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); + uint32 err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { @@ -148,11 +153,12 @@ void WorldSession::HandleBattlemasterJoinOpcode( 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)); + BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); + GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0); + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); @@ -166,13 +172,14 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); 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"); } else { + GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0); + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); @@ -180,13 +187,9 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); SendPacket(&data); - - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); 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); + sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); } void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv_data*/ ) @@ -303,7 +306,6 @@ void WorldSession::HandleBattleFieldPortOpcode( 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 uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 @@ -312,186 +314,137 @@ void WorldSession::HandleBattleFieldPortOpcode( WorldPacket &recv_data ) if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { - 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 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; - 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, arenatype); - SendPacket(&data); - } - } + sLog.outError("BattlegroundHandler: invalid bgtype (%u) received.", bgTypeId_); + 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 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()) + 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->GetGUID(), &ginfo)) { - sLog.outError("Battleground: itrplayerstatus not found."); + sLog.outError("BattlegroundHandler: itrplayerstatus not found."); return; } - - instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; // if action == 1, then instanceId is required - if (!instanceId && action == 1) + if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) { - sLog.outError("Battleground: instance not found."); + sLog.outError("BattlegroundHandler: instance not found."); return; } - BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId); + 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("Battleground: bg_template not found for type id %u.", bgTypeId); + sLog.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); return; } - if (_player->InBattleGroundQueue()) + // expected bracket entry + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + return; + + //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it + if (action == 1 && ginfo.ArenaType == 0) { - //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) + //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue + if (!_player->CanJoinToBattleground()) { - //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; - } + //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()); } - uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); - WorldPacket data; - switch( action ) + //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()) { - case 1: // port to battleground - if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) - return; // cheating? + 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? + if (!_player->InBattleGround()) _player->SetBattleGroundEntryPoint(); - // resurrect the player - if (!_player->isAlive()) - { - _player->ResurrectPlayer(1.0f); - _player->SpawnCorpseBones(); - } - // stop taxi flight at port - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - - } + // 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(); + } - 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 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); - // clear AFK - if(_player->isAFK()) - _player->ToggleAFK(); - // bg->HandleBeforeTeleportToBattleGround(_player); - 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); - break; - case 0: // leave queue - // if player leaves rated arena match before match start, it is counted as he played but he lost - if (isRated) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType()); + _player->GetSession()->SendPacket(&data); + // remove battleground queue status from BGmgr + bgQueue.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(ginfo.Team); + // bg->HandleBeforeTeleportToBattleGround(_player); + sBattleGroundMgr.SendToBattleGround(_player, ginfo.IsInvitedToBGInstanceGUID, 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); + break; + case 0: // leave queue + // if player leaves rated arena match before match start, it is counted as he played but he lost + if (ginfo.IsRated) + { + ArenaTeam * at = objmgr.GetArenaTeamById(ginfo.Team); + if (at) { - ArenaTeam * at = objmgr.GetArenaTeamById(team); - 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(); - } + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), ginfo.OpponentsTeamRating); + at->MemberLost(_player, ginfo.OpponentsTeamRating); + 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, queueSlot, STATUS_NONE, 0, 0, 0); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); - // 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); - break; - default: - sLog.outError("Battleground port: unknown action %u", action); - break; - } + } + _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); + bgQueue.RemovePlayer(_player->GetGUID(), true); + // player left queue, we should update it - do not update Arena Queue + if (!ginfo.ArenaType) + sBattleGroundMgr.ScheduleQueueUpdate(ginfo.ArenaTeamRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); + SendPacket(&data); + 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); + break; } } @@ -544,16 +497,16 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) } //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()) + BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; + GroupQueueInfo ginfo; + if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) continue; - if (itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) + if (ginfo.IsInvitedToBGInstanceGUID) { - bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId); + bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); if (!bg) continue; - uint32 remainingTime = getMSTimeDiff(getMSTime(), itrPlayerStatus->second.GroupInfo->RemoveInviteTime); + uint32 remainingTime = getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime); // send status invited to BattleGround sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType); SendPacket(&data); @@ -563,9 +516,15 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) continue; - uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); + + // expected bracket entry + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + continue; + + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId()); // send status in BattleGround Queue - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(itrPlayerStatus->second.GroupInfo->JoinTime, getMSTime()), arenaType); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, getMSTime()), arenaType); SendPacket(&data); } } @@ -657,8 +616,8 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) } //check existance - BattleGround* bg = NULL; - if (!(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA))) + BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA); + if (!bg) { sLog.outError("Battleground: template bg (all arenas) not found"); return; @@ -666,6 +625,9 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) BattleGroundTypeId bgTypeId = bg->GetTypeID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + return; // check queueing conditions if (!asGroup) @@ -684,7 +646,7 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) // no group found, error if (!grp) return; - uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); + uint32 err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); @@ -725,8 +687,7 @@ void WorldSession::HandleBattlemasterJoinArena( 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)); + BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (asGroup) { sLog.outDebug("Battleground: arena join as group start"); @@ -738,6 +699,8 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) else bg->SetRated(false); + GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); @@ -751,25 +714,24 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); 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"); - if (isRated) - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); + //announce to world ... removed } else { + GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); 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); + sBattleGroundMgr.ScheduleQueueUpdate(arenaRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); } void WorldSession::HandleReportPvPAFK( WorldPacket & recv_data ) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index d3f79b25576..f7d0e3e2293 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -56,13 +56,13 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr ); BattleGroundQueue::BattleGroundQueue() { - for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) + for (uint32 i = 0; i < BG_TEAMS_COUNT; ++i) { - for (uint32 j = 0; j < MAX_BATTLEGROUND_QUEUES; j++) + for (uint32 j = 0; j < MAX_BATTLEGROUND_BRACKETS; ++j) { m_SumOfWaitTimes[i][j] = 0; m_WaitTimeLastPlayer[i][j] = 0; - for (uint32 k = 0; k < COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; k++) + for (uint32 k = 0; k < COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; ++k) m_WaitTimes[i][j][k] = 0; } } @@ -71,9 +71,9 @@ BattleGroundQueue::BattleGroundQueue() BattleGroundQueue::~BattleGroundQueue() { m_QueuedPlayers.clear(); - for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) + for (int i = 0; i < MAX_BATTLEGROUND_BRACKETS; ++i) { - for (uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_COUNT; j++) + for (uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_COUNT; ++j) { for (GroupsQueueType::iterator itr = m_QueuedGroups[i][j].begin(); itr!= m_QueuedGroups[i][j].end(); ++itr) delete (*itr); @@ -149,14 +149,12 @@ bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 de /*** BATTLEGROUND QUEUES ***/ /*********************************************************/ -// add group to bg queue with the given leader and bg specifications -GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId BgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 arenateamid) +// add group or player (grp == NULL) to bg queue with the given leader and bg specifications +GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, Group* grp, BattleGroundTypeId BgTypeId, PvPDifficultyEntry const* backetEntry, uint8 ArenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 arenateamid) { - BGQueueIdBasedOnLevel queue_id = leader->GetBattleGroundQueueIdFromLevel(BgTypeId); + BattleGroundBracketId bracketId = backetEntry->GetBracketId(); // create new ginfo - // cannot use the method like in addplayer, because that could modify an in-queue group's stats - // (e.g. leader leaving queue then joining as individual again) GroupQueueInfo* ginfo = new GroupQueueInfo; ginfo->BgTypeId = BgTypeId; ginfo->ArenaType = ArenaType; @@ -177,27 +175,84 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId index += BG_TEAMS_COUNT; if (ginfo->Team == HORDE) index++; - sLog.outDebug("Adding Group to BattleGroundQueue bgTypeId : %u, queue_id : %u, index : %u", BgTypeId, queue_id, index); + sLog.outDebug("Adding Group to BattleGroundQueue bgTypeId : %u, bracket_id : %u, index : %u", BgTypeId, bracketId, index); - m_QueuedGroups[queue_id][index].push_back(ginfo); + uint32 lastOnlineTime = getMSTime(); - // return ginfo, because it is needed to add players to this group info - return ginfo; -} + //announce world (this don't need mutex) + if (isRated && sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE)) + { + sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating); + } -//add player to playermap -void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) -{ - //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak - PlayerQueueInfo& info = m_QueuedPlayers[plr->GetGUID()]; - info.LastOnlineTime = getMSTime(); - info.GroupInfo = ginfo; + //add players from group to ginfo + { + //ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_Lock); + if (grp) + { + for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if(!member) + continue; // this should never happen + PlayerQueueInfo& pl_info = m_QueuedPlayers[member->GetGUID()]; + pl_info.LastOnlineTime = lastOnlineTime; + pl_info.GroupInfo = ginfo; + // add the pinfo to ginfo's list + ginfo->Players[member->GetGUID()] = &pl_info; + } + } + else + { + PlayerQueueInfo& pl_info = m_QueuedPlayers[leader->GetGUID()]; + pl_info.LastOnlineTime = lastOnlineTime; + pl_info.GroupInfo = ginfo; + ginfo->Players[leader->GetGUID()] = &pl_info; + } + + //add GroupInfo to m_QueuedGroups + m_QueuedGroups[bracketId][index].push_back(ginfo); - // add the pinfo to ginfo's list - ginfo->Players[plr->GetGUID()] = &info; + //announce to world, this code needs mutex + if (!isRated && !isPremade && sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE)) + { + if (BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId)) + { + char const* bgName = bg->GetName(); + uint32 MinPlayers = bg->GetMinPlayersPerTeam(); + uint32 qHorde = 0; + uint32 qAlliance = 0; + uint32 q_min_level = backetEntry->minLevel; + uint32 q_max_level = backetEntry->maxLevel; + GroupsQueueType::const_iterator itr; + for(itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr) + if (!(*itr)->IsInvitedToBGInstanceGUID) + qAlliance += (*itr)->Players.size(); + for(itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE].end(); ++itr) + if (!(*itr)->IsInvitedToBGInstanceGUID) + qHorde += (*itr)->Players.size(); + + // Show queue status to player only (when joining queue) + if (sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) + { + ChatHandler(leader).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName, q_min_level, q_max_level, + qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0); + } + // System message + else + { + sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level, + qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0); + } + } + } + //release mutex + } + + return ginfo; } -void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id) +void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BattleGroundBracketId bracket_id) { uint32 timeInQueue = getMSTimeDiff(ginfo->JoinTime, getMSTime()); uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas! @@ -213,19 +268,19 @@ void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* g } //store pointer to arrayindex of player that was added first - uint32* lastPlayerAddedPointer = &(m_WaitTimeLastPlayer[team_index][queue_id]); + uint32* lastPlayerAddedPointer = &(m_WaitTimeLastPlayer[team_index][bracket_id]); //remove his time from sum - m_SumOfWaitTimes[team_index][queue_id] -= m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)]; + m_SumOfWaitTimes[team_index][bracket_id] -= m_WaitTimes[team_index][bracket_id][(*lastPlayerAddedPointer)]; //set average time to new - m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)] = timeInQueue; + m_WaitTimes[team_index][bracket_id][(*lastPlayerAddedPointer)] = timeInQueue; //add new time to sum - m_SumOfWaitTimes[team_index][queue_id] += timeInQueue; + m_SumOfWaitTimes[team_index][bracket_id] += timeInQueue; //set index of last player added to next one (*lastPlayerAddedPointer)++; (*lastPlayerAddedPointer) %= COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; } -uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id) +uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BattleGroundBracketId bracket_id) { uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas! if (!ginfo->ArenaType) @@ -239,8 +294,8 @@ uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueue team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE } //check if there is enought values(we always add values > 0) - if (m_WaitTimes[team_index][queue_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1] ) - return (m_SumOfWaitTimes[team_index][queue_id] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME); + if (m_WaitTimes[team_index][bracket_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1] ) + return (m_SumOfWaitTimes[team_index][bracket_id] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME); else //if there aren't enough values return 0 - not available return 0; @@ -251,7 +306,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou { //Player *plr = objmgr.GetPlayer(guid); - int32 queue_id = -1; // signed for proper for-loop finish + int32 bracket_id = -1; // signed for proper for-loop finish QueuedPlayersMap::iterator itr; //remove player from map, if he's there @@ -269,17 +324,17 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou // variable index removes useless searching in other team's queue uint32 index = (group->Team == HORDE) ? BG_TEAM_HORDE : BG_TEAM_ALLIANCE; - for (int32 queue_id_tmp = MAX_BATTLEGROUND_QUEUES - 1; queue_id_tmp >= 0 && queue_id == -1; --queue_id_tmp) + for (int32 bracket_id_tmp = MAX_BATTLEGROUND_BRACKETS - 1; bracket_id_tmp >= 0 && bracket_id == -1; --bracket_id_tmp) { //we must check premade and normal team's queue - because when players from premade are joining bg, //they leave groupinfo so we can't use its players size to find out index for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT; j += BG_QUEUE_NORMAL_ALLIANCE) { - for (group_itr_tmp = m_QueuedGroups[queue_id_tmp][j].begin(); group_itr_tmp != m_QueuedGroups[queue_id_tmp][j].end(); ++group_itr_tmp) + for(group_itr_tmp = m_QueuedGroups[bracket_id_tmp][j].begin(); group_itr_tmp != m_QueuedGroups[bracket_id_tmp][j].end(); ++group_itr_tmp) { if ((*group_itr_tmp) == group) { - queue_id = queue_id_tmp; + bracket_id = bracket_id_tmp; group_itr = group_itr_tmp; //we must store index to be able to erase iterator index = j; @@ -289,12 +344,12 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou } } //player can't be in queue without group, but just in case - if (queue_id == -1) + if (bracket_id == -1) { sLog.outError("BattleGroundQueue: ERROR Cannot find groupinfo for player GUID: %u", GUID_LOPART(guid)); return; } - sLog.outDebug("BattleGroundQueue: Removing player GUID %u, from queue_id %u", GUID_LOPART(guid), (uint32)queue_id); + sLog.outDebug("BattleGroundQueue: Removing player GUID %u, from bracket_id %u", GUID_LOPART(guid), (uint32)bracket_id); // ALL variables are correctly set // We can ignore leveling up in queue - it should not cause crash @@ -317,9 +372,9 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou // remove player queue info m_QueuedPlayers.erase(itr); - //if we left BG queue(not porting) OR if arena team left queue for rated match - if ((decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty())) - AnnounceWorld(group, guid, false); + // announce to world if arena team left queue for rated match, show only once + if (group->ArenaType && group->IsRated && group->Players.empty() && sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE)) + sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, group->ArenaType, group->ArenaType, group->ArenaTeamRating); //if player leaves queue and he is invited to rated arena match, then he have to loose if (group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount) @@ -340,7 +395,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou // remove group queue info if needed if (group->Players.empty()) { - m_QueuedGroups[queue_id][index].erase(group_itr); + m_QueuedGroups[bracket_id][index].erase(group_itr); delete group; } // if group wasn't empty, so it wasn't deleted, and player have left a rated @@ -366,78 +421,22 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou } } -//Announce world message -void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue) +//returns true when player pl_guid is in queue and is invited to bgInstanceGuid +bool BattleGroundQueue::IsPlayerInvited(const uint64& pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime) { - if(ginfo->ArenaType) //if Arena - { - if (sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated) - { - BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId); - if (!bg) - return; - - char const* bgName = bg->GetName(); - if (isAddedToQueue) - { - if (sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY)) - { - if(Player *plr = objmgr.GetPlayer(playerGUID)) - ChatHandler(plr).PSendSysMessage(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating); - } - else - sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating); - } - else - { - if (sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY)) - { - if(Player *plr = objmgr.GetPlayer(playerGUID)) - ChatHandler(plr).PSendSysMessage(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating); - } - else - sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating); - } - } - } - else //if BG - { - if (sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE)) - { - Player *plr = objmgr.GetPlayer(playerGUID); - BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId); - if (!bg || !plr) - return; + QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(pl_guid); + return ( qItr != m_QueuedPlayers.end() + && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == bgInstanceGuid + && qItr->second.GroupInfo->RemoveInviteTime == removeTime ); +} - BGQueueIdBasedOnLevel queue_id = plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID()); - char const* bgName = bg->GetName(); - uint32 MinPlayers = bg->GetMinPlayersPerTeam(); - uint32 qHorde = 0; - uint32 qAlliance = 0; - uint32 q_min_level = (queue_id + 1) * 10; - uint32 q_max_level = std::min(q_min_level + 9, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - GroupsQueueType::const_iterator itr; - for (itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr) - if (!(*itr)->IsInvitedToBGInstanceGUID) - qAlliance += (*itr)->Players.size(); - for (itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].end(); ++itr) - if (!(*itr)->IsInvitedToBGInstanceGUID) - qHorde += (*itr)->Players.size(); - - // Show queue status to player only (when joining queue) - if (sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) - { - ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, - bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers); - } - // System message - else - { - sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, - bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers); - } - } - } +bool BattleGroundQueue::GetPlayerGroupInfoData(const uint64& guid, GroupQueueInfo* ginfo) +{ + QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(guid); + if (qItr == m_QueuedPlayers.end()) + return false; + *ginfo = *(qItr->second.GroupInfo); + return true; } bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side) @@ -453,7 +452,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); BattleGroundTypeId bgTypeId = bg->GetTypeID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, bg->GetArenaType()); - BGQueueIdBasedOnLevel queue_id = bg->GetQueueId(); + BattleGroundBracketId bracket_id = bg->GetBracketId(); // set ArenaTeamId for rated matches if (bg->isArena() && bg->isRated()) @@ -471,7 +470,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b continue; // invite the player - PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id); + PlayerInvitedToBGUpdateAverageWaitTime(ginfo, bracket_id); //sBattleGroundMgr.InvitePlayer(plr, bg, ginfo->Team); // set invited player counters @@ -480,7 +479,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b plr->SetInviteForBattleGroundQueueType(bgQueueTypeId, ginfo->IsInvitedToBGInstanceGUID); // create remind invite events - BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->RemoveInviteTime); + BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime); plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME)); // create automatic remove events BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo->RemoveInviteTime); @@ -507,22 +506,22 @@ This function is inviting players to already running battlegrounds Invitation type is based on config file large groups are disadvantageous, because they will be kicked first if invitation type = 1 */ -void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id) +void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BattleGroundBracketId bracket_id) { int32 hordeFree = bg->GetFreeSlotsForTeam(HORDE); int32 aliFree = bg->GetFreeSlotsForTeam(ALLIANCE); //iterator for iterating through bg queue - GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].begin(); + GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].begin(); //count of groups in queue - used to stop cycles - uint32 aliCount = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].size(); + uint32 aliCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].size(); //index to queue which group is current uint32 aliIndex = 0; for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); aliIndex++) ++Ali_itr; //the same thing for horde - GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].begin(); - uint32 hordeCount = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].size(); + GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].begin(); + uint32 hordeCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].size(); uint32 hordeIndex = 0; for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); hordeIndex++) ++Horde_itr; @@ -585,22 +584,22 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel // this method checks if premade versus premade battleground is possible // then after 30 mins (default) in queue it moves premade group to normal queue // it tries to invite as much players as it can - to MaxPlayersPerTeam, because premade groups have more than MinPlayersPerTeam players -bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam) +bool BattleGroundQueue::CheckPremadeMatch(BattleGroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam) { //check match - if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty()) + if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].empty()) { //start premade match //if groups aren't invited GroupsQueueType::const_iterator ali_group, horde_group; - for (ali_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++ali_group) + for( ali_group = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); ali_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++ali_group) if (!(*ali_group)->IsInvitedToBGInstanceGUID) break; - for (horde_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].begin(); horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end(); ++horde_group) + for( horde_group = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].begin(); horde_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].end(); ++horde_group) if (!(*horde_group)->IsInvitedToBGInstanceGUID) break; - if (ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end()) + if (ali_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].end()) { m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam); m_SelectionPools[BG_TEAM_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam); @@ -609,7 +608,7 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 GroupsQueueType::const_iterator itr; for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) { - for (itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr) + for(itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr) { //if itr can join BG and player count is less that maxPlayers, then add group to selectionpool if (!(*itr)->IsInvitedToBGInstanceGUID && !m_SelectionPools[i].AddGroup((*itr), maxPlayers)) @@ -627,14 +626,14 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 uint32 time_before = getMSTime() - sWorld.getConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH); for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) { - if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty()) + if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty()) { - GroupsQueueType::iterator itr = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin(); + GroupsQueueType::iterator itr = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin(); if (!(*itr)->IsInvitedToBGInstanceGUID && ((*itr)->JoinTime < time_before || (*itr)->Players.size() < MinPlayersPerTeam)) { //we must insert group to normal queue and erase pointer from premade queue - m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].push_front((*itr)); - m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].erase(itr); + m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].push_front((*itr)); + m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].erase(itr); } } } @@ -643,13 +642,13 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 } // this method tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam -bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 minPlayers, uint32 maxPlayers) +bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BattleGroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers) { GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT]; for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) { - itr_team[i] = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); - for (; itr_team[i] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++(itr_team[i])) + itr_team[i] = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); + for(; itr_team[i] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++(itr_team[i])) { if (!(*(itr_team[i]))->IsInvitedToBGInstanceGUID) { @@ -668,7 +667,7 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas { //we will try to invite more groups to team with less players indexed by j ++(itr_team[j]); //this will not cause a crash, because for cycle above reached break; - for (; itr_team[j] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j])) + for(; itr_team[j] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j])) { if (!(*(itr_team[j]))->IsInvitedToBGInstanceGUID) if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount())) @@ -686,7 +685,7 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas } // this method will check if we can invite players to same faction skirmish match -bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_id, uint32 minPlayersPerTeam) +bool BattleGroundQueue::CheckSkirmishForSameFaction(BattleGroundBracketId bracket_id, uint32 minPlayersPerTeam) { if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < minPlayersPerTeam) return false; @@ -704,16 +703,16 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_ //store last ginfo pointer GroupQueueInfo* ginfo = m_SelectionPools[teamIndex].SelectedGroups.back(); //set itr_team to group that was added to selection pool latest - GroupsQueueType::iterator itr_team = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].begin(); - for (; itr_team != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team) + GroupsQueueType::iterator itr_team = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].begin(); + for(; itr_team != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team) if (ginfo == *itr_team) break; - if (itr_team == m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end()) + if (itr_team == m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end()) return false; GroupsQueueType::iterator itr_team2 = itr_team; ++itr_team2; //invite players to other selection pool - for (; itr_team2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2) + for(; itr_team2 != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2) { //if selection pool is full then break; if (!(*itr_team2)->IsInvitedToBGInstanceGUID && !m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam)) @@ -728,15 +727,15 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_ //set correct team (*itr)->Team = otherTeamId; //add team to other queue - m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + otherTeam].push_front(*itr); + m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + otherTeam].push_front(*itr); //remove team from old queue GroupsQueueType::iterator itr2 = itr_team; ++itr2; - for (; itr2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr2) + for(; itr2 != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr2) { if (*itr2 == *itr) { - m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].erase(itr2); + m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].erase(itr2); break; } } @@ -749,24 +748,24 @@ this method is called when group is inserted, or player / group is removed from it must be called after fully adding the members of a group to ensure group joining should be called from BattleGround::RemovePlayer function in some cases */ -void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated, uint32 arenaRating) +void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating) { //if no players in queue - do nothing - if( m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && - m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() && - m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].empty() && - m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].empty() ) + if( m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && + m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].empty() && + m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].empty() && + m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].empty() ) return; //battleground with free slot for player should be always in the beggining of the queue - // maybe it would be better to create bgfreeslotqueue for each queue_id_based_on_level + // maybe it would be better to create bgfreeslotqueue for each bracket_id BGFreeSlotQueueType::iterator itr, next; for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) { next = itr; ++next; // DO NOT allow queue manager to invite new player to arena - if( (*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueId() == queue_id && + if( (*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetBracketId() == bracket_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE ) { BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!) @@ -777,7 +776,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve m_SelectionPools[BG_TEAM_HORDE].Init(); // call a function that does the job for us - FillPlayersToBG(bg, queue_id); + FillPlayersToBG(bg, bracket_id); // now everything is set, invite players for (GroupsQueueType::const_iterator citr = m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.begin(); citr != m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.end(); ++citr) @@ -801,6 +800,14 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId); return; } + + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketById(bg_template->GetMapId(),bracket_id); + if (!bracketEntry) + { + sLog.outError("Battleground: Update: bg bracket entry not found for map %u bracket id %u", bg_template->GetMapId(), bracket_id); + return; + } + // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!) uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam(); uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam(); @@ -842,11 +849,11 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if (bg_template->isBattleGround()) { //check if there is premade against premade match - if (CheckPremadeMatch(queue_id, MinPlayersPerTeam, MaxPlayersPerTeam)) + if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam)) { //create new battleground - BattleGround * bg2 = NULL; - if (!(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, 0, false))) + BattleGround * bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, bracketEntry, 0, false); + if (!bg2) { sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId); return; @@ -867,12 +874,12 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if (!isRated) { // if there are enough players in pools, start new battleground or non rated arena - if (CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam) - || (bg_template->isArena() && CheckSkirmishForSameFaction(queue_id, MinPlayersPerTeam)) ) + if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam) + || (bg_template->isArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam)) ) { // we successfully created a pool - BattleGround * bg2 = NULL; - if (!(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, false))) + BattleGround * bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, bracketEntry, arenaType, false); + if (!bg2) { sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId); return; @@ -895,14 +902,14 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve { GroupQueueInfo* front1 = NULL; GroupQueueInfo* front2 = NULL; - if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty()) + if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].empty()) { - front1 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].front(); + front1 = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].front(); arenaRating = front1->ArenaTeamRating; } - if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty()) + if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].empty()) { - front2 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].front(); + front2 = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].front(); arenaRating = front2->ArenaTeamRating; } if (front1 && front2) @@ -932,8 +939,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve for (uint32 i = BG_QUEUE_PREMADE_ALLIANCE; i < BG_QUEUE_NORMAL_ALLIANCE; i++) { // take the group that joined first - itr_team[i] = m_QueuedGroups[queue_id][i].begin(); - for (; itr_team[i] != m_QueuedGroups[queue_id][i].end(); ++(itr_team[i])) + itr_team[i] = m_QueuedGroups[bracket_id][i].begin(); + for(; itr_team[i] != m_QueuedGroups[bracket_id][i].end(); ++(itr_team[i])) { // if group match conditions, then add it to pool if( !(*itr_team[i])->IsInvitedToBGInstanceGUID @@ -954,7 +961,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve { itr_team[BG_TEAM_ALLIANCE] = itr_team[BG_TEAM_HORDE]; ++itr_team[BG_TEAM_ALLIANCE]; - for (; itr_team[BG_TEAM_ALLIANCE] != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end(); ++(itr_team[BG_TEAM_ALLIANCE])) + for(; itr_team[BG_TEAM_ALLIANCE] != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].end(); ++(itr_team[BG_TEAM_ALLIANCE])) { if( !(*itr_team[BG_TEAM_ALLIANCE])->IsInvitedToBGInstanceGUID && (((*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating <= arenaMaxRating) @@ -970,7 +977,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve { itr_team[BG_TEAM_HORDE] = itr_team[BG_TEAM_ALLIANCE]; ++itr_team[BG_TEAM_HORDE]; - for (; itr_team[BG_TEAM_HORDE] != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++(itr_team[BG_TEAM_HORDE])) + for(; itr_team[BG_TEAM_HORDE] != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++(itr_team[BG_TEAM_HORDE])) { if( !(*itr_team[BG_TEAM_HORDE])->IsInvitedToBGInstanceGUID && (((*itr_team[BG_TEAM_HORDE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_HORDE])->ArenaTeamRating <= arenaMaxRating) @@ -985,8 +992,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve //if we have 2 teams, then start new arena and invite players! if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) { - BattleGround* arena = NULL; - if (!(arena = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, true))) + BattleGround* arena = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, bracketEntry, arenaType, true); + if (!arena) { sLog.outError("BattlegroundQueue::Update couldn't create arena instance for rated arena match!"); return; @@ -1000,16 +1007,16 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if ((*(itr_team[BG_TEAM_ALLIANCE]))->Team != ALLIANCE) { // add to alliance queue - m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[BG_TEAM_ALLIANCE])); + m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[BG_TEAM_ALLIANCE])); // erase from horde queue - m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[BG_TEAM_ALLIANCE]); - itr_team[BG_TEAM_ALLIANCE] = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); + m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[BG_TEAM_ALLIANCE]); + itr_team[BG_TEAM_ALLIANCE] = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); } if ((*(itr_team[BG_TEAM_HORDE]))->Team != HORDE) { - m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[BG_TEAM_HORDE])); - m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[BG_TEAM_HORDE]); - itr_team[BG_TEAM_HORDE] = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].begin(); + m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[BG_TEAM_HORDE])); + m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[BG_TEAM_HORDE]); + itr_team[BG_TEAM_HORDE] = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].begin(); } InviteGroupToBG(*(itr_team[BG_TEAM_ALLIANCE]), arena, ALLIANCE); @@ -1040,17 +1047,15 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); - if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue or in battleground + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue or in battleground { // check if player is invited to this bg - BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; - BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); - if( qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID - && qItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime ) + BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; + if (bgQueue.IsPlayerInvited(m_PlayerGuid, m_BgInstanceGUID, m_RemoveTime)) { WorldPacket data; //we must send remaining time in queue - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, qItr->second.GroupInfo->ArenaType); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, m_ArenaType); plr->GetSession()->SendPacket(&data); } } @@ -1083,22 +1088,19 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) //bg pointer can be NULL! so use it carefully! uint32 queueSlot = plr->GetBattleGroundQueueIndex(m_BgQueueTypeId); - if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue, or in Battleground + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue, or in Battleground { // check if player is in queue for this BG and if we are removing his invite event - BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].m_QueuedPlayers; - BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid); - if( qMapItr != qpMap.end() && qMapItr->second.GroupInfo - && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID - && qMapItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime ) + BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId]; + if (bgQueue.IsPlayerInvited(m_PlayerGuid, m_BgInstanceGUID, m_RemoveTime)) { sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); plr->RemoveBattleGroundQueueId(m_BgQueueTypeId); - sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].RemovePlayer(m_PlayerGuid, true); + bgQueue.RemovePlayer(m_PlayerGuid, true); //update queues if battleground isn't ended - if (bg) - sBattleGroundMgr.ScheduleQueueUpdate(m_BgQueueTypeId, m_BgTypeId, bg->GetQueueId()); + if (bg && bg->isBattleGround() && bg->GetStatus() != STATUS_WAIT_LEAVE) + sBattleGroundMgr.ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetBracketId()); WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); @@ -1140,8 +1142,8 @@ void BattleGroundMgr::DeleteAllBattleGrounds() { BattleGround * bg = itr->second; m_BattleGrounds[i].erase(itr++); - if (!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty()) - m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID()); + if (!m_ClientBattleGroundIds[i][bg->GetBracketId()].empty()) + m_ClientBattleGroundIds[i][bg->GetBracketId()].erase(bg->GetClientInstanceID()); delete bg; } } @@ -1176,8 +1178,8 @@ void BattleGroundMgr::Update(uint32 diff) { BattleGround * bg = itr->second; m_BattleGrounds[i].erase(itr); - if (!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty()) - m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID()); + if (!m_ClientBattleGroundIds[i][bg->GetBracketId()].empty()) + m_ClientBattleGroundIds[i][bg->GetBracketId()].erase(bg->GetClientInstanceID()); delete bg; } } @@ -1186,18 +1188,22 @@ void BattleGroundMgr::Update(uint32 diff) // update scheduled queues if (!m_QueueUpdateScheduler.empty()) { - //copy vector and clear the other - // TODO add lock - // TODO maybe std::list would be better and then unlock after end of cycle - std::vector<uint32> scheduled(m_QueueUpdateScheduler); - m_QueueUpdateScheduler.clear(); - // TODO drop lock + std::vector<uint64> scheduled; + { + //copy vector and clear the other + scheduled = std::vector<uint64>(m_QueueUpdateScheduler); + m_QueueUpdateScheduler.clear(); + //release lock + } + for (uint8 i = 0; i < scheduled.size(); i++) { - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundQueueTypeId(scheduled[i] >> 16); + uint32 arenaRating = scheduled[i] >> 32; + uint8 arenaType = scheduled[i] >> 24 & 255; + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundQueueTypeId(scheduled[i] >> 16 & 255); BattleGroundTypeId bgTypeId = BattleGroundTypeId((scheduled[i] >> 8) & 255); - BGQueueIdBasedOnLevel queue_id = BGQueueIdBasedOnLevel(scheduled[i] & 255); - m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, queue_id); + BattleGroundBracketId bracket_id = BattleGroundBracketId(scheduled[i] & 255); + m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, bracket_id, arenaType, arenaRating > 0, arenaRating); } } @@ -1207,14 +1213,14 @@ void BattleGroundMgr::Update(uint32 diff) // it's time to force update if (m_NextRatingDiscardUpdate < diff) { - // forced update for level 70 rated arenas + // forced update for rated arenas (scan all, but skipped non rated) sLog.outDebug("BattleGroundMgr: UPDATING ARENA QUEUES"); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_2v2, true, 0); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_2v2, true, 0); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_3v3, true, 0); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_3v3, true, 0); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_5v5, true, 0); - m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_5v5, true, 0); + for(int qtype = BATTLEGROUND_QUEUE_2v2; qtype <= BATTLEGROUND_QUEUE_5v5; ++qtype) + for(int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket) + m_BattleGroundQueues[qtype].Update( + BATTLEGROUND_AA, BattleGroundBracketId(bracket), + BattleGroundMgr::BGArenaType(BattleGroundQueueTypeId(qtype)), true, 0); + m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); } else @@ -1484,7 +1490,7 @@ BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTyp return m_BattleGrounds[bgTypeId].empty() ? NULL : m_BattleGrounds[bgTypeId].begin()->second; } -uint32 BattleGroundMgr::CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id) +uint32 BattleGroundMgr::CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BattleGroundBracketId bracket_id) { if (IsArenaType(bgTypeId)) return 0; //arenas don't have client-instanceids @@ -1496,18 +1502,18 @@ uint32 BattleGroundMgr::CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeI // the following works, because std::set is default ordered with "<" // the optimalization would be to use as bitmask std::vector<uint32> - but that would only make code unreadable uint32 lastId = 0; - for (std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();) + for(std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][bracket_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][bracket_id].end();) { if( (++lastId) != *itr) //if there is a gap between the ids, we will break.. break; lastId = *itr; } - m_ClientBattleGroundIds[bgTypeId][queue_id].insert(lastId + 1); + m_ClientBattleGroundIds[bgTypeId][bracket_id].insert(lastId + 1); return lastId + 1; } // create a new battleground that will really be used to play -BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated) +BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated) { // get the template BG BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId); @@ -1589,14 +1595,14 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI // generate a new instance id bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id - bg->SetClientInstanceID(CreateClientVisibleInstanceId(bgTypeId, queue_id)); + bg->SetClientInstanceID(CreateClientVisibleInstanceId(bgTypeId, bracketEntry->GetBracketId())); // reset the new bg (set status to status_wait_queue from status_none) bg->Reset(); // start the joining of the bg bg->SetStatus(STATUS_WAIT_JOIN); - bg->SetQueueId(queue_id); + bg->SetBracket(bracketEntry); bg->SetArenaType(arenaType); bg->SetRated(isRated); @@ -1843,9 +1849,6 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6 if (!plr) return; - uint32 PlayerLevel = 10; - PlayerLevel = plr->getLevel(); - data->Initialize(SMSG_BATTLEFIELD_LIST); *data << uint64(guid); // battlemaster guid *data << uint8(fromWhere); // from where you joined @@ -1865,13 +1868,20 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6 uint32 count = 0; *data << uint32(0); // number of bg instances - uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(bgTypeId); - for (std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end(); ++itr) + if(BattleGround* bgTemplate = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)) { - *data << uint32(*itr); - ++count; + // expected bracket entry + if(PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgTemplate->GetMapId(),plr->getLevel())) + { + BattleGroundBracketId bracketId = bracketEntry->GetBracketId(); + for(std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][bracketId].begin(); itr != m_ClientBattleGroundIds[bgTypeId][bracketId].end();++itr) + { + *data << uint32(*itr); + ++count; + } + data->put<uint32>( count_pos , count); + } } - data->put<uint32>( count_pos , count); } } @@ -2026,11 +2036,11 @@ void BattleGroundMgr::SetHolidayWeekends(uint32 mask) } } -void BattleGroundMgr::ScheduleQueueUpdate(BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id) +void BattleGroundMgr::ScheduleQueueUpdate(uint32 arenaRating, uint8 arenaType, BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BattleGroundBracketId bracket_id) { //This method must be atomic, TODO add mutex - //we will use only 1 number created of bgTypeId and queue_id - uint32 schedule_id = (bgQueueTypeId << 16) | (bgTypeId << 8) | queue_id; + //we will use only 1 number created of bgTypeId and bracket_id + uint64 schedule_id = ((uint64)arenaRating << 32) | (arenaType << 24) | (bgQueueTypeId << 16) | (bgTypeId << 8) | bracket_id; bool found = false; for (uint8 i = 0; i < m_QueueUpdateScheduler.size(); i++) { diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index bddc5291d23..120f05c9982 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -24,6 +24,7 @@ #include "Common.h" #include "Policies/Singleton.h" +#include "DBCEnums.h" #include "BattleGround.h" typedef std::map<uint32, BattleGround*> BattleGroundSet; @@ -74,20 +75,18 @@ class BattleGroundQueue BattleGroundQueue(); ~BattleGroundQueue(); - void Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType = 0, bool isRated = false, uint32 minRating = 0); + void Update(BattleGroundTypeId bgTypeId, BattleGroundBracketId bracket_id, uint8 arenaType = 0, bool isRated = false, uint32 minRating = 0); - void FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id); - bool CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam); - bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 minPlayers, uint32 maxPlayers); - bool CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_id, uint32 minPlayersPerTeam); - GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); - void AddPlayer(Player *plr, GroupQueueInfo *ginfo); + void FillPlayersToBG(BattleGround* bg, BattleGroundBracketId bracket_id); + bool CheckPremadeMatch(BattleGroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam); + bool CheckNormalMatch(BattleGround* bg_template, BattleGroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers); + bool CheckSkirmishForSameFaction(BattleGroundBracketId bracket_id, uint32 minPlayersPerTeam); + GroupQueueInfo * AddGroup(Player* leader, Group* group, BattleGroundTypeId bgTypeId, PvPDifficultyEntry const* backetEntry, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); - void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id); - uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id); - - void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); - void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue); + bool IsPlayerInvited(const uint64& pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime); + bool GetPlayerGroupInfoData(const uint64& guid, GroupQueueInfo* ginfo); + void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BattleGroundBracketId bracket_id); + uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BattleGroundBracketId bracket_id); typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap; QueuedPlayersMap m_QueuedPlayers; @@ -104,7 +103,7 @@ class BattleGroundQueue BG_QUEUE_NORMAL_ALLIANCE is used for normal (or small) alliance groups or non-rated arena matches BG_QUEUE_NORMAL_HORDE is used for normal (or small) horde groups or non-rated arena matches */ - GroupsQueueType m_QueuedGroups[MAX_BATTLEGROUND_QUEUES][BG_QUEUE_GROUP_TYPES_COUNT]; + GroupsQueueType m_QueuedGroups[MAX_BATTLEGROUND_BRACKETS][BG_QUEUE_GROUP_TYPES_COUNT]; // class to select and invite groups to bg class SelectionPool @@ -126,9 +125,9 @@ class BattleGroundQueue private: bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side); - uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; - uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES]; - uint32 m_SumOfWaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES]; + uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; + uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]; + uint32 m_SumOfWaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]; }; /* @@ -138,8 +137,8 @@ class BattleGroundQueue class BGQueueInviteEvent : public BasicEvent { public: - BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 removeTime) : - m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_RemoveTime(removeTime) + BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId, uint8 arenaType, uint32 removeTime) : + m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_ArenaType(arenaType), m_RemoveTime(removeTime) { }; virtual ~BGQueueInviteEvent() {}; @@ -150,6 +149,7 @@ class BGQueueInviteEvent : public BasicEvent uint64 m_PlayerGuid; uint32 m_BgInstanceGUID; BattleGroundTypeId m_BgTypeId; + uint8 m_ArenaType; uint32 m_RemoveTime; }; @@ -201,13 +201,13 @@ class BattleGroundMgr BattleGround* GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId); //there must be uint32 because MAX_BATTLEGROUND_TYPE_ID means unknown BattleGround* GetBattleGroundTemplate(BattleGroundTypeId bgTypeId); - BattleGround* CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated); + BattleGround* CreateNewBattleGround(BattleGroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated); uint32 CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsArena, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); void AddBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId, BattleGround* BG) { m_BattleGrounds[bgTypeId][InstanceID] = BG; }; void RemoveBattleGround(uint32 instanceID, BattleGroundTypeId bgTypeId) { m_BattleGrounds[bgTypeId].erase(instanceID); } - uint32 CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id); + uint32 CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BattleGroundBracketId bracket_id); void CreateInitialBattleGrounds(); void DeleteAllBattleGrounds(); @@ -220,7 +220,7 @@ class BattleGroundMgr BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPE_ID]; - void ScheduleQueueUpdate(BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id); + void ScheduleQueueUpdate(uint32 arenaRating, uint8 arenaType, BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BattleGroundBracketId bracket_id); uint32 GetMaxRatingDifference() const; uint32 GetRatingDiscardTimer() const; uint32 GetPrematureFinishTime() const; @@ -256,8 +256,8 @@ class BattleGroundMgr /* Battlegrounds */ BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID]; - std::vector<uint32>m_QueueUpdateScheduler; - std::set<uint32> m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_QUEUES]; //the instanceids just visible for the client + std::vector<uint64> m_QueueUpdateScheduler; + std::set<uint32> m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_BRACKETS]; //the instanceids just visible for the client uint32 m_NextRatingDiscardUpdate; time_t m_NextAutoDistributionTime; uint32 m_AutoDistributionTimeChecker; diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index 057e73d3bc9..befe5ee3a09 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -190,7 +190,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: { - std::string msg = ""; + std::string msg; recv_data >> msg; if(msg.empty()) @@ -227,9 +227,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) if(!normalizePlayerName(to)) { - WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); - data<<to; - SendPacket(&data); + SendPlayerNotFoundNotice(to); break; } @@ -238,9 +236,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) { - WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); - data<<to; - SendPacket(&data); + SendPlayerNotFoundNotice(to); return; } @@ -250,9 +246,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) uint32 sideb = player->GetTeam(); if( sidea != sideb ) { - WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); - data<<to; - SendPacket(&data); + SendPlayerNotFoundNotice(to); return; } } @@ -263,12 +257,13 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) return; } - GetPlayer()->Whisper(msg, lang,player->GetGUID()); + GetPlayer()->Whisper(msg, lang, player->GetGUID()); } break; case CHAT_MSG_PARTY: + case CHAT_MSG_PARTY_LEADER: { - std::string msg = ""; + std::string msg; recv_data >> msg; if(msg.empty()) @@ -285,22 +280,28 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) // if player is in battleground, he cannot say to battleground members by /p Group *group = GetPlayer()->GetOriginalGroup(); - // so if player hasn't OriginalGroup and his player->GetGroup() is BG raid, then return - if( !group && (!(group = GetPlayer()->GetGroup()) || group->isBGGroup()) ) + if(!group) + { + group = _player->GetGroup(); + if(!group || group->isBGGroup()) + return; + } + + if((type == CHAT_MSG_PARTY_LEADER) && !group->IsLeader(_player->GetGUID())) return; WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_PARTY, lang, NULL, 0, msg.c_str(),NULL); + ChatHandler::FillMessageData(&data, this, type, lang, NULL, 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID())); if(sWorld.getConfig(CONFIG_CHATLOG_PARTY)) sLog.outChat("[PARTY] Player %s tells group with leader %s: %s", GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); - } - break; + } break; + case CHAT_MSG_GUILD: { - std::string msg = ""; + std::string msg; recv_data >> msg; if(msg.empty()) @@ -318,6 +319,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) if (GetPlayer()->GetGuildId()) { Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (guild) guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); @@ -337,7 +339,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) } case CHAT_MSG_OFFICER: { - std::string msg = ""; + std::string msg; recv_data >> msg; if(msg.empty()) @@ -355,6 +357,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) if (GetPlayer()->GetGuildId()) { Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (guild) guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); @@ -366,7 +369,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) } case CHAT_MSG_RAID: { - std::string msg=""; + std::string msg; recv_data >> msg; if(msg.empty()) @@ -383,12 +386,15 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) // if player is in battleground, he cannot say to battleground members by /ra Group *group = GetPlayer()->GetOriginalGroup(); - // so if player hasn't OriginalGroup and his player->GetGroup() is BG raid or his group isn't raid, then return - if ((!group && !(group = GetPlayer()->GetGroup())) || group->isBGGroup() || !group->isRaidGroup()) - return; + if(!group) + { + group = GetPlayer()->GetGroup(); + if(!group || group->isBGGroup() || !group->isRaidGroup()) + return; + } WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL); + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); if(sWorld.getConfig(CONFIG_CHATLOG_RAID)) @@ -397,7 +403,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) } break; case CHAT_MSG_RAID_LEADER: { - std::string msg=""; + std::string msg; recv_data >> msg; if(msg.empty()) @@ -414,11 +420,15 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) // if player is in battleground, he cannot say to battleground members by /ra Group *group = GetPlayer()->GetOriginalGroup(); - if( !group && !(group = GetPlayer()->GetGroup()) || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID())) - return; + if(!group) + { + group = GetPlayer()->GetGroup(); + if(!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID())) + return; + } WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(),NULL); + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); if(sWorld.getConfig(CONFIG_CHATLOG_RAID)) @@ -427,7 +437,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) } break; case CHAT_MSG_RAID_WARNING: { - std::string msg=""; + std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) @@ -442,7 +452,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) WorldPacket data; //in battleground, raid warning is sent only to players in battleground - code is ok - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(),NULL); + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); if(sWorld.getConfig(CONFIG_CHATLOG_RAID)) @@ -452,7 +462,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) case CHAT_MSG_BATTLEGROUND: { - std::string msg=""; + std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) @@ -467,7 +477,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) return; WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(),NULL); + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); if(sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) @@ -477,7 +487,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) case CHAT_MSG_BATTLEGROUND_LEADER: { - std::string msg=""; + std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) @@ -486,13 +496,13 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) if(msg.empty()) break; - //battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() + // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() Group *group = GetPlayer()->GetGroup(); if(!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID())) return; WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(),NULL); + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL); group->BroadcastPacket(&data, false); if(sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) @@ -502,9 +512,8 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) case CHAT_MSG_CHANNEL: { - std::string channel = "", msg = ""; + std::string channel, msg; recv_data >> channel; - recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) @@ -518,10 +527,10 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) { - Channel *chn = cMgr->GetChannel(channel,_player); - if(chn) + + if(Channel *chn = cMgr->GetChannel(channel, _player)) { - chn->Say(_player->GetGUID(),msg.c_str(),lang); + chn->Say(_player->GetGUID(), msg.c_str(), lang); if((chn->HasFlag(CHANNEL_FLAG_TRADE) || chn->HasFlag(CHANNEL_FLAG_GENERAL) || @@ -670,15 +679,15 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) Trinity::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > emote_do(emote_builder); - Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > > emote_worker(GetPlayer(),sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),emote_do); - TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > >, WorldTypeMapContainer > message(emote_worker); + Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do); + TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder> >, WorldTypeMapContainer> message(emote_worker); cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); //Send scripted event call if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) - ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(),text_emote); + ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); } void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) @@ -695,7 +704,7 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) return; WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(),NULL); + ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(), NULL); player->GetSession()->SendPacket(&data); } @@ -704,3 +713,9 @@ void WorldSession::HandleChannelDeclineInvite(WorldPacket &recvPacket) sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); } +void WorldSession::SendPlayerNotFoundNotice(std::string name) +{ + WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, name.size()+1); + data << name; + SendPacket(&data); +} diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h index 715c0933bde..73bf8a2bf9a 100644 --- a/src/game/DBCEnums.h +++ b/src/game/DBCEnums.h @@ -32,6 +32,15 @@ // also see MAX_LEVEL and GT_MAX_LEVEL define #define STRONG_MAX_LEVEL 255 +enum BattleGroundBracketId // bracketId for level ranges +{ + BG_BRACKET_ID_FIRST = 0, + BG_BRACKET_ID_LAST = 15 +}; + +// must be max value in PvPDificulty slot+1 +#define MAX_BATTLEGROUND_BRACKETS 16 + enum AreaTeams { AREATEAM_NONE = 0, diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index 989e94fb2d5..3056b863516 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -107,6 +107,8 @@ MapDifficultyMap sMapDifficultyMap; DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt); +DBCStorage <PvPDifficultyEntry> sPvPDifficultyStore(PvPDifficultyfmt); + DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt); DBCStorage <QuestXPEntry> sQuestXPStore(QuestXPfmt); DBCStorage <QuestFactionRewEntry> sQuestFactionRewardStore(QuestFactionRewardfmt); @@ -216,7 +218,7 @@ void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 83; + const uint32 DBCFilesCount = 84; barGoLink bar(DBCFilesCount); @@ -329,6 +331,12 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMovieStore, dbcPath,"Movie.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sPvPDifficultyStore, dbcPath,"PvpDifficulty.dbc"); + for(uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) + if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) + if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS) + assert(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestXPStore, dbcPath,"QuestXP.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestFactionRewardStore, dbcPath,"QuestFactionReward.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc"); @@ -720,6 +728,30 @@ MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty) return itr != sMapDifficultyMap.end() ? &itr->second : NULL; } +PvPDifficultyEntry const* GetBattlegroundBracketByLevel( uint32 mapid, uint32 level ) +{ + // prevent out-of-range levels for dbc data + if (level > DEFAULT_MAX_LEVEL) + level = DEFAULT_MAX_LEVEL; + + for(uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) + if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) + if (entry->mapId == mapid && entry->minLevel <= level && entry->maxLevel >= level) + return entry; + + return NULL; +} + +PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattleGroundBracketId id) +{ + for(uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) + if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) + if (entry->mapId == mapid && entry->GetBracketId() == id) + return entry; + + return NULL; +} + uint32 const* GetTalentTabPages(uint8 cls) { return sTalentTabPages[cls]; diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h index fb301660525..b6b1380517f 100644 --- a/src/game/DBCStores.h +++ b/src/game/DBCStores.h @@ -59,6 +59,9 @@ MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty); uint32 const* /*[3]*/ GetTalentTabPages(uint8 cls); +PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level); +PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattleGroundBracketId id); + extern DBCStorage <AchievementEntry> sAchievementStore; extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore; extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 15f489573ff..956a7927bbf 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1190,6 +1190,19 @@ struct MovieEntry //uint32 unk2; // 2 always 100 }; +struct PvPDifficultyEntry +{ + //uint32 id; // 0 m_ID + uint32 mapId; // 1 + uint32 bracketId; // 2 + uint32 minLevel; // 3 + uint32 maxLevel; // 4 + uint32 difficulty; // 5 + + // helpers + BattleGroundBracketId GetBracketId() const { return BattleGroundBracketId(bracketId); } +}; + struct QuestSortEntry { uint32 id; // 0 m_ID diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index a323e47501a..e1c705887fd 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -81,6 +81,7 @@ const char MovieEntryfmt[]="nxx"; const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx"; const char QuestXPfmt[]="niiiiiiiiii"; const char QuestFactionRewardfmt[]="niiiiiiiiii"; +const char PvPDifficultyfmt[]="diiiii"; const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii"; const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii"; const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiixiiii"; diff --git a/src/game/Group.cpp b/src/game/Group.cpp index abd1c2c8869..145e9f0e427 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1456,7 +1456,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) SendUpdate(); } -uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) +uint32 Group::CanJoinBattleGroundQueue(BattleGround const* bgOrTemplate, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) { // check for min / max count uint32 memberscount = GetMembersCount(); @@ -1471,7 +1471,10 @@ uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGround if(!reference) return BG_JOIN_ERR_OFFLINE_MEMBER; - BGQueueIdBasedOnLevel queue_id = reference->GetBattleGroundQueueIdFromLevel(bgTypeId); + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgOrTemplate->GetMapId(),reference->getLevel()); + if(!bracketEntry) + return BG_JOIN_ERR_OFFLINE_MEMBER; + uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); uint32 team = reference->GetTeam(); @@ -1486,7 +1489,8 @@ uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGround if(member->GetTeam() != team) return BG_JOIN_ERR_MIXED_FACTION; // not in the same battleground level braket, don't let join - if(member->GetBattleGroundQueueIdFromLevel(bgTypeId) != queue_id) + PvPDifficultyEntry const* memberBracketEntry = GetBattlegroundBracketByLevel(bracketEntry->mapId,member->getLevel()); + if(memberBracketEntry != bracketEntry) return BG_JOIN_ERR_MIXED_LEVELS; // don't let join rated matches if the arena team id doesn't match if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) @@ -1495,7 +1499,7 @@ uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGround if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueTypeId)) return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE; // check for deserter debuff in case not arena queue - if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground()) + if(bgOrTemplate->GetTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground()) return BG_JOIN_ERR_GROUP_DESERTER; // check if member can join any more battleground queues if(!member->HasFreeBattleGroundQueueId()) diff --git a/src/game/Group.h b/src/game/Group.h index 58244d0cc5f..ebac5f095af 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -266,7 +266,7 @@ class Group void ConvertToRaid(); void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } - uint32 CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot); + uint32 CanJoinBattleGroundQueue(BattleGround const* bgOrTemplate, BattleGroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot); void ChangeMembersGroup(const uint64 &guid, const uint8 &group); void ChangeMembersGroup(Player *player, const uint8 &group); diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index f6429d40892..e7d7187d0b5 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -219,10 +219,10 @@ BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId, BattleGroun sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId()); - // 0-59 normal spawn 60-69 difficulty_1, 70-79 difficulty_2, 80 dufficulty_3 - uint8 spawnMode = (bg->GetQueueId() > QUEUE_ID_MAX_LEVEL_59) ? (bg->GetQueueId() - QUEUE_ID_MAX_LEVEL_59) : 0; - while (!GetMapDifficultyData(GetId(), Difficulty(spawnMode))) - spawnMode--; + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),bg->GetMinLevel()); + + uint8 spawnMode = bracketEntry ? bracketEntry->difficulty : REGULAR_DIFFICULTY; + BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode); ASSERT(map->IsBattleGroundOrArena()); map->SetBG(bg); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8bf3371fb98..31959d83ec6 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3676,10 +3676,10 @@ void Player::RemoveArenaSpellCooldowns() next = itr; ++next; SpellEntry const * entry = sSpellStore.LookupEntry(itr->first); - // check if spellentry is present and if the cooldown is less than 15 mins + // check if spellentry is present and if the cooldown is less than 10 mins if( entry && - entry->RecoveryTime <= 15 * MINUTE * IN_MILISECONDS && - entry->CategoryRecoveryTime <= 15 * MINUTE * IN_MILISECONDS ) + entry->RecoveryTime <= 10 * MINUTE * IN_MILISECONDS && + entry->CategoryRecoveryTime <= 10 * MINUTE * IN_MILISECONDS ) { // remove & notify RemoveSpellCooldown(itr->first, true); @@ -20687,24 +20687,17 @@ bool Player::GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const if(!bg) return false; - if(getLevel() < bg->GetMinLevel() || getLevel() > bg->GetMaxLevel()) + // limit check leel to dbc compatible level range + uint32 level = getLevel(); + if (level > DEFAULT_MAX_LEVEL) + level = DEFAULT_MAX_LEVEL; + + if(level < bg->GetMinLevel() || level > bg->GetMaxLevel()) return false; return true; } -BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const -{ - // for ranges 0 - 19, 20 - 29, 30 - 39, 40 - 49, 50 - 59, 60 - 69, 70 - 79, 80 - uint32 queue_id = ( getLevel() / 10) - 1; - if (queue_id >= MAX_BATTLEGROUND_QUEUES) - { - sLog.outError("BattleGround: too high queue_id %u this shouldn't happen", queue_id); - return QUEUE_ID_MAX_LEVEL_80; - } - return BGQueueIdBasedOnLevel(queue_id); -} - float Player::GetReputationPriceDiscount( Creature const* pCreature ) const { FactionTemplateEntry const* vendor_faction = pCreature->getFactionTemplateEntry(); diff --git a/src/game/Player.h b/src/game/Player.h index 34d3c01152a..bfd9225947e 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1982,8 +1982,6 @@ class Player : public Unit, public GridObject<Player> BattleGroundTypeId GetBattleGroundTypeId() const { return m_bgData.bgTypeID; } BattleGround* GetBattleGround() const; - BGQueueIdBasedOnLevel GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const; - bool InBattleGroundQueue() const { for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 60eadb288a5..c302aa80d82 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6219,27 +6219,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger triggered_spell_id = 28810; break; } - // Earthen Power (Rank 1, 2) - case 51523: - case 51524: - { - // Totem itself must be a caster of this spell - Unit* caster = NULL; - for (ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) - { - if ((*itr)->GetEntry() != 2630) - continue; - - caster = (*itr); - break; - } - - if (!caster) - return false; - - caster->CastSpell(caster, 59566, true, castItem, triggeredByAura, originalCaster); - return true; - } } break; } @@ -6851,6 +6830,26 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger { switch(dummySpell->Id) { + // Earthen Power (Rank 1, 2) + case 51523: + case 51524: + { + // Totem itself must be a caster of this spell + Unit* caster = NULL; + for (ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) { + if ((*itr)->GetEntry() != 2630) + continue; + + caster = (*itr); + break; + } + + if (!caster) + return false; + + caster->CastSpell(caster, 59566, true, castItem, triggeredByAura, originalCaster); + return true; + } // Tidal Force case 55198: { diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index ce3974312ab..3631ae36dc8 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -555,6 +555,7 @@ class WorldSession bool processChatmessageFurtherAfterSecurityChecks(std::string&, uint32); void HandleMessagechatOpcode(WorldPacket& recvPacket); + void SendPlayerNotFoundNotice(std::string name); void HandleTextEmoteOpcode(WorldPacket& recvPacket); void HandleChatIgnoredOpcode(WorldPacket& recvPacket); diff --git a/src/scripts/northrend/storm_peaks.cpp b/src/scripts/northrend/storm_peaks.cpp index 134a6a6c3b3..18c02d96777 100644 --- a/src/scripts/northrend/storm_peaks.cpp +++ b/src/scripts/northrend/storm_peaks.cpp @@ -163,7 +163,7 @@ bool GossipSelect_npc_thorim(Player* pPlayer, Creature* pCreature, uint32 uiSend break; case GOSSIP_ACTION_INFO_DEF+4: pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(QUEST_SIBLING_RIVALRY); + pPlayer->CompleteQuest(QUEST_SIBLING_RIVALRY); break; } return true; diff --git a/src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp b/src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp index 861b63858b0..11195e0cc1b 100644 --- a/src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp +++ b/src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp @@ -91,21 +91,29 @@ struct instance_halls_of_lightning : public ScriptedInstance m_uiBjarngrimDoorGUID = pGo->GetGUID(); if (m_auiEncounter[0] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); break; case GO_VOLKHAN_DOOR: m_uiVolkhanDoorGUID = pGo->GetGUID(); if (m_auiEncounter[1] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); break; case GO_IONAR_DOOR: m_uiIonarDoorGUID = pGo->GetGUID(); if (m_auiEncounter[2] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); break; case GO_LOKEN_DOOR: m_uiLokenDoorGUID = pGo->GetGUID(); if (m_auiEncounter[3] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); break; case GO_LOKEN_THRONE: m_uiLokenGlobeGUID = pGo->GetGUID(); diff --git a/src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp b/src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp index 5cb20923fd2..6c45c6a106b 100644 --- a/src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp +++ b/src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp @@ -222,6 +222,8 @@ struct boss_svala_sorrowgraveAI : public ScriptedAI Creature* pRitualChanneler[3]; Unit* pSacrificeTarget; + + bool bSacrificed; ScriptedInstance* pInstance; @@ -231,6 +233,8 @@ struct boss_svala_sorrowgraveAI : public ScriptedAI uiCallFlamesTimer = 10000; uiRitualOfSwordTimer = 20000; uiSacrificeTimer = 8000; + + bSacrificed = false; Phase = NORMAL; @@ -276,7 +280,7 @@ struct boss_svala_sorrowgraveAI : public ScriptedAI } } else uiCallFlamesTimer -= diff; - if (uiRitualOfSwordTimer <= diff) + if (!bSacrificed && uiRitualOfSwordTimer <= diff) { pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); if (pSacrificeTarget) @@ -294,7 +298,7 @@ struct boss_svala_sorrowgraveAI : public ScriptedAI if (mob_ritual_channelerAI *pChannelerAI = CAST_AI(mob_ritual_channelerAI,pRitualChanneler[i]->AI())) pChannelerAI->AttackStartNoMove(pSacrificeTarget); - uiRitualOfSwordTimer = urand(18000,22000); + bSacrificed = true; } } else uiRitualOfSwordTimer -= diff; |