Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
BattlegroundMgr.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ArenaTeamMgr.h"
7#include "Common.h"
8#include "ObjectMgr.h"
9#include "World.h"
10#include "WorldPacket.h"
11
12#include "ArenaTeam.h"
13#include "BattlegroundAB.h"
14#include "BattlegroundAV.h"
15#include "BattlegroundBE.h"
16#include "BattlegroundBFG.h"
17#include "BattlegroundDS.h"
18#include "BattlegroundEY.h"
19#include "BattlegroundIC.h"
20#include "BattlegroundMgr.h"
21#include "BattlegroundNA.h"
22#include "BattlegroundRL.h"
23#include "BattlegroundRV.h"
24#include "BattlegroundSA.h"
25#include "BattlegroundTP.h"
26#include "BattlegroundTV.h"
27#include "BattlegroundVOP.h"
28#include "BattlegroundWS.h"
29#include "Chat.h"
30#include "DisableMgr.h"
31#include "Formulas.h"
32#include "GameEventMgr.h"
33#include "Map.h"
34#include "MapInstanced.h"
35#include "MapManager.h"
36#include "Opcodes.h"
37#include "Player.h"
38#include "SharedDefines.h"
39
40/*********************************************************/
41/*** BATTLEGROUND MANAGER ***/
42/*********************************************************/
43
48
53
55{
56 for (BattlegroundDataContainer::iterator itr1 = bgDataStore.begin(); itr1 != bgDataStore.end(); ++itr1)
57 {
58 BattlegroundData& data = itr1->second;
59
60 while (!data.m_Battlegrounds.empty())
61 delete data.m_Battlegrounds.begin()->second;
62 data.m_Battlegrounds.clear();
63
64 while (!data.BGFreeSlotQueue.empty())
65 delete data.BGFreeSlotQueue.front();
66 }
67
68 bgDataStore.clear();
69}
70
71// used to update running battlegrounds, and delete finished ones
73{
74 for (BattlegroundDataContainer::iterator itr1 = bgDataStore.begin(); itr1 != bgDataStore.end(); ++itr1)
75 {
76 BattlegroundContainer& bgs = itr1->second.m_Battlegrounds;
77 BattlegroundContainer::iterator itrDelete = bgs.begin();
78 // first one is template and should not be deleted
79 for (BattlegroundContainer::iterator itr = ++itrDelete; itr != bgs.end();)
80 {
81 itrDelete = itr++;
82 Battleground* bg = itrDelete->second;
83
84 bg->Update(diff);
85 if (bg->ToBeDeleted())
86 {
87 itrDelete->second = NULL;
88 bgs.erase(itrDelete);
89 uint8 BracketID = uint8(bg->GetBracketId());
90 BattlegroundClientIdsContainer& clients = itr1->second.m_ClientBattlegroundIds[BracketID];
91 if (!clients.empty())
92 clients.erase(bg->GetClientInstanceID());
93
94 delete bg;
95 }
96 }
97 }
98
99 // update events timer
100 for (int qtype = BATTLEGROUND_QUEUE_NONE; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype)
101 m_BattlegroundQueues[qtype].UpdateEvents(diff);
102
103 // update scheduled queues
104 if (!m_QueueUpdateScheduler.empty())
105 {
106 std::vector<ScheduledQueueUpdate> scheduled;
107 std::swap(scheduled, m_QueueUpdateScheduler);
108 for (uint8 i = 0; i < scheduled.size(); i++)
109 {
110 uint32 arenaMMRating = scheduled[i].ArenaMMRating;
111 uint8 arenaType = scheduled[i].ArenaType;
112 BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId(scheduled[i].QueueId);
113 BattlegroundTypeId bgTypeId = BattlegroundTypeId(scheduled[i].TypeId);
114 BattlegroundBracketId bracket_id = BattlegroundBracketId(scheduled[i].BracketId);
115 m_BattlegroundQueues[bgQueueTypeId].BattlegroundQueueUpdate(diff, bgTypeId, bracket_id, arenaType, arenaMMRating > 0, arenaMMRating);
116 }
117 }
118
119 // if rating difference counts, maybe force-update queues
121 {
122 // it's time to force update
123 if (m_NextRatedArenaUpdate < diff)
124 {
125 // forced update for rated arenas (scan all, but skipped non rated)
126 SF_LOG_TRACE("bg.arena", "BattlegroundMgr: UPDATING ARENA QUEUES");
127 for (int qtype = BATTLEGROUND_QUEUE_2v2; qtype <= BATTLEGROUND_QUEUE_5v5; ++qtype)
128 for (int bracket = 0; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket)
129 m_BattlegroundQueues[qtype].BattlegroundQueueUpdate(diff,
132
134 }
135 else
137 }
138}
139
140void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype)
141{
142 ObjectGuid playerGuid = player->GetGUID();
143 ObjectGuid bgGuid;
144
145 if (bg)
146 bgGuid = bg->GetGUID();
147 else
148 StatusID = STATUS_NONE;
149
150 switch (StatusID)
151 {
152 case STATUS_NONE:
153 {
155
156 *data << uint32(Time2); // Join Time
157 *data << uint32(0); // Id
158 *data << uint32(QueueSlot); // Queue slot
159
160 data->WriteBit(playerGuid[2]);
161 data->WriteBit(playerGuid[0]);
162 data->WriteBit(playerGuid[4]);
163 data->WriteBit(playerGuid[5]);
164 data->WriteBit(playerGuid[3]);
165 data->WriteBit(playerGuid[7]);
166 data->WriteBit(playerGuid[1]);
167 data->WriteBit(playerGuid[6]);
168
169 data->WriteByteSeq(playerGuid[3]);
170 data->WriteByteSeq(playerGuid[5]);
171 data->WriteByteSeq(playerGuid[6]);
172 data->WriteByteSeq(playerGuid[4]);
173 data->WriteByteSeq(playerGuid[2]);
174 data->WriteByteSeq(playerGuid[0]);
175 data->WriteByteSeq(playerGuid[1]);
176 data->WriteByteSeq(playerGuid[7]);
177 break;
178 }
180 {
182
183 data->WriteBit(bgGuid[1]);
184 data->WriteBit(bgGuid[5]);
185 data->WriteBit(playerGuid[0]);
186 data->WriteBit(bgGuid[7]);
187 data->WriteBit(bg->isRated()); // Is Rated
188 data->WriteBit(0); // AsGroup
189 data->WriteBit(1); // Eligible In Queue
190 data->WriteBit(playerGuid[6]);
191 data->WriteBit(playerGuid[4]);
192 data->WriteBit(playerGuid[1]);
193 data->WriteBit(playerGuid[3]);
194 data->WriteBit(playerGuid[7]);
195 data->WriteBit(playerGuid[5]);
196 data->WriteBit(0); // IsSuspended
197 data->WriteBit(bgGuid[3]);
198 data->WriteBit(bgGuid[0]);
199 data->WriteBit(bgGuid[2]);
200 data->WriteBit(playerGuid[2]);
201 data->WriteBit(bgGuid[6]);
202 data->WriteBit(bgGuid[4]);
203
204 data->FlushBits();
205
206 data->WriteByteSeq(bgGuid[4]);
207 data->WriteByteSeq(playerGuid[6]);
208 *data << uint32(0); // Id
209 data->WriteByteSeq(bgGuid[5]);
210 *data << uint32(Time2); // Estimated Wait Time
211 data->WriteByteSeq(bgGuid[3]);
212 data->WriteByteSeq(playerGuid[3]);
213 data->WriteByteSeq(playerGuid[4]);
214 data->WriteByteSeq(playerGuid[0]);
215 *data << uint8(bg->GetMinLevel()); // MinLevel
216 data->WriteByteSeq(bgGuid[0]);
217 *data << uint32(Time1); // Join Time
218 *data << uint8(bg->isArena() ? arenatype : 1); // PremadeSize
219 data->WriteByteSeq(bgGuid[1]);
220 *data << uint32(GetMSTimeDiffToNow(Time2)); // Time since joined
221 data->WriteByteSeq(bgGuid[7]);
222 *data << uint32(QueueSlot); // Queue slot
223 data->WriteByteSeq(playerGuid[2]);
224 data->WriteByteSeq(bgGuid[6]);
225 *data << uint8(bg->GetMaxLevel()); // MaxLevel
226 data->WriteByteSeq(bgGuid[2]);
227 data->WriteByteSeq(playerGuid[5]);
228 data->WriteByteSeq(playerGuid[1]);
229 *data << uint32(bg->GetClientInstanceID()); // Client Instance ID
230 data->WriteByteSeq(playerGuid[7]);
231 break;
232 }
233 case STATUS_WAIT_JOIN:
234 {
236
237 data->WriteBit(playerGuid[7]);
238 data->WriteBit(playerGuid[5]);
239 data->WriteBit(playerGuid[4]);
240 data->WriteBit(playerGuid[1]);
241 data->WriteBit(bgGuid[3]);
242 data->WriteBit(bgGuid[2]);
243 data->WriteBit(1); // Missing Role
244 data->WriteBit(bgGuid[0]);
245 data->WriteBit(playerGuid[0]);
246 data->WriteBit(playerGuid[6]);
247 data->WriteBit(bgGuid[7]);
248 data->WriteBit(bgGuid[4]);
249 data->WriteBit(bgGuid[1]);
250 data->WriteBit(bg->isRated()); // Is Rated
251 data->WriteBit(playerGuid[2]);
252 data->WriteBit(bgGuid[6]);
253 data->WriteBit(playerGuid[3]);
254 data->WriteBit(bgGuid[5]);
255
256 data->WriteByteSeq(playerGuid[1]);
257 data->WriteByteSeq(bgGuid[1]);
258 data->WriteByteSeq(playerGuid[2]);
259 *data << uint8(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
260 *data << uint32(QueueSlot); // Queue slot
261 // *data << uint32(role);
262 *data << uint32(bg->GetClientInstanceID()); // Client Instance ID
263 data->WriteByteSeq(bgGuid[6]);
264 data->WriteByteSeq(bgGuid[7]);
265 *data << uint32(Time2); // Join Time
266 data->WriteByteSeq(playerGuid[7]);
267 *data << uint8(bg->GetMaxLevel()); // MaxLevel
268 data->WriteByteSeq(playerGuid[4]);
269 data->WriteByteSeq(bgGuid[2]);
270 data->WriteByteSeq(bgGuid[4]);
271 *data << uint32(Time1); // Time until closed
272 *data << uint8(bg->GetMinLevel()); // Min Level
273 data->WriteByteSeq(playerGuid[3]);
274 data->WriteByteSeq(bgGuid[0]);
275 data->WriteByteSeq(playerGuid[5]);
276 data->WriteByteSeq(playerGuid[6]);
277 *data << uint32(0); // Id
278 data->WriteByteSeq(bgGuid[3]);
279 data->WriteByteSeq(playerGuid[0]);
280 data->WriteByteSeq(bgGuid[5]);
281 *data << uint32(bg->GetMapId()); // Map Id
282 break;
283 }
285 {
287
288 data->WriteBit(playerGuid[0]);
289 data->WriteBit(bgGuid[3]);
290 data->WriteBit(playerGuid[3]);
291 data->WriteBit(bgGuid[2]);
292 data->WriteBit(playerGuid[2]);
293 data->WriteBit(bgGuid[5]);
294 data->WriteBit(bgGuid[1]);
295 data->WriteBit(playerGuid[7]);
296 data->WriteBit(0); // Left Early
297 data->WriteBit(playerGuid[6]);
298 data->WriteBit(bgGuid[0]);
299 data->WriteBit(player->GetBGTeam() == HORDE ? 0 : 1);
300 data->WriteBit(bgGuid[6]);
301 data->WriteBit(bgGuid[7]);
302 data->WriteBit(bgGuid[4]);
303 data->WriteBit(playerGuid[1]);
304 data->WriteBit(playerGuid[4]);
305 data->WriteBit(playerGuid[5]);
306 data->WriteBit(bg->isRated()); // Is Rated
307
308 data->FlushBits();
309
310 data->WriteByteSeq(playerGuid[3]);
311 *data << uint32(Time1); // Join Time
312 *data << uint32(bg->GetRemainingTime()); // Remaining Time
313 data->WriteByteSeq(bgGuid[7]);
314 data->WriteByteSeq(bgGuid[5]);
315 data->WriteByteSeq(playerGuid[1]);
316 data->WriteByteSeq(bgGuid[6]);
317 *data << uint32(Time2); // Elapsed Time
318 *data << uint8(bg->GetMaxLevel()); // Max Level
319 data->WriteByteSeq(bgGuid[1]);
320 data->WriteByteSeq(bgGuid[2]);
321 *data << uint32(QueueSlot); // Queue slot
322 data->WriteByteSeq(playerGuid[4]);
323 *data << uint8(bg->GetMinLevel()); // Min Level
324 data->WriteByteSeq(playerGuid[6]);
325 *data << uint32(bg->GetMapId()); // Map Id
326 data->WriteByteSeq(playerGuid[0]);
327 data->WriteByteSeq(playerGuid[5]);
328 data->WriteByteSeq(playerGuid[7]);
329 data->WriteByteSeq(bgGuid[4]);
330 *data << uint32(bg->GetClientInstanceID()); // Client Instance ID or faction ?
331 data->WriteByteSeq(playerGuid[2]);
332 *data << uint8(bg->isArena() ? arenatype : 1); // Player count, 1 for bgs, 2-3-5 for arena (2v2, 3v3, 5v5)
333 *data << uint32(0); // Id
334 data->WriteByteSeq(bgGuid[3]);
335 data->WriteByteSeq(bgGuid[0]);
336 break;
337 }
339 break;
340 }
341}
342
344{
345 ByteBuffer buff;
346 uint8 isArena = bg->isArena();
347
348 data->Initialize(SMSG_PVP_LOG_DATA, (1 + 1 + 4 + 40 * bg->GetPlayerScoresSize()));
349
350 *data << uint8(bg->GetPlayersCountByTeam(ALLIANCE));
351 *data << uint8(bg->GetPlayersCountByTeam(HORDE));
352
353 data->WriteBit(bg->GetStatus() == STATUS_WAIT_LEAVE); // If Ended
354 data->WriteBit(0); // Unk Some player stuff
355 data->WriteBit(0); // isRated
356
357 data->WriteBits(bg->GetPlayerScoresSize(), 19);
358
359 for (Battleground::BattlegroundScoreMap::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr)
360 {
361 if (!bg->IsPlayerInBattleground(itr->first))
362 {
363 SF_LOG_ERROR("network", "Player " UI64FMTD " has scoreboard entry for battleground %u but is not in battleground!", itr->first, uint32(bg->GetTypeID(true)));
364 continue;
365 }
366
367 Player* player = ObjectAccessor::FindPlayer(itr->first);
368 if (!player)
369 continue;
370 ObjectGuid playerGUID = itr->first;
371 BattlegroundScore* score = itr->second;
372
373 data->WriteBit(playerGUID[6]);
374 data->WriteBit(player->GetBGTeam() == HORDE ? 0 : 1);
375 data->WriteBit(0); // Rating Change
376 data->WriteBit(playerGUID[0]);
377 data->WriteBit(0); // MMR Change
378 data->WriteBit(playerGUID[7]);
379 data->WriteBit(0); // PreMatch MMR
380 data->WriteBit(playerGUID[3]);
381 data->WriteBit(0); // Prematch Rating
382 data->WriteBit(playerGUID[4]);
383 data->WriteBit(playerGUID[1]);
384
385 buff << uint32(score->HealingDone); // healing done
386 buff.WriteByteSeq(playerGUID[4]);
387 buff.WriteByteSeq(playerGUID[5]);
388 buff.WriteByteSeq(playerGUID[2]);
389
390 if (!isArena)
391 {
392 buff << uint32(score->Deaths);
393 buff << uint32(score->HonorableKills);
394 buff << uint32(score->BonusHonor / 100);
395 }
396
397 buff.WriteByteSeq(playerGUID[3]);
398 buff << uint32(score->DamageDone); // damage done
399 buff << uint32(score->KillingBlows);
400 buff.WriteByteSeq(playerGUID[1]);
401 buff.WriteByteSeq(playerGUID[6]);
402 buff.WriteByteSeq(playerGUID[7]);
403 buff.WriteByteSeq(playerGUID[0]);
404 buff << int32(bg->GetPlayerActiveSpec(playerGUID));
405
406 switch (bg->GetTypeID(true)) // Custom values
407 {
409 switch (bg->GetMapId())
410 {
411 case 489:
412 data->WriteBits(2, 22);
413 buff << uint32(((BattlegroundWGScore*)score)->FlagCaptures); // flag captures
414 buff << uint32(((BattlegroundWGScore*)score)->FlagReturns); // flag returns
415 break;
416 case 566:
417 data->WriteBits(1, 22);
418 buff << uint32(((BattlegroundEYScore*)score)->FlagCaptures); // flag captures
419 break;
420 case 529:
421 data->WriteBits(2, 22);
422 buff << uint32(((BattlegroundABScore*)score)->BasesAssaulted); // bases assaulted
423 buff << uint32(((BattlegroundABScore*)score)->BasesDefended); // bases defended
424 break;
425 case 30:
426 data->WriteBits(5, 22);
427 buff << uint32(((BattlegroundAVScore*)score)->GraveyardsAssaulted); // GraveyardsAssaulted
428 buff << uint32(((BattlegroundAVScore*)score)->GraveyardsDefended); // GraveyardsDefended
429 buff << uint32(((BattlegroundAVScore*)score)->TowersAssaulted); // TowersAssaulted
430 buff << uint32(((BattlegroundAVScore*)score)->TowersDefended); // TowersDefended
431 buff << uint32(((BattlegroundAVScore*)score)->MinesCaptured); // MinesCaptured
432 break;
433 case 607:
434 data->WriteBits(2, 22);
435 buff << uint32(((BattlegroundSAScore*)score)->demolishers_destroyed);
436 buff << uint32(((BattlegroundSAScore*)score)->gates_destroyed);
437 break;
438 case 628: // IC
439 data->WriteBits(2, 22);
440 buff << uint32(((BattlegroundICScore*)score)->BasesAssaulted); // bases assaulted
441 buff << uint32(((BattlegroundICScore*)score)->BasesDefended); // bases defended
442 break;
443 case 726:
444 data->WriteBits(2, 22);
445 buff << uint32(((BattlegroundTPScore*)score)->FlagCaptures); // flag captures
446 buff << uint32(((BattlegroundTPScore*)score)->FlagReturns); // flag returns
447 break;
448 case 761:
449 data->WriteBits(2, 22);
450 buff << uint32(((BattlegroundBFGScore*)score)->BasesAssaulted); // bases assaulted
451 buff << uint32(((BattlegroundBFGScore*)score)->BasesDefended); // bases defended
452 break;
453 case 998:
454 data->WriteBits(2, 22);
455 buff << uint32(((BattlegroundVOPScore*)score)->OrbControl); // orb possession
456 buff << uint32(((BattlegroundVOPScore*)score)->OrbScore); // victory points
457 break;
458 default:
459 data->WriteBits(0, 22);
460 break;
461 }
462 break;
464 data->WriteBits(5, 22);
465 buff << uint32(((BattlegroundAVScore*)score)->GraveyardsAssaulted); // GraveyardsAssaulted
466 buff << uint32(((BattlegroundAVScore*)score)->GraveyardsDefended); // GraveyardsDefended
467 buff << uint32(((BattlegroundAVScore*)score)->TowersAssaulted); // TowersAssaulted
468 buff << uint32(((BattlegroundAVScore*)score)->TowersDefended); // TowersDefended
469 buff << uint32(((BattlegroundAVScore*)score)->MinesCaptured); // MinesCaptured
470 break;
472 data->WriteBits(2, 22);
473 buff << uint32(((BattlegroundWGScore*)score)->FlagCaptures); // flag captures
474 buff << uint32(((BattlegroundWGScore*)score)->FlagReturns); // flag returns
475 break;
477 data->WriteBits(2, 22);
478 buff << uint32(((BattlegroundABScore*)score)->BasesAssaulted); // bases assaulted
479 buff << uint32(((BattlegroundABScore*)score)->BasesDefended); // bases defended
480 break;
482 data->WriteBits(1, 22);
483 buff << uint32(((BattlegroundEYScore*)score)->FlagCaptures); // flag captures
484 break;
486 data->WriteBits(2, 22);
487 buff << uint32(((BattlegroundSAScore*)score)->demolishers_destroyed);
488 buff << uint32(((BattlegroundSAScore*)score)->gates_destroyed);
489 break;
491 data->WriteBits(2, 22);
492 buff << uint32(((BattlegroundICScore*)score)->BasesAssaulted); // bases assaulted
493 buff << uint32(((BattlegroundICScore*)score)->BasesDefended); // bases defended
494 break;
496 data->WriteBits(2, 22);
497 buff << uint32(((BattlegroundTPScore*)score)->FlagCaptures); // flag captures
498 buff << uint32(((BattlegroundTPScore*)score)->FlagReturns); // flag returns
499 break;
501 data->WriteBits(2, 22);
502 buff << uint32(((BattlegroundBFGScore*)score)->BasesAssaulted); // bases assaulted
503 buff << uint32(((BattlegroundBFGScore*)score)->BasesDefended); // bases defended
504 break;
506 data->WriteBits(2, 22);
507 buff << uint32(((BattlegroundVOPScore*)score)->OrbControl); // orb possession
508 buff << uint32(((BattlegroundVOPScore*)score)->OrbScore); // victory Points
509 break;
517 data->WriteBits(0, 22);
518 break;
519 default:
520 data->WriteBits(0, 22);
521 break;
522 }
523
524 data->WriteBit(player->IsInWorld());
525 data->WriteBit(!isArena);
526 data->WriteBit(playerGUID[5]);
527 data->WriteBit(playerGUID[2]);
528 }
529
530
531 /*if (isRated) // arena
532 {
533 // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H
534 for (int8 i = 0; i < BG_TEAMS_COUNT; ++i)
535 {
536 int32 rating_change = bg->GetArenaTeamRatingChangeByIndex(i);
537
538 uint32 pointsLost = rating_change < 0 ? -rating_change : 0;
539 uint32 pointsGained = rating_change > 0 ? rating_change : 0;
540 uint32 MatchmakerRating = bg->GetArenaMatchmakerRatingByIndex(i);
541
542 *data << uint32(MatchmakerRating); // Matchmaking Value
543 *data << uint32(pointsLost); // Rating Lost
544 *data << uint32(pointsGained); // Rating gained
545
546 SF_LOG_DEBUG("bg.battleground", "rating change: %d", rating_change);
547 }
548 }*/
549
550 data->FlushBits();
551 data->append(buff);
552
553 if (bg->GetStatus() == STATUS_WAIT_LEAVE)
554 *data << uint8(bg->GetWinner());
555}
556
558{
559 ObjectGuid playerGuid = player->GetGUID(); // player who caused the error
560 ObjectGuid battlegroundGuid = bg->GetGUID();
561 ObjectGuid unkGuid3 = 0;
562
564
565 *data << uint32(player->GetBattlegroundQueueJoinTime(bg->GetTypeID())); // Join Time
566 *data << uint32(0); // Id ???
567 *data << uint32(QueueSlot); // Queue slot
568 *data << uint32(result); // Result
569
570 data->WriteBit(unkGuid3[7]);
571 data->WriteBit(battlegroundGuid[2]);
572 data->WriteBit(battlegroundGuid[7]);
573 data->WriteBit(unkGuid3[5]);
574 data->WriteBit(playerGuid[2]);
575 data->WriteBit(battlegroundGuid[6]);
576 data->WriteBit(playerGuid[7]);
577 data->WriteBit(playerGuid[3]);
578 data->WriteBit(battlegroundGuid[0]);
579 data->WriteBit(battlegroundGuid[3]);
580 data->WriteBit(unkGuid3[4]);
581 data->WriteBit(playerGuid[1]);
582 data->WriteBit(unkGuid3[0]);
583 data->WriteBit(playerGuid[0]);
584 data->WriteBit(unkGuid3[2]);
585 data->WriteBit(battlegroundGuid[4]);
586 data->WriteBit(playerGuid[4]);
587 data->WriteByteSeq(battlegroundGuid[1]);
588 data->WriteBit(unkGuid3[3]);
589 data->WriteBit(battlegroundGuid[5]);
590 data->WriteBit(unkGuid3[1]);
591 data->WriteBit(playerGuid[6]);
592 data->WriteBit(playerGuid[5]);
593 data->WriteBit(unkGuid3[6]);
594
595 data->WriteByteSeq(unkGuid3[1]);
596 data->WriteByteSeq(unkGuid3[2]);
597 data->WriteByteSeq(unkGuid3[7]);
598 data->WriteByteSeq(battlegroundGuid[6]);
599 data->WriteByteSeq(battlegroundGuid[0]);
600 data->WriteByteSeq(playerGuid[5]);
601 data->WriteByteSeq(playerGuid[0]);
602 data->WriteByteSeq(battlegroundGuid[1]);
603 data->WriteByteSeq(battlegroundGuid[7]);
604 data->WriteByteSeq(playerGuid[6]);
605 data->WriteByteSeq(unkGuid3[0]);
606 data->WriteByteSeq(battlegroundGuid[5]);
607 data->WriteByteSeq(unkGuid3[6]);
608 data->WriteByteSeq(playerGuid[1]);
609 data->WriteByteSeq(battlegroundGuid[2]);
610 data->WriteByteSeq(playerGuid[7]);
611 data->WriteByteSeq(playerGuid[2]);
612 data->WriteByteSeq(playerGuid[3]);
613 data->WriteByteSeq(unkGuid3[5]);
614 data->WriteByteSeq(playerGuid[4]);
615 data->WriteByteSeq(unkGuid3[3]);
616 data->WriteByteSeq(battlegroundGuid[3]);
617 data->WriteByteSeq(unkGuid3[4]);
618 data->WriteByteSeq(battlegroundGuid[4]);
619}
620
622{
624 data->WriteBit(0);
625 *data << uint32(value);
626 *data << uint32(field);
627}
628
630{
631 data->Initialize(SMSG_PLAY_SOUND, 4 + 9);
632 data->WriteBits(0, 8);
633 *data << uint32(soundid);
634}
635
637{
638 ObjectGuid guidBytes = guid;
639
641 data->WriteBit(guidBytes[3]);
642 data->WriteBit(guidBytes[5]);
643 data->WriteBit(guidBytes[6]);
644 data->WriteBit(guidBytes[0]);
645 data->WriteBit(guidBytes[1]);
646 data->WriteBit(guidBytes[2]);
647 data->WriteBit(guidBytes[7]);
648 data->WriteBit(guidBytes[4]);
649
650 data->WriteByteSeq(guidBytes[0]);
651 data->WriteByteSeq(guidBytes[6]);
652 data->WriteByteSeq(guidBytes[5]);
653 data->WriteByteSeq(guidBytes[7]);
654 data->WriteByteSeq(guidBytes[2]);
655 data->WriteByteSeq(guidBytes[1]);
656 data->WriteByteSeq(guidBytes[3]);
657 data->WriteByteSeq(guidBytes[4]);
658}
659
661{
662 ObjectGuid guidBytes = guid;
663
665 data->WriteBit(guidBytes[7]);
666 data->WriteBit(guidBytes[1]);
667 data->WriteBit(guidBytes[0]);
668 data->WriteBit(guidBytes[4]);
669 data->WriteBit(guidBytes[2]);
670 data->WriteBit(guidBytes[5]);
671 data->WriteBit(guidBytes[6]);
672 data->WriteBit(guidBytes[3]);
673
674 data->WriteByteSeq(guidBytes[0]);
675 data->WriteByteSeq(guidBytes[3]);
676 data->WriteByteSeq(guidBytes[7]);
677 data->WriteByteSeq(guidBytes[5]);
678 data->WriteByteSeq(guidBytes[2]);
679 data->WriteByteSeq(guidBytes[6]);
680 data->WriteByteSeq(guidBytes[4]);
681 data->WriteByteSeq(guidBytes[1]);
682}
683
685{
686 //cause at HandleBattlegroundJoinOpcode the clients sends the instanceid he gets from
687 //SMSG_BATTLEFIELD_LIST we need to find the battleground with this clientinstance-id
689 if (!bg)
690 return NULL;
691
692 if (bg->isArena())
693 return GetBattleground(instanceId, bgTypeId);
694
695 BattlegroundDataContainer::const_iterator it = bgDataStore.find(bgTypeId);
696 if (it == bgDataStore.end())
697 return NULL;
698
699 for (BattlegroundContainer::const_iterator itr = it->second.m_Battlegrounds.begin(); itr != it->second.m_Battlegrounds.end(); ++itr)
700 {
701 if (itr->second->GetClientInstanceID() == instanceId)
702 return itr->second;
703 }
704
705 return NULL;
706}
707
709{
710 if (!instanceId)
711 return NULL;
712
713 BattlegroundDataContainer::const_iterator begin, end;
714
716 {
717 begin = bgDataStore.begin();
718 end = bgDataStore.end();
719 }
720 else
721 {
722 end = bgDataStore.find(bgTypeId);
723 if (end == bgDataStore.end())
724 return NULL;
725 begin = end++;
726 }
727
728 for (BattlegroundDataContainer::const_iterator it = begin; it != end; ++it)
729 {
730 BattlegroundContainer const& bgs = it->second.m_Battlegrounds;
731 BattlegroundContainer::const_iterator itr = bgs.find(instanceId);
732 if (itr != bgs.end())
733 return itr->second;
734 }
735
736 return NULL;
737}
738
740{
741 BattlegroundDataContainer::const_iterator itr = bgDataStore.find(bgTypeId);
742 if (itr == bgDataStore.end())
743 return NULL;
744
745 BattlegroundContainer const& bgs = itr->second.m_Battlegrounds;
746 // map is sorted and we can be sure that lowest instance id has only BG template
747 return bgs.empty() ? NULL : bgs.begin()->second;
748}
749
751{
752 if (IsArenaType(bgTypeId))
753 return 0; //arenas don't have client-instanceids
754
755 uint8 BracketID = uint8(bracket_id);
756 // we create here an instanceid, which is just for
757 // displaying this to the client and without any other use..
758 // the client-instanceIds are unique for each battleground-type
759 // the instance-id just needs to be as low as possible, beginning with 1
760 // the following works, because std::set is default ordered with "<"
761 // the optimalization would be to use as bitmask std::vector<uint32> - but that would only make code unreadable
762
763 BattlegroundClientIdsContainer& clientIds = bgDataStore[bgTypeId].m_ClientBattlegroundIds[BracketID];
764 uint32 lastId = 0;
765 for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end();)
766 {
767 if ((++lastId) != *itr) //if there is a gap between the ids, we will break..
768 break;
769 lastId = *itr;
770 }
771
772 clientIds.insert(++lastId);
773 return lastId;
774}
775
776// create a new battleground that will really be used to play
777Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId originalBgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated)
778{
779 BattlegroundTypeId bgTypeId = originalBgTypeId;
780 bool isRandom = false;
781
782 switch (originalBgTypeId)
783 {
785 isRandom = true;
788 bgTypeId = GetRandomBG(originalBgTypeId);
789 break;
790 default:
791 break;
792 }
793
794 // get the template BG
795 Battleground* bg_template = GetBattlegroundTemplate(bgTypeId);
796
797 if (!bg_template)
798 {
799 SF_LOG_ERROR("bg.battleground", "Battleground: CreateNewBattleground - bg template not found for %u", uint32(bgTypeId));
800 return NULL;
801 }
802
803 Battleground* bg = NULL;
804 // create a copy of the BG template
805 switch (bgTypeId)
806 {
808 bg = new BattlegroundAV(*(BattlegroundAV*)bg_template);
809 break;
811 bg = new BattlegroundWS(*(BattlegroundWS*)bg_template);
812 break;
814 bg = new BattlegroundAB(*(BattlegroundAB*)bg_template);
815 break;
817 bg = new BattlegroundNA(*(BattlegroundNA*)bg_template);
818 break;
820 bg = new BattlegroundBE(*(BattlegroundBE*)bg_template);
821 break;
823 bg = new BattlegroundEY(*(BattlegroundEY*)bg_template);
824 break;
826 bg = new BattlegroundRL(*(BattlegroundRL*)bg_template);
827 break;
829 bg = new BattlegroundSA(*(BattlegroundSA*)bg_template);
830 break;
832 bg = new BattlegroundDS(*(BattlegroundDS*)bg_template);
833 break;
835 bg = new BattlegroundRV(*(BattlegroundRV*)bg_template);
836 break;
838 bg = new BattlegroundIC(*(BattlegroundIC*)bg_template);
839 break;
841 bg = new BattlegroundTP(*(BattlegroundTP*)bg_template);
842 break;
844 bg = new BattlegroundBFG(*(BattlegroundBFG*)bg_template);
845 break;
847 bg = new BattlegroundVOP(*(BattlegroundVOP*)bg_template);
848 break;
850 bg = new BattlegroundTV(*(BattlegroundTV*)bg_template);
851 break;
854 bg = new Battleground(*bg_template);
855 break;
856 default:
857 return NULL;
858 }
859
860 bg->SetBracket(bracketEntry);
861 bg->SetInstanceID(sMapMgr->GenerateInstanceId());
863 bg->Reset(); // reset the new bg (set status to status_wait_queue from status_none)
864 bg->SetStatus(STATUS_WAIT_JOIN); // start the joining of the bg
865 bg->SetArenaType(arenaType);
866 bg->SetTypeID(originalBgTypeId);
867 bg->SetRandomTypeID(bgTypeId);
868 bg->SetRated(isRated);
869 bg->SetRandom(isRandom);
871
872 // Set up correct min/max player counts for scoreboards
873 if (bg->isArena())
874 {
875 uint32 maxPlayersPerTeam = 0;
876 switch (arenaType)
877 {
878 case ARENA_TYPE_2v2:
879 maxPlayersPerTeam = 2;
880 break;
881 case ARENA_TYPE_3v3:
882 maxPlayersPerTeam = 3;
883 break;
884 case ARENA_TYPE_5v5:
885 maxPlayersPerTeam = 5;
886 break;
887 }
888
889 bg->SetMaxPlayersPerTeam(maxPlayersPerTeam);
890 bg->SetMaxPlayers(maxPlayersPerTeam * 2);
891 }
892
893 return bg;
894}
895
896// used to create the BG templates
898{
899 // Create the BG
900 Battleground* bg = NULL;
901 switch (data.bgTypeId)
902 {
904 bg = new BattlegroundAV;
905 break;
907 bg = new BattlegroundWS;
908 break;
910 bg = new BattlegroundAB;
911 break;
913 bg = new BattlegroundNA;
914 break;
916 bg = new BattlegroundBE;
917 break;
919 bg = new BattlegroundEY;
920 break;
922 bg = new BattlegroundRL;
923 break;
925 bg = new BattlegroundSA;
926 break;
928 bg = new BattlegroundDS;
929 break;
931 bg = new BattlegroundRV;
932 break;
934 bg = new BattlegroundIC;
935 break;
937 bg = new Battleground;
938 break;
940 bg = new Battleground;
941 bg->SetRandom(true);
942 break;
944 bg = new BattlegroundTP;
945 break;
947 bg = new BattlegroundTV;
948 break;
950 bg = new BattlegroundBFG;
951 break;
953 bg = new BattlegroundVOP;
954 break;
955 default:
956 return false;
957 }
958
959 bg->SetMapId(data.MapID);
960 bg->SetTypeID(data.bgTypeId);
961 bg->SetInstanceID(0);
962 bg->SetArenaorBGType(data.IsArena);
965 bg->SetMinPlayers(data.MinPlayersPerTeam * 2);
966 bg->SetMaxPlayers(data.MaxPlayersPerTeam * 2);
967 bg->SetName(data.BattlegroundName);
971 bg->SetLevelRange(data.LevelMin, data.LevelMax);
972 bg->SetScriptId(data.scriptId);
974
975 AddBattleground(bg);
976
977 return true;
978}
979
981{
982 uint32 oldMSTime = getMSTime();
983 // 0 1 2 3 4 5 6 7 8 9 10 11
984 QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
985
986 if (!result)
987 {
988 SF_LOG_ERROR("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
989 return;
990 }
991
992 uint32 count = 0;
993
994 do
995 {
996 Field* fields = result->Fetch();
997
998 uint32 bgTypeId = fields[0].GetUInt32();
1000 continue;
1001
1002 // can be overwrite by values from DB
1003 BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
1004 if (!bl)
1005 {
1006 SF_LOG_ERROR("bg.battleground", "Battleground ID %u not found in BattleMasterList.dbc. Battleground not created.", bgTypeId);
1007 continue;
1008 }
1009
1011 data.bgTypeId = BattlegroundTypeId(bgTypeId);
1012 data.IsArena = (bl->type == TYPE_ARENA);
1013 data.MinPlayersPerTeam = fields[1].GetUInt16();
1014 data.MaxPlayersPerTeam = fields[2].GetUInt16();
1015 data.LevelMin = fields[3].GetUInt8();
1016 data.LevelMax = fields[4].GetUInt8();
1017 float dist = fields[9].GetFloat();
1018 data.StartMaxDist = dist * dist;
1019
1020 data.scriptId = sObjectMgr->GetScriptId(fields[11].GetCString());
1021 data.BattlegroundName = bl->name;
1022 data.MapID = bl->mapid[0];
1023
1024 if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
1025 {
1026 SF_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)",
1027 bgTypeId, data.MinPlayersPerTeam, data.MaxPlayersPerTeam);
1028 continue;
1029 }
1030
1031 if (data.LevelMin == 0 || data.LevelMax == 0 || data.LevelMin > data.LevelMax)
1032 {
1033 SF_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has bad values for LevelMin (%u) and LevelMax(%u)",
1034 bgTypeId, data.LevelMin, data.LevelMax);
1035 continue;
1036 }
1037
1039 {
1040 data.Team1StartLocX = 0;
1041 data.Team1StartLocY = 0;
1042 data.Team1StartLocZ = 0;
1043 data.Team1StartLocO = fields[6].GetFloat();
1044 data.Team2StartLocX = 0;
1045 data.Team2StartLocY = 0;
1046 data.Team2StartLocZ = 0;
1047 data.Team2StartLocO = fields[8].GetFloat();
1048 }
1049 else
1050 {
1051 uint32 startId = fields[5].GetUInt32();
1052 if (WorldSafeLocsEntry const* start = sWorldSafeLocsStore.LookupEntry(startId))
1053 {
1054 data.Team1StartLocX = start->x;
1055 data.Team1StartLocY = start->y;
1056 data.Team1StartLocZ = start->z;
1057 data.Team1StartLocO = fields[6].GetFloat();
1058 }
1059 else
1060 {
1061 SF_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.", bgTypeId, startId);
1062 continue;
1063 }
1064
1065 startId = fields[7].GetUInt32();
1066 if (WorldSafeLocsEntry const* start = sWorldSafeLocsStore.LookupEntry(startId))
1067 {
1068 data.Team2StartLocX = start->x;
1069 data.Team2StartLocY = start->y;
1070 data.Team2StartLocZ = start->z;
1071 data.Team2StartLocO = fields[8].GetFloat();
1072 }
1073 else
1074 {
1075 SF_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.", bgTypeId, startId);
1076 continue;
1077 }
1078 }
1079
1080 if (!CreateBattleground(data))
1081 continue;
1082
1083 if (data.IsArena)
1084 {
1086 m_ArenaSelectionWeights[data.bgTypeId] = fields[10].GetUInt8();
1087 }
1089 m_BGSelectionWeights[data.bgTypeId] = fields[10].GetUInt8();
1090
1091 ++count;
1092 } while (result->NextRow());
1093
1094 SF_LOG_INFO("server.loading", ">> Loaded %u battlegrounds in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
1095}
1096
1098{
1099 if (!player)
1100 return;
1101
1102 BattlegroundDataContainer::iterator it = bgDataStore.find(bgTypeId);
1103 if (it == bgDataStore.end())
1104 return;
1105
1106 PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(it->second.m_Battlegrounds.begin()->second->GetMapId(), player->getLevel());
1107 if (!bracketEntry)
1108 return;
1109
1113
1114 ObjectGuid guidBytes = guid;
1115
1117 *data << uint32(winnerConquest) // Winner Conquest Reward or Random Winner Conquest Reward
1118 << uint32(loserHonor) // Loser Honor Reward or Random Loser Honor Reward
1119 << uint8(bracketEntry->minLevel) // min level
1120 << uint32(winnerConquest) // Winner Conquest Reward or Random Winner Conquest Reward
1121 << uint32(winnerHonor) // Winner Honor Reward or Random Winner Honor Reward
1122 << uint32(bgTypeId) // battleground id
1123 << uint32(winnerHonor) // Winner Honor Reward or Random Winner Honor Reward
1124 << uint8(bracketEntry->maxLevel) // max level
1125 << uint32(loserHonor); // Loser Honor Reward or Random Loser Honor Reward
1126
1127 data->WriteBit(guidBytes[0]);
1128 data->WriteBit(0); // fake bit ?
1129 data->WriteBit(guidBytes[4]);
1130 data->WriteBit(0); // fake bit ?
1131 data->WriteBit(guidBytes[2]);
1132 data->WriteBit(0); // fake bit ?
1133 data->WriteBit(guidBytes[7]);
1134 data->WriteBit(guidBytes[6]);
1135 data->WriteBit(guidBytes[5]);
1136 data->WriteBit(guidBytes[1]);
1137 data->WriteBit(0); // fake bit ?
1138 data->WriteBit(guidBytes[3]);
1139
1140 size_t count_pos = data->bitwpos();
1141 data->WriteBits(0, 22); // placeholder
1142
1143 data->FlushBits();
1144
1145 data->WriteByteSeq(guidBytes[7]);
1146 data->WriteByteSeq(guidBytes[3]);
1147 data->WriteByteSeq(guidBytes[4]);
1148 data->WriteByteSeq(guidBytes[0]);
1149 data->WriteByteSeq(guidBytes[5]);
1150 data->WriteByteSeq(guidBytes[6]);
1151 data->WriteByteSeq(guidBytes[1]);
1152 data->WriteByteSeq(guidBytes[2]);
1153
1154 uint32 count = 0;
1155 uint8 bracketId = uint8(bracketEntry->GetBracketId());
1156 BattlegroundClientIdsContainer& clientIds = it->second.m_ClientBattlegroundIds[bracketId];
1157 for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end(); ++itr)
1158 {
1159 *data << uint32(*itr);
1160 ++count;
1161 }
1162 data->PutBits(count_pos, count, 22); // bg instance count
1163}
1164
1166{
1167 if (Battleground* bg = GetBattleground(instanceId, bgTypeId))
1168 {
1169 float x, y, z, O;
1170 uint32 mapid = bg->GetMapId();
1171 uint32 team = player->GetBGTeam();
1172
1173 bg->GetTeamStartLoc(team, x, y, z, O);
1174 SF_LOG_DEBUG("bg.battleground", "BattlegroundMgr::SendToBattleground: Sending %s to map %u, X %f, Y %f, Z %f, O %f (bgType %u)", player->GetName().c_str(), mapid, x, y, z, O, uint32(bgTypeId));
1175 player->TeleportTo(mapid, x, y, z, O);
1176 }
1177 else
1178 SF_LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Instance %u (bgType %u) not found while trying to teleport player %s", instanceId, uint32(bgTypeId), player->GetName().c_str());
1179}
1180
1182{
1183 ObjectGuid Guid = guid;
1184 uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds
1185 if (time_ == uint32(-1))
1186 time_ = 0;
1187
1189 data.WriteGuidMask(Guid, 5, 2, 7, 6, 1, 0, 3, 4);
1190
1191 data.WriteGuidBytes(Guid, 2, 3, 5, 4, 6);
1192 data << time_;
1193 data.WriteGuidBytes(Guid, 7, 0, 1);
1194
1195 player->GetSession()->SendPacket(&data);
1196}
1197
1208
1210{
1211 switch (bgTypeId)
1212 {
1214 return BATTLEGROUND_QUEUE_AB;
1216 return BATTLEGROUND_QUEUE_AV;
1218 return BATTLEGROUND_QUEUE_EY;
1220 return BATTLEGROUND_QUEUE_IC;
1222 return BATTLEGROUND_QUEUE_TP;
1226 return BATTLEGROUND_QUEUE_RB;
1228 return BATTLEGROUND_QUEUE_SA;
1230 return BATTLEGROUND_QUEUE_WS;
1240 switch (arenaType)
1241 {
1242 case ARENA_TYPE_2v2:
1244 case ARENA_TYPE_3v3:
1246 case ARENA_TYPE_5v5:
1248 default:
1250 }
1251 default:
1253 }
1254}
1255
1288
1290{
1291 switch (bgQueueTypeId)
1292 {
1294 return ARENA_TYPE_2v2;
1296 return ARENA_TYPE_3v3;
1298 return ARENA_TYPE_5v5;
1299 default:
1300 return 0;
1301 }
1302}
1303
1309
1315
1317{
1318 for (uint32 bgtype = 1; bgtype < MAX_BATTLEGROUND_TYPE_ID; ++bgtype)
1319 {
1321 {
1322 bg->SetHoliday(mask & (1 << bgtype));
1323 }
1324 }
1325}
1326
1327void BattlegroundMgr::ScheduleQueueUpdate(uint32 arenaMatchmakerRating, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
1328{
1329 //This method must be atomic, @todo add mutex
1330 //we will use only 1 number created of bgTypeId and bracket_id
1331 ScheduledQueueUpdate scheduleId = { arenaMatchmakerRating, arenaType, bgQueueTypeId, bgTypeId, bracket_id };
1332 if (std::find(m_QueueUpdateScheduler.begin(), m_QueueUpdateScheduler.end(), scheduleId) == m_QueueUpdateScheduler.end())
1333 m_QueueUpdateScheduler.push_back(scheduleId);
1334}
1335
1337{
1338 // this is for stupid people who can't use brain and set max rating difference to 0
1340 if (diff == 0)
1341 diff = 5000;
1342 return diff;
1343}
1344
1349
1354
1356{
1357 uint32 oldMSTime = getMSTime();
1358
1359 mBattleMastersMap.clear(); // need for reload case
1360
1361 QueryResult result = WorldDatabase.Query("SELECT entry, bg_template FROM battlemaster_entry");
1362
1363 if (!result)
1364 {
1365 SF_LOG_INFO("server.loading", ">> Loaded 0 battlemaster entries. DB table `battlemaster_entry` is empty!");
1366 return;
1367 }
1368
1369 uint32 count = 0;
1370
1371 do
1372 {
1373 ++count;
1374
1375 Field* fields = result->Fetch();
1376
1377 uint32 entry = fields[0].GetUInt32();
1378 uint32 bgTypeId = fields[1].GetUInt32();
1379 if (!sBattlemasterListStore.LookupEntry(bgTypeId))
1380 {
1381 SF_LOG_ERROR("sql.sql", "Table `battlemaster_entry` contain entry %u for not existed battleground type %u, ignored.", entry, bgTypeId);
1382 continue;
1383 }
1384
1385 mBattleMastersMap[entry] = BattlegroundTypeId(bgTypeId);
1386 } while (result->NextRow());
1387
1388 SF_LOG_INFO("server.loading", ">> Loaded %u battlemaster entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
1389}
1390
1409
1428
1433
1435{
1436 uint32 weight = 0;
1438 BattlegroundSelectionWeightMap selectionWeights;
1439
1441 {
1442 for (BattlegroundSelectionWeightMap::const_iterator it = m_ArenaSelectionWeights.begin(); it != m_ArenaSelectionWeights.end(); ++it)
1443 {
1444 if (it->second)
1445 {
1446 weight += it->second;
1447 selectionWeights[it->first] = it->second;
1448 }
1449 }
1450 }
1451 else if (bgTypeId == BattlegroundTypeId::BATTLEGROUND_RB)
1452 {
1453 for (BattlegroundSelectionWeightMap::const_iterator it = m_BGSelectionWeights.begin(); it != m_BGSelectionWeights.end(); ++it)
1454 {
1455 if (it->second)
1456 {
1457 weight += it->second;
1458 selectionWeights[it->first] = it->second;
1459 }
1460 }
1461 }
1462
1463 if (weight)
1464 {
1465 // Select a random value
1466 uint32 selectedWeight = std::rand() % (weight - 1);
1467 // Select the correct bg (if we have in DB A(10), B(20), C(10), D(15) --> [0---A---9|10---B---29|30---C---39|40---D---54])
1468 weight = 0;
1469 for (BattlegroundSelectionWeightMap::const_iterator it = selectionWeights.begin(); it != selectionWeights.end(); ++it)
1470 {
1471 weight += it->second;
1472 if (selectedWeight < weight)
1473 {
1474 returnBgTypeId = it->first;
1475 break;
1476 }
1477 }
1478 }
1479
1480 return returnBgTypeId;
1481}
1482
1484{
1485 return bgDataStore[bgTypeId].BGFreeSlotQueue;
1486}
1487
1489{
1490 bgDataStore[bgTypeId].BGFreeSlotQueue.push_front(bg);
1491}
1492
1494{
1495 BGFreeSlotQueueContainer& queues = bgDataStore[bgTypeId].BGFreeSlotQueue;
1496 for (BGFreeSlotQueueContainer::iterator itr = queues.begin(); itr != queues.end(); ++itr)
1497 if ((*itr)->GetInstanceID() == instanceId)
1498 {
1499 queues.erase(itr);
1500 return;
1501 }
1502}
1503
1505{
1506 if (bg)
1507 bgDataStore[bg->GetTypeID()].m_Battlegrounds[bg->GetInstanceID()] = bg;
1508}
1509
1511{
1512 bgDataStore[bgTypeId].m_Battlegrounds.erase(instanceId);
1513}
@ ARENA_TYPE_5v5
@ ARENA_TYPE_3v3
@ ARENA_TYPE_2v2
@ TYPE_ARENA
@ STATUS_WAIT_QUEUE
@ STATUS_NONE
@ STATUS_WAIT_LEAVE
@ STATUS_WAIT_JOIN
@ STATUS_IN_PROGRESS
std::map< uint32, Battleground * > BattlegroundContainer
std::set< uint32 > BattlegroundClientIdsContainer
std::list< Battleground * > BGFreeSlotQueueContainer
#define MAX_BATTLEGROUND_BRACKETS
Definition DBCEnums.h:34
BattlegroundBracketId
Definition DBCEnums.h:28
DBCStorage< WorldSafeLocsEntry > sWorldSafeLocsStore(WorldSafeLocsEntryfmt)
DBCStorage< BattlemasterListEntry > sBattlemasterListStore(BattlemasterListEntryfmt)
PvPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
std::int32_t int32
Definition Define.h:73
#define UI64FMTD
Definition Define.h:64
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
@ DISABLE_TYPE_BATTLEGROUND
Definition DisableMgr.h:18
bool IsHolidayActive(HolidayIds id)
@ LANG_DEBUG_BG_OFF
Definition Language.h:722
@ LANG_DEBUG_ARENA_OFF
Definition Language.h:720
@ LANG_DEBUG_BG_ON
Definition Language.h:721
@ LANG_DEBUG_ARENA_ON
Definition Language.h:719
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_TRACE(filterType__,...)
Definition Log.h:131
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
#define sMapMgr
Definition MapManager.h:145
@ HIGHGUID_BATTLEGROUND
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
#define sObjectMgr
Definition ObjectMgr.h:1617
Skyfire::AutoPtr< ResultSet, Skyfire::Mutex > QueryResult
Definition QueryResult.h:48
GroupJoinBattlegroundResult
#define CURRENCY_PRECISION
BattlegroundQueueTypeId
@ BATTLEGROUND_QUEUE_2v2
@ BATTLEGROUND_QUEUE_RB
@ BATTLEGROUND_QUEUE_SA
@ BATTLEGROUND_QUEUE_AB
@ BATTLEGROUND_QUEUE_5v5
@ BATTLEGROUND_QUEUE_WS
@ BATTLEGROUND_QUEUE_BFG
@ BATTLEGROUND_QUEUE_AV
@ MAX_BATTLEGROUND_QUEUE_TYPES
@ BATTLEGROUND_QUEUE_EY
@ BATTLEGROUND_QUEUE_TP
@ BATTLEGROUND_QUEUE_3v3
@ BATTLEGROUND_QUEUE_NONE
@ BATTLEGROUND_QUEUE_VOP
@ BATTLEGROUND_QUEUE_IC
@ ALLIANCE
@ HORDE
BattlegroundTypeId
HolidayIds
#define MAX_BATTLEGROUND_TYPE_ID
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:22
uint32 getMSTime()
Definition Timer.h:12
void SetMapId(uint32 MapID)
void SetInstanceID(uint32 InstanceID)
uint32 GetMapId() const
BattlegroundTypeId GetTypeID(bool GetRandom=false) const
bool ToBeDeleted() const
uint32 GetMinLevel() const
void SetRandom(bool isRandom)
void SetMaxPlayers(uint32 MaxPlayers)
virtual void Reset()
uint32 GetPlayerScoresSize() const
uint32 GetPlayerActiveSpec(uint64 guid) const
void SetScriptId(uint32 scriptId)
bool isRated() const
void SetName(char const *Name)
void SetBracket(PvPDifficultyEntry const *bracketEntry)
void SetMinPlayersPerTeam(uint32 MinPlayers)
void SetRated(bool state)
void SetStartMaxDist(float startMaxDist)
uint32 GetRemainingTime() const
uint64 GetGUID() const
void Update(uint32 diff)
uint32 GetInstanceID() const
BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const
void SetLevelRange(uint32 min, uint32 max)
uint32 GetClientInstanceID() const
void SetGuid(uint64 newGuid)
void SetClientInstanceID(uint32 InstanceID)
void SetStatus(BattlegroundStatus Status)
bool isArena() const
void SetArenaType(uint8 type)
void SetRandomTypeID(BattlegroundTypeId TypeID)
void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
BattlegroundStatus GetStatus() const
void SetArenaorBGType(bool _isArena)
uint8 GetWinner() const
uint32 GetPlayersCountByTeam(uint32 Team) const
uint32 GetLastResurrectTime() const
BattlegroundBracketId GetBracketId() const
bool IsPlayerInBattleground(uint64 guid) const
uint32 GetMaxLevel() const
BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const
void SetMinPlayers(uint32 MinPlayers)
void SetMaxPlayersPerTeam(uint32 MaxPlayers)
void SetTypeID(BattlegroundTypeId TypeID)
Battleground * GetBattlegroundThroughClientInstance(uint32 instanceId, BattlegroundTypeId bgTypeId)
void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value)
void BuildPlayerJoinedBattlegroundPacket(WorldPacket *data, uint64 guid)
bool CreateBattleground(CreateBattlegroundData &data)
void AddToBGFreeSlotQueue(BattlegroundTypeId bgTypeId, Battleground *bg)
BattlegroundSelectionWeightMap m_BGSelectionWeights
std::vector< ScheduledQueueUpdate > m_QueueUpdateScheduler
std::map< BattlegroundTypeId, uint8 > BattlegroundSelectionWeightMap
Battleground * GetBattleground(uint32 InstanceID, BattlegroundTypeId bgTypeId)
void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId)
uint32 GetMaxRatingDifference() const
BattlegroundTypeId GetRandomBG(BattlegroundTypeId id)
void CreateInitialBattlegrounds()
BattlegroundQueue m_BattlegroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]
static bool IsArenaType(BattlegroundTypeId bgTypeId)
BGFreeSlotQueueContainer & GetBGFreeSlotQueueStore(BattlegroundTypeId bgTypeId)
static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType)
void AddBattleground(Battleground *bg)
void BuildBattlegroundStatusPacket(WorldPacket *data, Battleground *bg, Player *player, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType)
static BattlegroundTypeId BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId)
void RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uint32 instanceId)
BattleMastersMap mBattleMastersMap
void ScheduleQueueUpdate(uint32 arenaMatchmakerRating, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
Battleground * CreateNewBattleground(BattlegroundTypeId bgTypeId, PvPDifficultyEntry const *bracketEntry, uint8 arenaType, bool isRated)
BattlegroundSelectionWeightMap m_ArenaSelectionWeights
void SendToBattleground(Player *player, uint32 InstanceID, BattlegroundTypeId bgTypeId)
void SetHolidayWeekends(uint32 mask)
void BuildPvpLogDataPacket(WorldPacket *data, Battleground *bg)
uint32 GetRatingDiscardTimer() const
static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday)
void BuildStatusFailedPacket(WorldPacket *data, Battleground *bg, Player *pPlayer, uint8 QueueSlot, GroupJoinBattlegroundResult result)
static HolidayIds BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId)
void BuildBattlegroundListPacket(WorldPacket *data, uint64 guid, Player *player, BattlegroundTypeId bgTypeId)
Battleground * GetBattlegroundTemplate(BattlegroundTypeId bgTypeId)
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundId)
void BuildPlayerLeftBattlegroundPacket(WorldPacket *data, uint64 guid)
uint32 GetPrematureFinishTime() const
uint32 CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
void Update(uint32 diff)
uint32 m_NextRatedArenaUpdate
void SendAreaSpiritHealerQueryOpcode(Player *player, Battleground *bg, uint64 guid)
static bool IsBGWeekend(BattlegroundTypeId bgTypeId)
static uint8 BGArenaType(BattlegroundQueueTypeId bgQueueTypeId)
BattlegroundDataContainer bgDataStore
Class for manage Strand of Ancient battleground.
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
size_t bitwpos() const
Returns position of last written bit.
Definition ByteBuffer.h:492
void append(T value)
Definition ByteBuffer.h:147
void PutBits(size_t pos, T value, uint32 bitCount)
Definition ByteBuffer.h:283
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void WriteByteSeq(uint8 b)
Definition ByteBuffer.h:227
void FlushBits()
Definition ByteBuffer.h:154
Definition Field.h:16
uint8 GetUInt8() const
Definition Field.h:26
uint16 GetUInt16() const
Definition Field.h:69
float GetFloat() const
Definition Field.h:177
uint32 GetUInt32() const
Definition Field.h:105
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
bool IsInWorld() const
Definition Object.h:114
uint32 GetBGTeam() const
Definition Player.cpp:17979
uint32 GetBattlegroundQueueJoinTime(BattlegroundTypeId bgTypeId) const
Definition Player.h:2707
WorldSession * GetSession() const
Definition Player.h:2417
bool GetRandomWinner() const
Definition Player.h:2757
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:2090
uint8 getLevel() const
Definition Unit.h:1528
std::string const & GetName() const
Definition Object.h:664
void Initialize(Opcodes opcode, size_t newres=200)
Definition WorldPacket.h:31
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
WorldDatabaseWorkerPool WorldDatabase
Accessor to the world database.
Definition Main.cpp:40
@ SMSG_BATTLEFIELD_LIST
Definition Opcodes.h:536
@ SMSG_BATTLEFIELD_STATUS_ACTIVE
Definition Opcodes.h:545
@ SMSG_AREA_SPIRIT_HEALER_TIME
Definition Opcodes.h:515
@ SMSG_BATTLEFIELD_STATUS
Definition Opcodes.h:544
@ SMSG_BATTLEFIELD_STATUS_NEEDCONFIRMATION
Definition Opcodes.h:547
@ SMSG_UPDATE_WORLD_STATE
Definition Opcodes.h:1055
@ SMSG_PLAY_SOUND
Definition Opcodes.h:883
@ SMSG_BATTLEFIELD_STATUS_QUEUED
Definition Opcodes.h:548
@ SMSG_PVP_LOG_DATA
Definition Opcodes.h:892
@ SMSG_BATTLEGROUND_PLAYER_LEFT
Definition Opcodes.h:550
@ SMSG_BATTLEFIELD_STATUS_FAILED
Definition Opcodes.h:546
@ SMSG_BATTLEGROUND_PLAYER_JOINED
Definition Opcodes.h:549
#define sWorld
Definition World.h:910
WorldIntConfigs
Definition World.h:198
@ CONFIG_BG_REWARD_WINNER_HONOR_FIRST
Definition World.h:355
@ CONFIG_ARENA_RATED_UPDATE_TIMER
Definition World.h:297
@ CONFIG_BG_REWARD_WINNER_HONOR_LAST
Definition World.h:356
@ CONFIG_BG_REWARD_WINNER_CONQUEST_LAST
Definition World.h:360
@ CONFIG_ARENA_RATING_DISCARD_TIMER
Definition World.h:296
@ CONFIG_BG_REWARD_LOSER_HONOR_FIRST
Definition World.h:357
@ CONFIG_BG_REWARD_LOSER_HONOR_LAST
Definition World.h:358
@ CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST
Definition World.h:359
@ CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER
Definition World.h:293
@ CONFIG_ARENA_MAX_RATING_DIFFERENCE
Definition World.h:295
bool IsDisabledFor(DisableType type, uint32 entry, Unit const *unit, uint8 flags)
BattlegroundContainer m_Battlegrounds
BGFreeSlotQueueContainer BGFreeSlotQueue
int32 mapid[16]
uint32 type
char * name
BattlegroundTypeId bgTypeId
uint32 maxLevel
BattlegroundBracketId GetBracketId() const
uint32 minLevel