[2] | 1 | /* |
---|
| 2 | * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> |
---|
| 3 | * |
---|
| 4 | * This program is free software; you can redistribute it and/or modify |
---|
| 5 | * it under the terms of the GNU General Public License as published by |
---|
| 6 | * the Free Software Foundation; either version 2 of the License, or |
---|
| 7 | * (at your option) any later version. |
---|
| 8 | * |
---|
| 9 | * This program is distributed in the hope that it will be useful, |
---|
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 12 | * GNU General Public License for more details. |
---|
| 13 | * |
---|
| 14 | * You should have received a copy of the GNU General Public License |
---|
| 15 | * along with this program; if not, write to the Free Software |
---|
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
| 17 | */ |
---|
| 18 | |
---|
| 19 | #include "Common.h" |
---|
| 20 | #include "Player.h" |
---|
| 21 | #include "BattleGroundMgr.h" |
---|
| 22 | #include "BattleGroundAV.h" |
---|
| 23 | #include "BattleGroundAB.h" |
---|
| 24 | #include "BattleGroundEY.h" |
---|
| 25 | #include "BattleGroundWS.h" |
---|
| 26 | #include "BattleGroundNA.h" |
---|
| 27 | #include "BattleGroundBE.h" |
---|
| 28 | #include "BattleGroundAA.h" |
---|
| 29 | #include "BattleGroundRL.h" |
---|
| 30 | #include "SharedDefines.h" |
---|
| 31 | #include "Policies/SingletonImp.h" |
---|
| 32 | #include "MapManager.h" |
---|
| 33 | #include "ObjectMgr.h" |
---|
| 34 | #include "ProgressBar.h" |
---|
| 35 | #include "World.h" |
---|
| 36 | #include "Chat.h" |
---|
| 37 | |
---|
| 38 | INSTANTIATE_SINGLETON_1( BattleGroundMgr ); |
---|
| 39 | |
---|
| 40 | /*********************************************************/ |
---|
| 41 | /*** BATTLEGROUND QUEUE SYSTEM ***/ |
---|
| 42 | /*********************************************************/ |
---|
| 43 | |
---|
| 44 | BattleGroundQueue::BattleGroundQueue() |
---|
| 45 | { |
---|
| 46 | //queues are empty, we don't have to call clear() |
---|
| 47 | for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) |
---|
| 48 | { |
---|
| 49 | m_QueuedPlayers[i].Horde = 0; |
---|
| 50 | m_QueuedPlayers[i].Alliance = 0; |
---|
| 51 | //m_QueuedPlayers[i].AverageTime = 0; |
---|
| 52 | } |
---|
| 53 | } |
---|
| 54 | |
---|
| 55 | BattleGroundQueue::~BattleGroundQueue() |
---|
| 56 | { |
---|
| 57 | for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) |
---|
| 58 | { |
---|
| 59 | m_QueuedPlayers[i].clear(); |
---|
| 60 | } |
---|
| 61 | } |
---|
| 62 | |
---|
| 63 | void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) |
---|
| 64 | { |
---|
| 65 | uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); |
---|
| 66 | |
---|
| 67 | //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak |
---|
| 68 | PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()]; |
---|
| 69 | info.InviteTime = 0; |
---|
| 70 | info.IsInvitedToBGInstanceGUID = 0; |
---|
| 71 | info.LastInviteTime = 0; |
---|
| 72 | info.LastOnlineTime = getMSTime(); |
---|
| 73 | info.Team = plr->GetTeam(); |
---|
| 74 | |
---|
| 75 | //add player to waiting order queue |
---|
| 76 | m_PlayersSortedByWaitTime[queue_id].push_back(plr->GetGUID()); |
---|
| 77 | |
---|
| 78 | if(plr->GetTeam() == ALLIANCE) |
---|
| 79 | ++m_QueuedPlayers[queue_id].Alliance; |
---|
| 80 | else |
---|
| 81 | ++m_QueuedPlayers[queue_id].Horde; |
---|
| 82 | |
---|
| 83 | this->Update(bgTypeId, queue_id); |
---|
| 84 | |
---|
| 85 | if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) |
---|
| 86 | { |
---|
| 87 | BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgTypeId); |
---|
| 88 | char const* bgName = bg->GetName(); |
---|
| 89 | |
---|
| 90 | uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id); |
---|
| 91 | uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id); |
---|
| 92 | |
---|
| 93 | // replace hardcoded max level by player max level for nice output |
---|
| 94 | if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) |
---|
| 95 | q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); |
---|
| 96 | |
---|
| 97 | int8 MinPlayers = bg->GetMinPlayersPerTeam(); |
---|
| 98 | |
---|
| 99 | uint8 qHorde = m_QueuedPlayers[queue_id].Horde; |
---|
| 100 | uint8 qAlliance = m_QueuedPlayers[queue_id].Alliance; |
---|
| 101 | |
---|
| 102 | // Show queue status to player only (when joining queue) |
---|
| 103 | if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) |
---|
| 104 | { |
---|
| 105 | ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, |
---|
| 106 | bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde); |
---|
| 107 | } |
---|
| 108 | // System message |
---|
| 109 | else |
---|
| 110 | { |
---|
| 111 | sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, |
---|
| 112 | bgName, q_min_level, q_max_level, qAlliance, MinPlayers - qAlliance, qHorde, MinPlayers - qHorde); |
---|
| 113 | } |
---|
| 114 | } |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) |
---|
| 118 | { |
---|
| 119 | Player *plr = objmgr.GetPlayer(guid); |
---|
| 120 | |
---|
| 121 | uint32 queue_id = 0; |
---|
| 122 | QueuedPlayersMap::iterator itr; |
---|
| 123 | bool IsSet = false; |
---|
| 124 | if(!plr) |
---|
| 125 | { //player is offline, we need to find him somewhere in queues |
---|
| 126 | /// there is something wrong if this code is run, because we have in queue only online players! |
---|
| 127 | sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); |
---|
| 128 | for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) |
---|
| 129 | { |
---|
| 130 | itr = m_QueuedPlayers[i].find(guid); |
---|
| 131 | if(itr != m_QueuedPlayers[i].end()) |
---|
| 132 | { |
---|
| 133 | queue_id = i; |
---|
| 134 | IsSet = true; |
---|
| 135 | break; |
---|
| 136 | } |
---|
| 137 | } |
---|
| 138 | } |
---|
| 139 | else |
---|
| 140 | { //player is online, we have his level, so we can find exact queue from his level |
---|
| 141 | queue_id = plr->GetBattleGroundQueueIdFromLevel(); |
---|
| 142 | itr = m_QueuedPlayers[queue_id].find(guid); |
---|
| 143 | IsSet = true; |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | //all variables are set, so remove player |
---|
| 147 | //remove player from time queue |
---|
| 148 | m_PlayersSortedByWaitTime[queue_id].remove(guid); |
---|
| 149 | |
---|
| 150 | if (IsSet && itr != m_QueuedPlayers[queue_id].end()) |
---|
| 151 | { |
---|
| 152 | if (!itr->second.IsInvitedToBGInstanceGUID) |
---|
| 153 | { |
---|
| 154 | if(itr->second.Team == ALLIANCE) |
---|
| 155 | --m_QueuedPlayers[queue_id].Alliance; |
---|
| 156 | else |
---|
| 157 | --m_QueuedPlayers[queue_id].Horde; |
---|
| 158 | } |
---|
| 159 | else |
---|
| 160 | { |
---|
| 161 | if (decreaseInvitedCount) |
---|
| 162 | { |
---|
| 163 | BattleGround* bg = sBattleGroundMgr.GetBattleGround(itr->second.IsInvitedToBGInstanceGUID); |
---|
| 164 | if (bg) |
---|
| 165 | bg->DecreaseInvitedCount(itr->second.Team); |
---|
| 166 | } |
---|
| 167 | } |
---|
| 168 | m_QueuedPlayers[queue_id].erase(itr); |
---|
| 169 | } |
---|
| 170 | } |
---|
| 171 | |
---|
| 172 | /* |
---|
| 173 | this method is called when player is inserted, or removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue |
---|
| 174 | add method calls this by itself, the remove method could works in other way, so you have to call this method from other code after calling remove method |
---|
| 175 | */ |
---|
| 176 | void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) |
---|
| 177 | { |
---|
| 178 | if (queue_id >= MAX_BATTLEGROUND_QUEUES) |
---|
| 179 | { |
---|
| 180 | //this is error, that caused crashes (not in , but now it shouldn't) |
---|
| 181 | sLog.outError("BattleGroundQueue::Update() called for non existing queue type - this can cause crash, pls report problem, if this is the last line of error log before crash"); |
---|
| 182 | return; |
---|
| 183 | } |
---|
| 184 | |
---|
| 185 | //if no players in queue ... do nothing |
---|
| 186 | if (this->m_QueuedPlayers[queue_id].Alliance == 0 && this->m_QueuedPlayers[queue_id].Horde == 0) |
---|
| 187 | return; |
---|
| 188 | |
---|
| 189 | //battleground with free slot for player should be always the last in this queue |
---|
| 190 | for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); ++itr) |
---|
| 191 | { |
---|
| 192 | // battleground is running, so if: |
---|
| 193 | // DO NOT allow queue manager to invite new player to running arena |
---|
| 194 | if ((*itr)->isBattleGround() && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) |
---|
| 195 | { |
---|
| 196 | //we must check both teams |
---|
| 197 | BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!) |
---|
| 198 | // and iterator is invalid |
---|
| 199 | |
---|
| 200 | //check if there are some players in queue |
---|
| 201 | if (m_QueuedPlayers[queue_id].Alliance > 0 || m_QueuedPlayers[queue_id].Horde > 0) |
---|
| 202 | { |
---|
| 203 | for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) |
---|
| 204 | { |
---|
| 205 | Player* plr = objmgr.GetPlayer(*itr2); |
---|
| 206 | if (!plr) |
---|
| 207 | { |
---|
| 208 | //something is wrong!, kick player from queue |
---|
| 209 | sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); |
---|
| 210 | uint64 oldval = *itr2; |
---|
| 211 | itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); |
---|
| 212 | RemovePlayer(oldval, true); |
---|
| 213 | continue; |
---|
| 214 | } |
---|
| 215 | |
---|
| 216 | // player will be invited, if in bg there is a free slot for him |
---|
| 217 | if (bg->HasFreeSlotsForTeam(plr->GetTeam())) |
---|
| 218 | { |
---|
| 219 | // iterator to player's queue status |
---|
| 220 | QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); |
---|
| 221 | |
---|
| 222 | // remove him from time queue |
---|
| 223 | itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); |
---|
| 224 | |
---|
| 225 | // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and pls report it) |
---|
| 226 | if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) |
---|
| 227 | continue; |
---|
| 228 | |
---|
| 229 | // check if player is not already invited |
---|
| 230 | if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) |
---|
| 231 | { |
---|
| 232 | itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg->GetInstanceID(); |
---|
| 233 | itrPlayerStatus->second.InviteTime = getMSTime(); |
---|
| 234 | itrPlayerStatus->second.LastInviteTime = getMSTime(); |
---|
| 235 | if(itrPlayerStatus->second.Team == ALLIANCE) |
---|
| 236 | --m_QueuedPlayers[queue_id].Alliance; |
---|
| 237 | else |
---|
| 238 | --m_QueuedPlayers[queue_id].Horde; |
---|
| 239 | sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID()); |
---|
| 240 | |
---|
| 241 | WorldPacket data; |
---|
| 242 | uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); |
---|
| 243 | sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); |
---|
| 244 | plr->GetSession()->SendPacket(&data); |
---|
| 245 | } |
---|
| 246 | } |
---|
| 247 | else |
---|
| 248 | ++itr2; |
---|
| 249 | |
---|
| 250 | //if battleground is FULL, then it is removed from free slot queue - not yet implemented! |
---|
| 251 | if (!bg->HasFreeSlots()) |
---|
| 252 | { |
---|
| 253 | //if bg is full, there is no need to invite other players, so break |
---|
| 254 | break; |
---|
| 255 | //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue |
---|
| 256 | //bg->RemoveFromBGFreeSlotQueue() --- do not uncomment this - not yet implemented |
---|
| 257 | } |
---|
| 258 | } |
---|
| 259 | } |
---|
| 260 | } |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | /* THIS IS A CASE THAT IN QUEUE THERE IS ENOUGHT PLAYERS TO START NEW BG */ |
---|
| 264 | //itr->end is the last BG - template, which is not already started! |
---|
| 265 | |
---|
| 266 | /* here will be a most of change, when we create battlegrounds instantiated */ |
---|
| 267 | /* if (there is enough players to start new BG) |
---|
| 268 | Battleground* newbg = sBattleGroundMgr.CreateNewBattleGround(bgTypeId) |
---|
| 269 | - that function will use the COPY constructor on BattleGround class ( in bg manager we should have one battleground as a template |
---|
| 270 | (battleground template will be used only to create new BGs, it will be an instance of BG class, but it won't ever start) */ |
---|
| 271 | |
---|
| 272 | /* following code is working with current Battleground system and it should be removed, when BGs will work like instances */ |
---|
| 273 | BattleGround* bg2 = sBattleGroundMgr.GetBattleGround(bgTypeId); |
---|
| 274 | if (bg2->GetQueueType() != MAX_BATTLEGROUND_QUEUES || bg2->GetStatus() != STATUS_WAIT_QUEUE) |
---|
| 275 | return; |
---|
| 276 | if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam()) |
---|
| 277 | { |
---|
| 278 | bg2->SetStatus(STATUS_WAIT_JOIN); |
---|
| 279 | bg2->SetQueueType(queue_id); |
---|
| 280 | |
---|
| 281 | for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) |
---|
| 282 | { |
---|
| 283 | Player* plr = objmgr.GetPlayer(*itr2); |
---|
| 284 | if (!plr) |
---|
| 285 | { |
---|
| 286 | //something is wrong!, kick player from queue |
---|
| 287 | sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); |
---|
| 288 | uint64 oldval = *itr2; |
---|
| 289 | itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); |
---|
| 290 | RemovePlayer(oldval, true); |
---|
| 291 | continue; |
---|
| 292 | } |
---|
| 293 | |
---|
| 294 | /* TODO: (i'm not sure this code will be useful: |
---|
| 295 | here should be some condition like if (bg2->isArena() && bg2->isRated()) |
---|
| 296 | { |
---|
| 297 | invite players from 1 certain group on each faction to play arena match |
---|
| 298 | } else if ....and existing code |
---|
| 299 | */ |
---|
| 300 | // player will be invited, if in bg there is a free slot for him |
---|
| 301 | if (bg2->HasFreeSlotsForTeam(plr->GetTeam())) |
---|
| 302 | { |
---|
| 303 | // iterator to player's queue status |
---|
| 304 | QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); |
---|
| 305 | |
---|
| 306 | // remove him from time queue |
---|
| 307 | itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); |
---|
| 308 | |
---|
| 309 | // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and report it) |
---|
| 310 | if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) |
---|
| 311 | continue; |
---|
| 312 | |
---|
| 313 | //check if player is not already invited |
---|
| 314 | if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) |
---|
| 315 | { |
---|
| 316 | itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID(); |
---|
| 317 | itrPlayerStatus->second.InviteTime = getMSTime(); |
---|
| 318 | itrPlayerStatus->second.LastInviteTime = getMSTime(); |
---|
| 319 | |
---|
| 320 | if(itrPlayerStatus->second.Team == ALLIANCE) |
---|
| 321 | --m_QueuedPlayers[queue_id].Alliance; |
---|
| 322 | else |
---|
| 323 | --m_QueuedPlayers[queue_id].Horde; |
---|
| 324 | |
---|
| 325 | sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID()); |
---|
| 326 | |
---|
| 327 | WorldPacket data; |
---|
| 328 | uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); |
---|
| 329 | sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); |
---|
| 330 | plr->GetSession()->SendPacket(&data); |
---|
| 331 | } |
---|
| 332 | } |
---|
| 333 | else |
---|
| 334 | ++itr2; |
---|
| 335 | } |
---|
| 336 | bg2->StartBattleGround(); |
---|
| 337 | } |
---|
| 338 | } |
---|
| 339 | |
---|
| 340 | /*********************************************************/ |
---|
| 341 | /*** BATTLEGROUND QUEUE EVENTS ***/ |
---|
| 342 | /*********************************************************/ |
---|
| 343 | |
---|
| 344 | bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 p_time) |
---|
| 345 | { |
---|
| 346 | Player* plr = objmgr.GetPlayer( m_PlayerGuid ); |
---|
| 347 | |
---|
| 348 | // player logged off (we should do nothing, he is correctly removed from queue in another procedure) |
---|
| 349 | if (!plr) |
---|
| 350 | return true; |
---|
| 351 | |
---|
| 352 | // Player can be in another BG queue and must be removed in normal way in any case |
---|
| 353 | // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG) |
---|
| 354 | // if (plr->GetBattleGroundId() > 0) |
---|
| 355 | // return true; |
---|
| 356 | |
---|
| 357 | BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); |
---|
| 358 | if (!bg) |
---|
| 359 | return true; |
---|
| 360 | |
---|
| 361 | uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); |
---|
| 362 | if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue |
---|
| 363 | { |
---|
| 364 | // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems |
---|
| 365 | BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; |
---|
| 366 | BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); |
---|
| 367 | if (qItr != qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) |
---|
| 368 | { |
---|
| 369 | WorldPacket data; |
---|
| 370 | sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); |
---|
| 371 | plr->GetSession()->SendPacket(&data); |
---|
| 372 | } |
---|
| 373 | } |
---|
| 374 | return true; //event will be deleted |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | void BGQueueInviteEvent::Abort(uint64 /*e_time*/) |
---|
| 378 | { |
---|
| 379 | //this should not be called |
---|
| 380 | sLog.outError("Battleground invite event ABORTED!"); |
---|
| 381 | } |
---|
| 382 | |
---|
| 383 | bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) |
---|
| 384 | { |
---|
| 385 | Player* plr = objmgr.GetPlayer( m_PlayerGuid ); |
---|
| 386 | if (!plr) |
---|
| 387 | // player logged off (we should do nothing, he is correctly removed from queue in another procedure) |
---|
| 388 | return true; |
---|
| 389 | |
---|
| 390 | // Player can be in another BG queue and must be removed in normal way in any case |
---|
| 391 | //if (plr->InBattleGround()) |
---|
| 392 | // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG) |
---|
| 393 | // return true; |
---|
| 394 | |
---|
| 395 | BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); |
---|
| 396 | if (!bg) |
---|
| 397 | return true; |
---|
| 398 | |
---|
| 399 | uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); |
---|
| 400 | if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue (base at player data |
---|
| 401 | { |
---|
| 402 | // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems |
---|
| 403 | BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; |
---|
| 404 | BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); |
---|
| 405 | if (qItr!=qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) |
---|
| 406 | { |
---|
| 407 | plr->RemoveBattleGroundQueueId(bg->GetTypeID()); |
---|
| 408 | sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].RemovePlayer(m_PlayerGuid, true); |
---|
| 409 | sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].Update(bg->GetTypeID(), bg->GetQueueType()); |
---|
| 410 | |
---|
| 411 | WorldPacket data; |
---|
| 412 | sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0); |
---|
| 413 | plr->GetSession()->SendPacket(&data); |
---|
| 414 | } |
---|
| 415 | } |
---|
| 416 | |
---|
| 417 | //event will be deleted |
---|
| 418 | return true; |
---|
| 419 | } |
---|
| 420 | |
---|
| 421 | void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) |
---|
| 422 | { |
---|
| 423 | //this should not be called |
---|
| 424 | sLog.outError("Battleground remove event ABORTED!"); |
---|
| 425 | } |
---|
| 426 | |
---|
| 427 | /*********************************************************/ |
---|
| 428 | /*** BATTLEGROUND MANAGER ***/ |
---|
| 429 | /*********************************************************/ |
---|
| 430 | |
---|
| 431 | BattleGroundMgr::BattleGroundMgr() |
---|
| 432 | { |
---|
| 433 | m_BattleGrounds.clear(); |
---|
| 434 | } |
---|
| 435 | |
---|
| 436 | BattleGroundMgr::~BattleGroundMgr() |
---|
| 437 | { |
---|
| 438 | for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) |
---|
| 439 | delete itr->second; |
---|
| 440 | m_BattleGrounds.clear(); |
---|
| 441 | } |
---|
| 442 | |
---|
| 443 | void BattleGroundMgr::Update(time_t diff) |
---|
| 444 | { |
---|
| 445 | for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) |
---|
| 446 | itr->second->Update(diff); |
---|
| 447 | } |
---|
| 448 | |
---|
| 449 | void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2) |
---|
| 450 | { |
---|
| 451 | // we can be in 3 queues in same time... |
---|
| 452 | if(StatusID == 0) |
---|
| 453 | { |
---|
| 454 | data->Initialize(SMSG_BATTLEFIELD_STATUS, 4*3); |
---|
| 455 | *data << uint32(QueueSlot); // queue id (0...2) |
---|
| 456 | *data << uint64(0); |
---|
| 457 | return; |
---|
| 458 | } |
---|
| 459 | |
---|
| 460 | data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4)); |
---|
| 461 | *data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time |
---|
| 462 | // uint64 in client |
---|
| 463 | *data << uint64( uint64(bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); |
---|
| 464 | *data << uint32(0); // unknown |
---|
| 465 | // alliance/horde for BG and skirmish/rated for Arenas |
---|
| 466 | *data << uint8(bg->isArena() ? (bg->isRated() ? 1 : 0) : bg->GetTeamIndexByTeamId(team)); |
---|
| 467 | *data << uint32(StatusID); // status |
---|
| 468 | switch(StatusID) |
---|
| 469 | { |
---|
| 470 | case STATUS_WAIT_QUEUE: // status_in_queue |
---|
| 471 | *data << uint32(Time1); // average wait time, milliseconds |
---|
| 472 | *data << uint32(Time2); // time in queue, updated every minute? |
---|
| 473 | break; |
---|
| 474 | case STATUS_WAIT_JOIN: // status_invite |
---|
| 475 | *data << uint32(bg->GetMapId()); // map id |
---|
| 476 | *data << uint32(Time1); // time to remove from queue, milliseconds |
---|
| 477 | break; |
---|
| 478 | case STATUS_IN_PROGRESS: // status_in_progress |
---|
| 479 | *data << uint32(bg->GetMapId()); // map id |
---|
| 480 | *data << uint32(Time1); // 0 at bg start, 120000 after bg end, time to bg auto leave, milliseconds |
---|
| 481 | *data << uint32(Time2); // time from bg start, milliseconds |
---|
| 482 | *data << uint8(0x1); // unk sometimes 0x0! |
---|
| 483 | break; |
---|
| 484 | default: |
---|
| 485 | sLog.outError("Unknown BG status!"); |
---|
| 486 | break; |
---|
| 487 | } |
---|
| 488 | } |
---|
| 489 | |
---|
| 490 | void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) |
---|
| 491 | { |
---|
| 492 | uint8 type = (bg->isArena() ? 1 : 0); |
---|
| 493 | // last check on 2.4.1 |
---|
| 494 | data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize())); |
---|
| 495 | *data << uint8(type); // seems to be type (battleground=0/arena=1) |
---|
| 496 | if(type) // arena |
---|
| 497 | { |
---|
| 498 | for(uint8 i = 0; i < 2; i++) |
---|
| 499 | { |
---|
| 500 | *data << uint32(3000+1+i); // rating change: showed value - 3000 |
---|
| 501 | *data << uint32(0); // 2.4.0, has some to do with rating change... |
---|
| 502 | *data << uint8(0); // some unknown string |
---|
| 503 | } |
---|
| 504 | } |
---|
| 505 | |
---|
| 506 | if(bg->GetWinner() == 2) |
---|
| 507 | { |
---|
| 508 | *data << uint8(0); // bg in progress |
---|
| 509 | } |
---|
| 510 | else |
---|
| 511 | { |
---|
| 512 | *data << uint8(1); // bg ended |
---|
| 513 | *data << uint8(bg->GetWinner()); // who win |
---|
| 514 | } |
---|
| 515 | |
---|
| 516 | *data << (int32)(bg->GetPlayerScoresSize()); |
---|
| 517 | |
---|
| 518 | for(std::map<uint64, BattleGroundScore*>::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr) |
---|
| 519 | { |
---|
| 520 | *data << (uint64)itr->first; |
---|
| 521 | *data << (int32)itr->second->KillingBlows; |
---|
| 522 | if(type) |
---|
| 523 | { |
---|
| 524 | // this value is team (green/gold)? |
---|
| 525 | // that part probably wrong |
---|
| 526 | Player *plr = objmgr.GetPlayer(itr->first); |
---|
| 527 | if(plr) |
---|
| 528 | { |
---|
| 529 | if(plr->GetTeam() == HORDE) |
---|
| 530 | *data << uint8(0); |
---|
| 531 | else if(plr->GetTeam() == ALLIANCE) |
---|
| 532 | *data << uint8(1); |
---|
| 533 | else |
---|
| 534 | *data << uint8(0); |
---|
| 535 | } |
---|
| 536 | else |
---|
| 537 | *data << uint8(0); |
---|
| 538 | } |
---|
| 539 | else |
---|
| 540 | { |
---|
| 541 | *data << (int32)itr->second->HonorableKills; |
---|
| 542 | *data << (int32)itr->second->Deaths; |
---|
| 543 | *data << (int32)itr->second->BonusHonor; // bonus honor |
---|
| 544 | } |
---|
| 545 | *data << (int32)itr->second->DamageDone; // damage done |
---|
| 546 | *data << (int32)itr->second->HealingDone; // healing done |
---|
| 547 | switch(bg->GetTypeID()) // battleground specific things |
---|
| 548 | { |
---|
| 549 | case BATTLEGROUND_AV: |
---|
| 550 | *data << (uint32)0x00000005; // count of next fields |
---|
| 551 | *data << (uint32)((BattleGroundAVScore*)itr->second)->GraveyardsAssaulted; // GraveyardsAssaulted |
---|
| 552 | *data << (uint32)((BattleGroundAVScore*)itr->second)->GraveyardsDefended; // GraveyardsDefended |
---|
| 553 | *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersAssaulted; // TowersAssaulted |
---|
| 554 | *data << (uint32)((BattleGroundAVScore*)itr->second)->TowersDefended; // TowersDefended |
---|
| 555 | *data << (uint32)((BattleGroundAVScore*)itr->second)->MinesCaptured; // MinesCaptured |
---|
| 556 | break; |
---|
| 557 | case BATTLEGROUND_WS: |
---|
| 558 | *data << (uint32)0x00000002; // count of next fields |
---|
| 559 | *data << (uint32)((BattleGroundWGScore*)itr->second)->FlagCaptures; // flag captures |
---|
| 560 | *data << (uint32)((BattleGroundWGScore*)itr->second)->FlagReturns; // flag returns |
---|
| 561 | break; |
---|
| 562 | case BATTLEGROUND_AB: |
---|
| 563 | *data << (uint32)0x00000002; // count of next fields |
---|
| 564 | *data << (uint32)((BattleGroundABScore*)itr->second)->BasesAssaulted; // bases asssulted |
---|
| 565 | *data << (uint32)((BattleGroundABScore*)itr->second)->BasesDefended; // bases defended |
---|
| 566 | break; |
---|
| 567 | case BATTLEGROUND_EY: |
---|
| 568 | *data << (uint32)0x00000001; // count of next fields |
---|
| 569 | *data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures |
---|
| 570 | break; |
---|
| 571 | case BATTLEGROUND_NA: |
---|
| 572 | case BATTLEGROUND_BE: |
---|
| 573 | case BATTLEGROUND_AA: |
---|
| 574 | case BATTLEGROUND_RL: |
---|
| 575 | *data << (int32)0; // 0 |
---|
| 576 | break; |
---|
| 577 | default: |
---|
| 578 | sLog.outDebug("Unhandled MSG_PVP_LOG_DATA for BG id %u", bg->GetTypeID()); |
---|
| 579 | *data << (int32)0; |
---|
| 580 | break; |
---|
| 581 | } |
---|
| 582 | } |
---|
| 583 | } |
---|
| 584 | |
---|
| 585 | void BattleGroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId) |
---|
| 586 | { |
---|
| 587 | /*bgTypeId is: |
---|
| 588 | 0 - Your group has joined a battleground queue, but you are not eligible |
---|
| 589 | 1 - Your group has joined the queue for AV |
---|
| 590 | 2 - Your group has joined the queue for WS |
---|
| 591 | 3 - Your group has joined the queue for AB |
---|
| 592 | 4 - Your group has joined the queue for NA |
---|
| 593 | 5 - Your group has joined the queue for BE Arena |
---|
| 594 | 6 - Your group has joined the queue for All Arenas |
---|
| 595 | 7 - Your group has joined the queue for EotS*/ |
---|
| 596 | data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); |
---|
| 597 | *data << uint32(bgTypeId); |
---|
| 598 | } |
---|
| 599 | |
---|
| 600 | void BattleGroundMgr::BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value) |
---|
| 601 | { |
---|
| 602 | data->Initialize(SMSG_UPDATE_WORLD_STATE, 4+4); |
---|
| 603 | *data << uint32(field); |
---|
| 604 | *data << uint32(value); |
---|
| 605 | } |
---|
| 606 | |
---|
| 607 | void BattleGroundMgr::BuildPlaySoundPacket(WorldPacket *data, uint32 soundid) |
---|
| 608 | { |
---|
| 609 | data->Initialize(SMSG_PLAY_SOUND, 4); |
---|
| 610 | *data << uint32(soundid); |
---|
| 611 | } |
---|
| 612 | |
---|
| 613 | void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr) |
---|
| 614 | { |
---|
| 615 | data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8); |
---|
| 616 | *data << uint64(plr->GetGUID()); |
---|
| 617 | } |
---|
| 618 | |
---|
| 619 | void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr) |
---|
| 620 | { |
---|
| 621 | data->Initialize(SMSG_BATTLEGROUND_PLAYER_JOINED, 8); |
---|
| 622 | *data << uint64(plr->GetGUID()); |
---|
| 623 | } |
---|
| 624 | |
---|
| 625 | void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID) |
---|
| 626 | { |
---|
| 627 | // set invited player counters: |
---|
| 628 | BattleGround* bg = this->GetBattleGround(bgInstanceGUID); |
---|
| 629 | if(!bg) |
---|
| 630 | return; |
---|
| 631 | |
---|
| 632 | bg->IncreaseInvitedCount(plr->GetTeam()); |
---|
| 633 | plr->SetInviteForBattleGroundType(bg->GetTypeID()); |
---|
| 634 | // create invite events: |
---|
| 635 | //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events |
---|
| 636 | BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); |
---|
| 637 | plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2)); |
---|
| 638 | BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam()); |
---|
| 639 | plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); |
---|
| 640 | } |
---|
| 641 | |
---|
| 642 | uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, 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) |
---|
| 643 | { |
---|
| 644 | // Create the BG |
---|
| 645 | BattleGround *bg = NULL; |
---|
| 646 | |
---|
| 647 | switch(bgTypeId) |
---|
| 648 | { |
---|
| 649 | case BATTLEGROUND_AV: bg = new BattleGroundAV; break; |
---|
| 650 | case BATTLEGROUND_WS: bg = new BattleGroundWS; break; |
---|
| 651 | case BATTLEGROUND_AB: bg = new BattleGroundAB; break; |
---|
| 652 | case BATTLEGROUND_NA: bg = new BattleGroundNA; break; |
---|
| 653 | case BATTLEGROUND_BE: bg = new BattleGroundBE; break; |
---|
| 654 | case BATTLEGROUND_AA: bg = new BattleGroundAA; break; |
---|
| 655 | case BATTLEGROUND_EY: bg = new BattleGroundEY; break; |
---|
| 656 | case BATTLEGROUND_RL: bg = new BattleGroundRL; break; |
---|
| 657 | default:bg = new BattleGround; break; // placeholder for non implemented BG |
---|
| 658 | } |
---|
| 659 | |
---|
| 660 | bg->SetMapId(MapID); |
---|
| 661 | bg->Reset(); |
---|
| 662 | if(!bg->SetupBattleGround()) |
---|
| 663 | { |
---|
| 664 | delete bg; |
---|
| 665 | return 0; |
---|
| 666 | } |
---|
| 667 | |
---|
| 668 | BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId); |
---|
| 669 | //in previous method is checked if exists entry in sBattlemasterListStore, so no check needed |
---|
| 670 | if (bl) |
---|
| 671 | { |
---|
| 672 | bg->SetArenaorBGType(bl->type == TYPE_ARENA); |
---|
| 673 | } |
---|
| 674 | |
---|
| 675 | bg->SetTypeID(bgTypeId); |
---|
| 676 | bg->SetInstanceID(bgTypeId); // temporary |
---|
| 677 | bg->SetMinPlayersPerTeam(MinPlayersPerTeam); |
---|
| 678 | bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam); |
---|
| 679 | bg->SetMinPlayers(MinPlayersPerTeam*2); |
---|
| 680 | bg->SetMaxPlayers(MaxPlayersPerTeam*2); |
---|
| 681 | bg->SetName(BattleGroundName); |
---|
| 682 | bg->SetTeamStartLoc(ALLIANCE, Team1StartLocX, Team1StartLocY, Team1StartLocZ, Team1StartLocO); |
---|
| 683 | bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); |
---|
| 684 | bg->SetLevelRange(LevelMin, LevelMax); |
---|
| 685 | //add BaggleGround instance to FreeSlotQueue |
---|
| 686 | bg->AddToBGFreeSlotQueue(); |
---|
| 687 | |
---|
| 688 | AddBattleGround(bg->GetInstanceID(), bg); |
---|
| 689 | //sLog.outDetail("BattleGroundMgr: Created new battleground: %u %s (Map %u, %u players per team, Levels %u-%u)", bg_TypeID, bg->m_Name, bg->m_MapId, bg->m_MaxPlayersPerTeam, bg->m_LevelMin, bg->m_LevelMax); |
---|
| 690 | return bg->GetInstanceID(); |
---|
| 691 | } |
---|
| 692 | |
---|
| 693 | void BattleGroundMgr::CreateInitialBattleGrounds() |
---|
| 694 | { |
---|
| 695 | float AStartLoc[4]; |
---|
| 696 | float HStartLoc[4]; |
---|
| 697 | uint32 MaxPlayersPerTeam, MinPlayersPerTeam, MinLvl, MaxLvl, start1, start2; |
---|
| 698 | BattlemasterListEntry const *bl; |
---|
| 699 | WorldSafeLocsEntry const *start; |
---|
| 700 | |
---|
| 701 | uint32 count = 0; |
---|
| 702 | |
---|
| 703 | // 0 1 2 3 4 5 6 7 8 |
---|
| 704 | QueryResult *result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam,MaxPlayersPerTeam,MinLvl,MaxLvl,AllianceStartLoc,AllianceStartO,HordeStartLoc,HordeStartO FROM battleground_template"); |
---|
| 705 | |
---|
| 706 | if(!result) |
---|
| 707 | { |
---|
| 708 | barGoLink bar(1); |
---|
| 709 | |
---|
| 710 | bar.step(); |
---|
| 711 | |
---|
| 712 | sLog.outString(); |
---|
| 713 | sLog.outErrorDb(">> Loaded 0 battlegrounds. DB table `battleground_template` is empty."); |
---|
| 714 | return; |
---|
| 715 | } |
---|
| 716 | |
---|
| 717 | barGoLink bar(result->GetRowCount()); |
---|
| 718 | |
---|
| 719 | do |
---|
| 720 | { |
---|
| 721 | Field *fields = result->Fetch(); |
---|
| 722 | bar.step(); |
---|
| 723 | |
---|
| 724 | uint32 bgTypeID = fields[0].GetUInt32(); |
---|
| 725 | |
---|
| 726 | // can be overwrited by values from DB |
---|
| 727 | bl = sBattlemasterListStore.LookupEntry(bgTypeID); |
---|
| 728 | if(!bl) |
---|
| 729 | { |
---|
| 730 | sLog.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.",bgTypeID); |
---|
| 731 | continue; |
---|
| 732 | } |
---|
| 733 | |
---|
| 734 | MaxPlayersPerTeam = bl->maxplayersperteam; |
---|
| 735 | MinPlayersPerTeam = bl->maxplayersperteam/2; |
---|
| 736 | MinLvl = bl->minlvl; |
---|
| 737 | MaxLvl = bl->maxlvl; |
---|
| 738 | |
---|
| 739 | if(fields[1].GetUInt32()) |
---|
| 740 | MinPlayersPerTeam = fields[1].GetUInt32(); |
---|
| 741 | |
---|
| 742 | if(fields[2].GetUInt32()) |
---|
| 743 | MaxPlayersPerTeam = fields[2].GetUInt32(); |
---|
| 744 | |
---|
| 745 | if(fields[3].GetUInt32()) |
---|
| 746 | MinLvl = fields[3].GetUInt32(); |
---|
| 747 | |
---|
| 748 | if(fields[4].GetUInt32()) |
---|
| 749 | MaxLvl = fields[4].GetUInt32(); |
---|
| 750 | |
---|
| 751 | start1 = fields[5].GetUInt32(); |
---|
| 752 | |
---|
| 753 | start = sWorldSafeLocsStore.LookupEntry(start1); |
---|
| 754 | if(start) |
---|
| 755 | { |
---|
| 756 | AStartLoc[0] = start->x; |
---|
| 757 | AStartLoc[1] = start->y; |
---|
| 758 | AStartLoc[2] = start->z; |
---|
| 759 | AStartLoc[3] = fields[6].GetFloat(); |
---|
| 760 | } |
---|
| 761 | else if(bgTypeID == BATTLEGROUND_AA) |
---|
| 762 | { |
---|
| 763 | AStartLoc[0] = 0; |
---|
| 764 | AStartLoc[1] = 0; |
---|
| 765 | AStartLoc[2] = 0; |
---|
| 766 | AStartLoc[3] = fields[6].GetFloat(); |
---|
| 767 | } |
---|
| 768 | else |
---|
| 769 | { |
---|
| 770 | sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.",bgTypeID,start1); |
---|
| 771 | continue; |
---|
| 772 | } |
---|
| 773 | |
---|
| 774 | start2 = fields[7].GetUInt32(); |
---|
| 775 | |
---|
| 776 | start = sWorldSafeLocsStore.LookupEntry(start2); |
---|
| 777 | if(start) |
---|
| 778 | { |
---|
| 779 | HStartLoc[0] = start->x; |
---|
| 780 | HStartLoc[1] = start->y; |
---|
| 781 | HStartLoc[2] = start->z; |
---|
| 782 | HStartLoc[3] = fields[8].GetFloat(); |
---|
| 783 | } |
---|
| 784 | else if(bgTypeID == BATTLEGROUND_AA) |
---|
| 785 | { |
---|
| 786 | HStartLoc[0] = 0; |
---|
| 787 | HStartLoc[1] = 0; |
---|
| 788 | HStartLoc[2] = 0; |
---|
| 789 | HStartLoc[3] = fields[8].GetFloat(); |
---|
| 790 | } |
---|
| 791 | else |
---|
| 792 | { |
---|
| 793 | sLog.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.",bgTypeID,start2); |
---|
| 794 | continue; |
---|
| 795 | } |
---|
| 796 | |
---|
| 797 | //sLog.outDetail("Creating battleground %s, %u-%u", bl->name[sWorld.GetDBClang()], MinLvl, MaxLvl); |
---|
| 798 | if(!CreateBattleGround(bgTypeID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, bl->name[sWorld.GetDefaultDbcLocale()], bl->mapid[0], AStartLoc[0], AStartLoc[1], AStartLoc[2], AStartLoc[3], HStartLoc[0], HStartLoc[1], HStartLoc[2], HStartLoc[3])) |
---|
| 799 | continue; |
---|
| 800 | |
---|
| 801 | ++count; |
---|
| 802 | } while (result->NextRow()); |
---|
| 803 | |
---|
| 804 | delete result; |
---|
| 805 | |
---|
| 806 | sLog.outString(); |
---|
| 807 | sLog.outString( ">> Loaded %u battlegrounds", count ); |
---|
| 808 | } |
---|
| 809 | |
---|
| 810 | void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) |
---|
| 811 | { |
---|
| 812 | uint32 PlayerLevel = 10; |
---|
| 813 | |
---|
| 814 | if(plr) |
---|
| 815 | PlayerLevel = plr->getLevel(); |
---|
| 816 | |
---|
| 817 | data->Initialize(SMSG_BATTLEFIELD_LIST); |
---|
| 818 | *data << uint64(guid); // battlemaster guid |
---|
| 819 | *data << uint32(bgTypeId); // battleground id |
---|
| 820 | if(bgTypeId == BATTLEGROUND_AA) // arena |
---|
| 821 | { |
---|
| 822 | *data << uint8(5); // unk |
---|
| 823 | *data << uint32(0); // unk |
---|
| 824 | } |
---|
| 825 | else // battleground |
---|
| 826 | { |
---|
| 827 | *data << uint8(0x00); // unk |
---|
| 828 | |
---|
| 829 | size_t count_pos = data->wpos(); |
---|
| 830 | uint32 count = 0; |
---|
| 831 | *data << uint32(0x00); // number of bg instances |
---|
| 832 | |
---|
| 833 | for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) |
---|
| 834 | { |
---|
| 835 | if(itr->second->GetTypeID() == bgTypeId && (PlayerLevel >= itr->second->GetMinLevel()) && (PlayerLevel <= itr->second->GetMaxLevel())) |
---|
| 836 | { |
---|
| 837 | *data << uint32(itr->second->GetInstanceID()); |
---|
| 838 | ++count; |
---|
| 839 | } |
---|
| 840 | } |
---|
| 841 | data->put<uint32>( count_pos , count); |
---|
| 842 | } |
---|
| 843 | } |
---|
| 844 | |
---|
| 845 | void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId) |
---|
| 846 | { |
---|
| 847 | BattleGround *bg = GetBattleGround(bgTypeId); |
---|
| 848 | if(bg) |
---|
| 849 | { |
---|
| 850 | uint32 mapid = bg->GetMapId(); |
---|
| 851 | float x, y, z, O; |
---|
| 852 | bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O); |
---|
| 853 | |
---|
| 854 | sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O); |
---|
| 855 | pl->TeleportTo(mapid, x, y, z, O); |
---|
| 856 | } |
---|
| 857 | } |
---|
| 858 | |
---|
| 859 | void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid) |
---|
| 860 | { |
---|
| 861 | WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12); |
---|
| 862 | uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds |
---|
| 863 | if(time_ == uint32(-1)) |
---|
| 864 | time_ = 0; |
---|
| 865 | data << guid << time_; |
---|
| 866 | pl->GetSession()->SendPacket(&data); |
---|
| 867 | } |
---|