Changeset 9
- Timestamp:
- 11/19/08 13:22:41 (17 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 39 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/sql/mangos.sql
r6 r9 199 199 ('debug standstate',2,'Syntax: .debug standstate #emoteid\r\n\r\nChange the emote of your character while standing to #emoteid.'), 200 200 ('debug update',3,'Syntax: .debug update #field #value\r\n\r\nUpdate the field #field of the selected character or creature with value #value.\r\n\r\nIf no #value is provided, display the content of field #field.'), 201 ('debug arena',3,'Syntax: .debug arena\r\n\r\n Toggles arena 1v1 or normal mode.'), 201 202 ('delticket',2,'Syntax: .delticket all\r\n .delticket #num\r\n .delticket $character_name\r\n\rall to dalete all tickets at server, $character_name to delete ticket of this character, #num to delete ticket #num.'), 202 203 ('demorph',2,'Syntax: .demorph\r\n\r\nDemorph the selected player.'), … … 209 210 ('event stop',2,'Syntax: .event stop #event_id\r\nStop event #event_id. Set start time for event to time in past that make current moment is event stop time (change not saved in DB).'), 210 211 ('explorecheat',3,'Syntax: .explorecheat #flag\r\n\r\nReveal or hide all maps for the selected player. If no player is selected, hide or reveal maps to you.\r\n\r\nUse a #flag of value 1 to reveal, use a #flag value of 0 to hide all maps.'), 212 ('flusharenapoints',3,'Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'), 211 213 ('gm',1,'Syntax: .gm on/off\r\n\r\nEnable or Disable GM MODE'), 212 214 ('gm fly',3,'Syntax: .gm fly on/off\r\nEnable/disable gm fly mode.'), … … 1364 1366 /*!40000 ALTER TABLE `instance_template` DISABLE KEYS */; 1365 1367 INSERT INTO `instance_template` VALUES 1368 (30,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 1366 1369 (33,0,22,30,10,7200,NULL,NULL,NULL,NULL,''), 1367 1370 (34,0,24,32,10,7200,NULL,NULL,NULL,NULL,''), … … 1387 1390 (429,0,55,60,5,7200,NULL,NULL,NULL,NULL,''), 1388 1391 (469,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), 1392 (489,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 1389 1393 (509,0,60,0,20,259200,NULL,NULL,NULL,NULL,''), 1394 (529,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 1390 1395 (531,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), 1391 (533,0,60,0,40,604800,NULL,NULL,NULL,NULL,''); 1396 (533,0,60,0,40,604800,NULL,NULL,NULL,NULL,''), 1397 (559,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 1398 (562,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 1399 (566,0,10,0,50,0,NULL,NULL,NULL,NULL,''), 1400 (572,0,10,0,50,0,NULL,NULL,NULL,NULL,''); 1392 1401 /*!40000 ALTER TABLE `instance_template` ENABLE KEYS */; 1393 1402 UNLOCK TABLES; … … 2567 2576 (709,'Do not Disturb',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2568 2577 (710,'Away from Keyboard',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2569 (711,'Queue status for %s (Lvl: %u to %u)\nQueued alliances: %u (Need at least %u more)\nQueued hordes: %u (Need at least %u more)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2570 (712,'|cffff0000[BG Queue Announcer]:|r %s -- [%u-%u] A: %u (Need: %u), H: %u (Needs %u)|r',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); 2578 (711,'Your group is too large for this battleground. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2579 (712,'Your group is too large for this arena. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2580 (713,'Your group has members not in your arena team. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2581 (714,'Your group does not have enough players to join this match.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2582 (715,'The Gold Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2583 (716,'The Green Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2584 (717, 'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2585 (718, 'Your group has an offline member. Please remove him before joining.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2586 (719, 'Your group has players from the opposing faction. You can\'t join the battleground as a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2587 (720, 'Your group has players from different battleground brakets. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2588 (721, 'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2589 (722, 'Someone in your party is Deserter. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2590 (723, 'Someone in your party is already in three battleground queues. You cannot join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2591 (724, 'You cannot teleport to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2592 (725, 'You cannot summon players to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2593 (726, 'You must be in GM mode to teleport to a player in a battleground.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2594 (727, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), 2595 (728, 'Arena testing turned %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); 2571 2596 /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; 2572 2597 UNLOCK TABLES; -
trunk/src/game/ArenaTeam.cpp
r2 r9 52 52 return false; 53 53 54 sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART( CaptainGuid));54 sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid)); 55 55 56 56 CaptainGuid = captainGuid; … … 139 139 pl->SetInArenaTeam(Id, GetSlot()); 140 140 pl->SetArenaTeamIdInvited(0); 141 } 142 else 143 { 144 Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id, PlayerGuid); 141 // personal rating 142 pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 5, 1500); 145 143 } 146 144 … … 150 148 if(pl) 151 149 pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); 152 else 153 Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, PlayerGuid); 154 } 150 } 151 152 // setuint32valueindb is asynch, can't be used here 153 Tokens tokens; 154 if(!Player::LoadValuesArrayFromDB(tokens,PlayerGuid)) 155 return false; 156 157 // arena team id 158 uint16 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6); 159 char buf[11]; 160 snprintf(buf,11,"%u",Id); 161 tokens[index] = buf; 162 // pers rating 163 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 5; 164 buf[11]; 165 snprintf(buf,11,"%u",1500); 166 tokens[index] = buf; 167 // hide promote/remove buttons 168 if(CaptainGuid != PlayerGuid) 169 { 170 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6); 171 buf[11]; 172 snprintf(buf,11,"%u",1); 173 tokens[index] = buf; 174 } 175 176 Player::SaveValuesArrayInDB(tokens,PlayerGuid); 177 155 178 return true; 156 179 } … … 158 181 bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) 159 182 { 160 LoadStatsFromDB(ArenaTeamId);161 LoadMembersFromDB(ArenaTeamId);162 163 // 0 1 2 3 4 5 6 7 8164 183 QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); 165 184 … … 181 200 delete result; 182 201 202 // only load here, so additional checks can be made 203 LoadStatsFromDB(ArenaTeamId); 204 LoadMembersFromDB(ArenaTeamId); 205 206 if(!GetMembersSize()) 207 { 208 // arena team is empty, delete from db 209 CharacterDatabase.BeginTransaction(); 210 CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); 211 CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 212 CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); 213 CharacterDatabase.CommitTransaction(); 214 // return false 215 return false; 216 } 217 183 218 return true; 184 219 } … … 208 243 Field *fields; 209 244 210 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId);245 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season,points_to_add FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 211 246 if(!result) 212 247 return; … … 217 252 ArenaTeamMember newmember; 218 253 newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); 254 // check if this member is in this arenateam 255 // based on character data field 256 if(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6),newmember.guid) != ArenaTeamId) 257 { 258 // the player's registered arena team for this slot isn't this team, so delete member info from here 259 CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u' AND arenateamid = '%u'",fields[0].GetUInt32(), ArenaTeamId); 260 continue; 261 } 219 262 LoadPlayerStats(&newmember); 220 263 newmember.played_week = fields[1].GetUInt32(); … … 277 320 278 321 Player *player = objmgr.GetPlayer(guid); 322 // this will be ugly. because of the asynchronous sql handling, we have to set all the fields of the player at once, and save them at once, or else the save will only modify the last field. 323 // rip off of setuint32valueindb 279 324 if(player) 280 325 { 281 326 player->SetInArenaTeam(0, GetSlot()); 282 327 player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0); 283 } 284 else 285 { 286 Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid); 287 } 288 289 CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid)); 328 // delete all info regarding this team 329 for(int i = 0; i < 6; ++i) 330 { 331 player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0); 332 } 333 } 334 335 // we have to do it this way, setuint32valueindb is asynch, unsafe to use multiple times in a row on the same player 336 Tokens tokens; 337 if(!Player::LoadValuesArrayFromDB(tokens,guid)) 338 return; 339 340 for(int i = 0; i < 6; ++i) 341 { 342 uint16 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i; 343 char buf[11]; 344 snprintf(buf,11,"%u",0); 345 tokens[index] = buf; 346 } 347 348 Player::SaveValuesArrayInDB(tokens,guid); 349 350 // only delete from this arena team! 351 CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid)); 290 352 } 291 353 … … 314 376 CharacterDatabase.BeginTransaction(); 315 377 CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id); 378 CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); 316 379 CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id); 317 380 CharacterDatabase.CommitTransaction(); … … 343 406 data << uint32(itr->played_season); // played this season 344 407 data << uint32(itr->wons_season); // wins this season 345 data << uint32( 0); // personal rating?408 data << uint32(pl->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5)); // personal rating? 346 409 } 347 410 else … … 357 420 data << uint32(itr->played_season); // played this season 358 421 data << uint32(itr->wons_season); // wins this season 359 data << uint32( 0); // personal rating?422 data << uint32(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5, itr->guid)); // personal rating? 360 423 } 361 424 } … … 392 455 } 393 456 457 void ArenaTeam::NotifyStatsChanged() 458 { 459 // this is called after a rated match ended 460 // updates arena team stats for every member of the team (not only the ones who participated!) 461 for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 462 { 463 Player * plr=objmgr.GetPlayer(itr->guid); 464 if(plr) 465 Stats(plr->GetSession()); 466 } 467 } 468 394 469 void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) 395 470 { … … 399 474 data << uint32(GetId()); // arena team id 400 475 data << uint32(stats.rating); // rating 401 data << uint32(stats.games); // games 402 data << uint32(stats.wins); // wins 403 data << uint32(stats.played); // played (count of all games, that played...) 404 data << uint32(0); // 2.3.3 personal rating? 476 data << uint32(stats.played); // season played 477 data << uint32(stats.wins2); // season wins 478 uint32 participated = 0; 479 for(MemberList::iterator itr = members.begin(); itr!= members.end(); ++itr) 480 { 481 if(itr->guid == guid) 482 { 483 participated = itr->played_season; 484 break; 485 } 486 } 487 data << uint32(participated); // played (count of all games, that the inspected member participated...) 488 data << uint32(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5, guid)); // unk, 2.3.3 (personal rating?) 489 405 490 session->SendPacket(&data); 406 491 } … … 495 580 } 496 581 582 uint32 ArenaTeam::GetPoints(uint32 MemberRating) 583 { 584 // returns how many points would be awarded with this team type with this rating 585 float points; 586 587 uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating; 588 589 if(rating<=1500) 590 { 591 points = (float)rating * 0.22f + 14.0f; 592 } 593 else 594 { 595 points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating)); 596 } 597 598 // type penalties for <5v5 teams 599 if(Type == ARENA_TEAM_2v2) 600 points *= 0.76f; 601 else if(Type == ARENA_TEAM_3v3) 602 points *= 0.88f; 603 604 return (uint32) points; 605 } 606 607 float ArenaTeam::GetChanceAgainst(uint32 rating) 608 { 609 // returns the chance to win against a team with the given rating, used in the rating adjustment calculation 610 // ELO system 611 return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)rating - (float)stats.rating)/400.0f)); 612 } 613 614 int32 ArenaTeam::WonAgainstChance(float chance) 615 { 616 // called when the team has won, and had 'chance' calculated chance to beat the opponent 617 // calculate the rating modification (ELO system with k=32) 618 int32 mod = (int32)floor(32.0f * (1.0f - chance)); 619 // modify the team stats accordingly 620 stats.rating += mod; 621 stats.games += 1; 622 stats.wins += 1; 623 stats.played += 1; 624 stats.wins2 += 1; 625 /* this should be done in .flusharenapoints; not a breaker though. 626 uint32 higher_rank = 0; 627 QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT(arenateamid) FROM arena_team_stats WHERE rating > '%u' AND arenateamid <> '%u'",stats.rating, Id); 628 if(result) 629 { 630 higher_rank = result->Fetch()->GetUInt32(); 631 delete result; 632 } 633 stats.rank = higher_rank + 1;*/ 634 // return the rating change, used to display it on the results screen 635 return mod; 636 } 637 638 int32 ArenaTeam::LostAgainstChance(float chance) 639 { 640 // called when the team has lost, and had 'chance' calculated chance to beat the opponent 641 // calculate the rating modification (ELO system with k=32) 642 int32 mod = (int32)ceil(32.0f * (0.0f - chance)); 643 // modify the team stats accordingly 644 stats.rating += mod; 645 stats.games += 1; 646 stats.played += 1; 647 /* uint32 higher_rank = 0; 648 QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT (arenateamid) FROM arena_team_stats WHERE rating > '%u' AND arenateamid <> '%u'",stats.rating, Id); 649 if(result) 650 { 651 higher_rank = result->Fetch()->GetUInt32(); 652 delete result; 653 } 654 stats.rank = higher_rank + 1;*/ 655 // return the rating adjustment for display 656 return mod; 657 } 658 659 void ArenaTeam::MemberLost(Player * plr, uint32 againstrating) 660 { 661 // called for each participant of a match after losing 662 for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 663 { 664 if(itr->guid == plr->GetGUID()) 665 { 666 // update personal rating 667 int32 personalrating = plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5); 668 float chance = 1.0f/(1.0f+exp(log(10.0f)*(float)((float)againstrating - (float)personalrating)/400.0f)); 669 int32 mod = (int32)ceil(32.0f * (0.0f - chance)); 670 personalrating += mod; 671 if(personalrating < 0) 672 personalrating = 0; 673 plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, personalrating); 674 // update personal played stats 675 itr->played_week +=1; 676 itr->played_season +=1; 677 // update the unit fields 678 plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->played_week); 679 plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->played_season); 680 return; 681 } 682 } 683 } 684 685 void ArenaTeam::MemberWon(Player * plr, uint32 againstrating) 686 { 687 // called for each participant after winning a match 688 for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 689 { 690 if(itr->guid == plr->GetGUID()) 691 { 692 // update personal rating 693 int32 personalrating = plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5); 694 float chance = 1.0f/(1.0f+exp(log(10.0f)*(float)((float)againstrating - (float)personalrating)/400.0f)); 695 int32 mod = (int32)floor(32.0f * (1.0f - chance)); 696 personalrating += mod; 697 if(personalrating < 0) 698 personalrating = 0; 699 plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, personalrating); 700 // update personal stats 701 itr->played_week +=1; 702 itr->played_season +=1; 703 itr->wons_season += 1; 704 itr->wons_week += 1; 705 // update unit fields 706 plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->played_week); 707 plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->played_season); 708 return; 709 } 710 } 711 } 712 713 void ArenaTeam::UpdateArenaPointsHelper() 714 { 715 // called after a match has ended and the stats are already modified 716 // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons) 717 // 10 played games per week is a minimum 718 if(stats.games < 10) 719 return; 720 // to get points, a player has to participate in at least 30% of the matches 721 uint32 min_plays = ceil(stats.games * 0.3); 722 for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 723 { 724 // the player participated in enough games, update his points 725 if(itr->played_week >= min_plays) 726 { 727 // do it separately for online and offline players 728 // online players might have modified personal rating in MemberLost/MemberWon, that's not already saved to DB because of asynch queries 729 // offline player cant have a personal rating not matching the db 730 Player * plr = objmgr.GetPlayer(itr->guid); 731 uint32 points_to_add = 0; 732 if(plr) 733 points_to_add = GetPoints(plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5)); 734 else 735 points_to_add = GetPoints(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5,itr->guid)); 736 // it's enough to set the points in memory, the saving is done in separate function 737 CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid); 738 } 739 // the player failed to participate in enough games, so no points for him 740 else 741 { 742 CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", 0, Id, itr->guid); 743 } 744 } 745 } 746 747 void ArenaTeam::SaveToDB() 748 { 749 // save team and member stats to db 750 // called after a match has ended 751 CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games, stats.played, stats.rank, stats.wins, stats.wins2, GetId()); 752 for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 753 { 754 CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->played_week, itr->wons_week, itr->played_season, itr->wons_season, Id, itr->guid); 755 } 756 } 757 758 void ArenaTeam::FinishWeek() 759 { 760 stats.games = 0; // played this week 761 stats.wins = 0; // wins this week 762 for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 763 { 764 itr->played_week = 0; 765 itr->wons_week = 0; 766 } 767 } 768 497 769 /* 498 770 arenateam fields (id from 2.3.3 client): 499 771 1414 - arena team id 2v2 500 772 1415 - 0=captain, 1=member 501 1416 - played this season502 1417 - played this week773 1416 - played this week 774 1417 - played this season 503 775 1418 - unk 504 1419 - unk776 1419 - personal arena rating 505 777 1420 - arena team id 3v3 506 778 1421 - 0=captain, 1=member 507 1422 - played this season508 1423 - played this week779 1422 - played this week 780 1423 - played this season 509 781 1424 - unk 510 1425 - unk782 1425 - personal arena rating 511 783 1426 - arena team id 5v5 512 784 1427 - 0=captain, 1=member 513 1428 - played this season514 1429 - played this week785 1428 - played this week 786 1429 - played this season 515 787 1430 - unk 516 1431 - unk788 1431 - personal arena rating 517 789 */ -
trunk/src/game/ArenaTeam.h
r2 r9 150 150 void LoadPlayerStats(ArenaTeamMember* member); 151 151 152 void SaveToDB(); 153 152 154 void BroadcastPacket(WorldPacket *packet); 153 155 … … 156 158 void Stats(WorldSession *session); 157 159 void InspectStats(WorldSession *session, uint64 guid); 160 161 uint32 GetPoints(uint32 MemberRating); 162 float GetChanceAgainst(uint32 rating); 163 int32 WonAgainstChance(float chance); 164 void MemberWon(Player * plr, uint32 againstrating); 165 int32 LostAgainstChance(float chance); 166 void MemberLost(Player * plr, uint32 againstrating); 167 168 void UpdateArenaPointsHelper(); 169 170 void FinishWeek(); 171 172 void NotifyStatsChanged(); 158 173 159 174 protected: -
trunk/src/game/BattleGround.cpp
r2 r9 25 25 #include "Chat.h" 26 26 #include "SpellAuras.h" 27 #include "ArenaTeam.h" 27 28 #include "World.h" 28 29 #include "Util.h" … … 48 49 m_LevelMin = 0; 49 50 m_LevelMax = 0; 51 m_InBGFreeSlotQueue = false; 52 m_SetDeleteThis = false; 50 53 51 54 m_MaxPlayersPerTeam = 0; … … 68 71 m_TeamStartLocO[BG_TEAM_HORDE] = 0; 69 72 73 m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0; 74 m_ArenaTeamIds[BG_TEAM_HORDE] = 0; 75 76 m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0; 77 m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0; 78 70 79 m_BgRaids[BG_TEAM_ALLIANCE] = NULL; 71 80 m_BgRaids[BG_TEAM_HORDE] = NULL; … … 73 82 m_PlayersCount[BG_TEAM_ALLIANCE] = 0; 74 83 m_PlayersCount[BG_TEAM_HORDE] = 0; 84 85 m_PrematureCountDown = false; 86 m_PrematureCountDown = 0; 75 87 } 76 88 77 89 BattleGround::~BattleGround() 78 90 { 79 91 // remove objects and creatures 92 // (this is done automatically in mapmanager update, when the instance is reset after the reset time) 93 int size = m_BgCreatures.size(); 94 for(int i = 0; i < size; ++i) 95 { 96 DelCreature(i); 97 } 98 size = m_BgObjects.size(); 99 for(int i = 0; i < size; ++i) 100 { 101 DelObject(i); 102 } 103 104 // delete creature and go respawn times 105 WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID()); 106 WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID()); 107 // delete instance from db 108 CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID()); 109 // remove from battlegrounds 110 sBattleGroundMgr.RemoveBattleGround(GetInstanceID()); 111 // unload map 112 if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID())) 113 if(map->IsBattleGroundOrArena()) 114 ((BattleGroundMap*)map)->SetUnload(); 115 // remove from bg free slot queue 116 this->RemoveFromBGFreeSlotQueue(); 80 117 } 81 118 82 119 void BattleGround::Update(time_t diff) 83 120 { 84 85 121 if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) 86 122 //BG is empty … … 189 225 } 190 226 227 // if less then minimum players are in on one side, then start premature finish timer 228 if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam())) 229 { 230 if(!m_PrematureCountDown) 231 { 232 m_PrematureCountDown = true; 233 m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime(); 234 SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); 235 } 236 else if(m_PrematureCountDownTimer < diff) 237 { 238 // time's up! 239 EndBattleGround(0); // noone wins 240 m_PrematureCountDown = false; 241 } 242 else 243 { 244 uint32 newtime = m_PrematureCountDownTimer - diff; 245 // announce every minute 246 if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000) 247 SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); 248 m_PrematureCountDownTimer = newtime; 249 } 250 } 251 else if (m_PrematureCountDown) 252 m_PrematureCountDown = false; 253 191 254 if(GetStatus() == STATUS_WAIT_LEAVE) 192 255 { … … 240 303 continue; 241 304 242 if(plr->GetTeam() == TeamID) 305 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 306 307 if(team == TeamID) 243 308 plr->GetSession()->SendPacket(packet); 244 309 } … … 266 331 } 267 332 268 if(plr->GetTeam() == TeamID) 333 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 334 335 if(team == TeamID) 269 336 { 270 337 sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID); … … 286 353 } 287 354 288 if(plr->GetTeam() == TeamID) 355 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 356 357 if(team == TeamID) 289 358 plr->CastSpell(plr, SpellID, true); 290 359 } … … 303 372 } 304 373 305 if(plr->GetTeam() == TeamID) 374 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 375 376 if(team == TeamID) 306 377 UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor); 307 378 } … … 325 396 } 326 397 327 if(plr->GetTeam() == TeamID) 398 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 399 400 if(team == TeamID) 328 401 plr->ModifyFactionReputation(factionEntry, Reputation); 329 402 } … … 346 419 void BattleGround::EndBattleGround(uint32 winner) 347 420 { 421 // battleground finished, remove from the running bg's list 422 this->RemoveFromBGFreeSlotQueue(); 423 424 ArenaTeam * winner_arena_team = NULL; 425 ArenaTeam * loser_arena_team = NULL; 426 uint32 loser_rating = 0; 427 uint32 winner_rating = 0; 348 428 WorldPacket data; 349 429 Player *Source = NULL; … … 352 432 if(winner == ALLIANCE) 353 433 { 354 winmsg = GetMangosString(LANG_BG_A_WINS); 434 if(isBattleGround()) 435 winmsg = GetMangosString(LANG_BG_A_WINS); 436 else 437 winmsg = GetMangosString(LANG_ARENA_GOLD_WINS); 355 438 356 439 PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound … … 358 441 SetWinner(WINNER_ALLIANCE); 359 442 } 443 else if(winner == HORDE) 444 { 445 if(isBattleGround()) 446 winmsg = GetMangosString(LANG_BG_H_WINS); 447 else 448 winmsg = GetMangosString(LANG_ARENA_GREEN_WINS); 449 450 PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound 451 452 SetWinner(WINNER_HORDE); 453 } 360 454 else 361 455 { 362 winmsg = GetMangosString(LANG_BG_H_WINS); 363 364 PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound 365 366 SetWinner(WINNER_HORDE); 456 SetWinner(3); 367 457 } 368 458 … … 370 460 m_EndTime = 0; 371 461 462 // arena rating calculation 463 if(isArena() && isRated()) 464 { 465 if(winner == ALLIANCE) 466 { 467 winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 468 loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 469 } 470 else if(winner == HORDE) 471 { 472 winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 473 loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 474 } 475 if(winner_arena_team && loser_arena_team) 476 { 477 loser_rating = loser_arena_team->GetStats().rating; 478 winner_rating = winner_arena_team->GetStats().rating; 479 float winner_chance = winner_arena_team->GetChanceAgainst(loser_rating); 480 float loser_chance = loser_arena_team->GetChanceAgainst(winner_rating); 481 int32 winner_change = winner_arena_team->WonAgainstChance(winner_chance); 482 int32 loser_change = loser_arena_team->LostAgainstChance(loser_chance); 483 sLog.outDebug("--- %u ; %u ; %d ; %d ; %u ; %u ---",winner_rating,loser_rating,winner_chance,loser_chance,winner_change,loser_change); 484 if(winner == ALLIANCE) 485 { 486 SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change); 487 SetArenaTeamRatingChangeForTeam(HORDE, loser_change); 488 } 489 else 490 { 491 SetArenaTeamRatingChangeForTeam(HORDE, winner_change); 492 SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change); 493 } 494 } 495 else 496 { 497 SetArenaTeamRatingChangeForTeam(ALLIANCE, 0); 498 SetArenaTeamRatingChangeForTeam(HORDE, 0); 499 } 500 } 501 372 502 for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) 373 503 { … … 379 509 } 380 510 511 // should remove spirit of redemption 512 if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) 513 plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); 514 381 515 if(!plr->isAlive()) 382 516 { … … 385 519 } 386 520 387 if(plr->GetTeam() == winner) 521 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); 522 if(!team) team = plr->GetTeam(); 523 524 // per player calculation 525 if(isArena() && isRated() && winner_arena_team && loser_arena_team) 526 { 527 if(team == winner) 528 winner_arena_team->MemberWon(plr,loser_rating); 529 else 530 loser_arena_team->MemberLost(plr,winner_rating); 531 } 532 533 if(team == winner) 388 534 { 389 535 if(!Source) … … 405 551 plr->GetSession()->SendPacket(&data); 406 552 407 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); 553 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); 554 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); 408 555 plr->GetSession()->SendPacket(&data); 409 556 } 557 558 if(isArena() && isRated() && winner_arena_team && loser_arena_team) 559 { 560 // update arena points only after increasing the player's match count! 561 winner_arena_team->UpdateArenaPointsHelper(); 562 loser_arena_team->UpdateArenaPointsHelper(); 563 // save the stat changes 564 winner_arena_team->SaveToDB(); 565 loser_arena_team->SaveToDB(); 566 // send updated arena team stats to players 567 // this way all arena team members will get notified, not only the ones who participated in this match 568 winner_arena_team->NotifyStatsChanged(); 569 loser_arena_team->NotifyStatsChanged(); 570 } 571 572 // inform invited players about the removal 573 sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); 410 574 411 575 if(Source) … … 559 723 void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) 560 724 { 725 uint32 team = GetPlayerTeam(guid); 726 bool participant = false; 561 727 // Remove from lists/maps 562 728 std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid); 563 729 if(itr != m_Players.end()) 564 730 { 565 UpdatePlayersCountByTeam( itr->second.Team, true); // -1 player731 UpdatePlayersCountByTeam(team, true); // -1 player 566 732 m_Players.erase(itr); 733 // check if the player was a participant of the match, or only entered through gm command (goname) 734 participant = true; 567 735 } 568 736 … … 578 746 Player *plr = objmgr.GetPlayer(guid); 579 747 748 // should remove spirit of redemption 749 if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) 750 plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); 751 580 752 if(plr && !plr->isAlive()) // resurrect on exit 581 753 { … … 590 762 plr->ClearAfkReports(); 591 763 592 if(isArena()) 593 { 594 if(!sWorld.IsFFAPvPRealm()) 595 plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); 596 } 597 598 WorldPacket data; 599 if(SendPacket) 600 { 601 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); 602 plr->GetSession()->SendPacket(&data); 603 } 604 605 // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg 606 plr->RemoveBattleGroundQueueId(m_TypeID); 607 608 DecreaseInvitedCount(plr->GetTeam()); 609 //we should update battleground queue, but only if bg isn't ending 610 if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) 611 sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType()); 612 613 if(!plr->GetBattleGroundId()) 614 return; 615 616 Group * group = plr->GetGroup(); 617 618 // remove from raid group if exist 619 if(group && group == GetBgRaid(plr->GetTeam())) 620 { 621 if(!group->RemoveMember(guid, 0)) // group was disbanded 764 if(participant) // if the player was a match participant, remove auras, calc rating, update queue 765 { 766 if(!team) team = plr->GetTeam(); 767 768 uint32 bgTypeId = GetTypeID(); 769 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); 770 // if arena, remove the specific arena auras 771 if(isArena()) 622 772 { 623 SetBgRaid(plr->GetTeam(), NULL); 624 delete group; 773 plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out 774 bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing) 775 776 // summon old pet if there was one and there isn't a current pet 777 if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber()) 778 { 779 Pet* NewPet = new Pet; 780 if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true)) 781 delete NewPet; 782 783 (plr)->SetTemporaryUnsummonedPetNumber(0); 784 } 785 786 if(isRated() && GetStatus() == STATUS_IN_PROGRESS) 787 { 788 //left a rated match while the encounter was in progress, consider as loser 789 ArenaTeam * winner_arena_team = 0; 790 ArenaTeam * loser_arena_team = 0; 791 if(team == HORDE) 792 { 793 winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 794 loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 795 } 796 else 797 { 798 winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); 799 loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); 800 } 801 if(winner_arena_team && loser_arena_team) 802 { 803 loser_arena_team->MemberLost(plr,winner_arena_team->GetRating()); 804 } 805 } 625 806 } 807 808 WorldPacket data; 809 if(SendPacket) 810 { 811 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); 812 plr->GetSession()->SendPacket(&data); 813 } 814 815 // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg 816 plr->RemoveBattleGroundQueueId(bgQueueTypeId); 817 818 DecreaseInvitedCount(team); 819 //we should update battleground queue, but only if bg isn't ending 820 if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) 821 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType()); 822 823 Group * group = plr->GetGroup(); 824 // remove from raid group if exist 825 if(group && group == GetBgRaid(team)) 826 { 827 if(!group->RemoveMember(guid, 0)) // group was disbanded 828 { 829 SetBgRaid(team, NULL); 830 delete group; 831 } 832 } 833 834 // Let others know 835 sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); 836 SendPacketToTeam(team, &data, plr, false); 626 837 } 627 838 628 839 // Do next only if found in battleground 629 840 plr->SetBattleGroundId(0); // We're not in BG. 630 631 // Let others know 632 sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); 633 SendPacketToTeam(plr->GetTeam(), &data, plr, false); 841 // reset destination bg team 842 plr->SetBGTeam(0); 634 843 635 844 if(Transport) 636 845 { 637 846 plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); 638 //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O);639 847 } 640 848 … … 643 851 } 644 852 645 /// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist 646 // we always should check if BG is in that queue before adding.. 647 648 if(!GetPlayersSize()) 649 { 650 Reset(); 651 } 853 if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE)) 854 { 855 // if no players left AND no invitees left, set this bg to delete in next update 856 // direct deletion could cause crashes 857 m_SetDeleteThis = true; 858 // return to prevent addition to freeslotqueue 859 return; 860 } 861 862 // a player exited the battleground, so there are free slots. add to queue 863 this->AddToBGFreeSlotQueue(); 652 864 } 653 865 … … 661 873 SetEndTime(0); 662 874 SetLastResurrectTime(0); 875 SetArenaType(0); 876 SetRated(false); 663 877 664 878 m_Events = 0; … … 669 883 m_InvitedAlliance = 0; 670 884 m_InvitedHorde = 0; 885 m_InBGFreeSlotQueue = false; 671 886 672 887 m_Players.clear(); 673 888 m_PlayerScores.clear(); 674 889 675 // reset BGSubclass 890 // reset BGSubclass (this cleans up creatures and gos as well) 676 891 this->ResetBGSubclass(); 677 892 } … … 699 914 m_Players[guid] = bp; 700 915 701 UpdatePlayersCountByTeam(team, false); 916 UpdatePlayersCountByTeam(team, false); // +1 player 702 917 703 918 WorldPacket data; … … 705 920 SendPacketToTeam(team, &data, plr, false); 706 921 922 // add arena specific auras 707 923 if(isArena()) 708 924 { 925 // remove auras first, only then reset spell cooldowns 926 // this is to prevent bugging amp. curse, combustion, etc. like spells 927 plr->RemoveArenaAuras(); 709 928 plr->RemoveArenaSpellCooldowns(); 710 //plr->RemoveArenaAuras();711 929 plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT); 712 930 if(team == ALLIANCE && plr->GetTeam() == ALLIANCE) … … 720 938 plr->DestroyConjuredItems(true); 721 939 940 Pet* pet = plr->GetPet(); 941 if(pet) 942 { 943 if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET) 944 { 945 (plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber()); 946 (plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)); 947 } 948 (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); 949 } 950 722 951 if(GetStatus() == STATUS_WAIT_JOIN) // not started yet 723 952 { … … 734 963 } 735 964 736 if(isArena())737 plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);738 739 965 // Log 740 966 sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName()); … … 744 970 void BattleGround::AddToBGFreeSlotQueue() 745 971 { 746 sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); 972 // make sure to add only once 973 if(!m_InBGFreeSlotQueue) 974 { 975 sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); 976 m_InBGFreeSlotQueue = true; 977 } 747 978 } 748 979 … … 750 981 void BattleGround::RemoveFromBGFreeSlotQueue() 751 982 { 752 /* uncomment this code when battlegrounds will work like instances 983 // set to be able to re-add if needed 984 m_InBGFreeSlotQueue = false; 985 // uncomment this code when battlegrounds will work like instances 753 986 for (std::deque<BattleGround*>::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) 754 987 { … … 758 991 return; 759 992 } 760 }*/ 761 } 762 763 /* 764 this method should decide, if we can invite new player of certain team to BG, it is based on BATTLEGROUND_STATUS 765 */ 766 bool BattleGround::HasFreeSlotsForTeam(uint32 Team) const 993 } 994 } 995 996 // get the number of free slots for team 997 // works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group 998 uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const 767 999 { 768 1000 //if BG is starting ... invite anyone: 769 1001 if (GetStatus() == STATUS_WAIT_JOIN) 770 return GetInvitedCount(Team) < GetMaxPlayersPerTeam();1002 return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; 771 1003 //if BG is already started .. do not allow to join too much players of one faction 772 1004 uint32 otherTeam; 1005 uint32 otherIn; 773 1006 if (Team == ALLIANCE) 1007 { 774 1008 otherTeam = GetInvitedCount(HORDE); 1009 otherIn = GetPlayersCountByTeam(HORDE); 1010 } 775 1011 else 1012 { 776 1013 otherTeam = GetInvitedCount(ALLIANCE); 1014 otherIn = GetPlayersCountByTeam(ALLIANCE); 1015 } 777 1016 if (GetStatus() == STATUS_IN_PROGRESS) 778 return (GetInvitedCount(Team) <= otherTeam && GetInvitedCount(Team) < GetMaxPlayersPerTeam()); 779 780 return false; 781 } 782 783 /* this method isn't called already, it will be useful when more battlegrounds of one type will be available */ 1017 { 1018 // difference based on ppl invited (not necessarily entered battle) 1019 // default: allow 0 1020 uint32 diff = 0; 1021 // allow join one person if the sides are equal (to fill up bg to minplayersperteam) 1022 if (otherTeam == GetInvitedCount(Team)) 1023 diff = 1; 1024 // allow join more ppl if the other side has more players 1025 else if(otherTeam > GetInvitedCount(Team)) 1026 diff = otherTeam - GetInvitedCount(Team); 1027 1028 // difference based on max players per team (don't allow inviting more) 1029 uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; 1030 1031 // difference based on players who already entered 1032 // default: allow 0 1033 uint32 diff3 = 0; 1034 // allow join one person if the sides are equal (to fill up bg minplayersperteam) 1035 if (otherIn == GetPlayersCountByTeam(Team)) 1036 diff3 = 1; 1037 // allow join more ppl if the other side has more players 1038 else if (otherIn > GetPlayersCountByTeam(Team)) 1039 diff3 = otherIn - GetPlayersCountByTeam(Team); 1040 1041 // return the minimum of the 3 differences 1042 1043 // min of diff and diff 2 1044 diff = diff < diff2 ? diff : diff2; 1045 1046 // min of diff, diff2 and diff3 1047 return diff < diff3 ? diff : diff3 ; 1048 } 1049 1050 return 0; 1051 } 1052 784 1053 bool BattleGround::HasFreeSlots() const 785 1054 { … … 807 1076 break; 808 1077 case SCORE_BONUS_HONOR: // Honor bonus 809 // reward honor instantly 810 if(Source->RewardHonor(NULL, 1, value)) 811 itr->second->BonusHonor += value; 1078 // do not add honor in arenas 1079 if(isBattleGround()) 1080 { 1081 // reward honor instantly 1082 if(Source->RewardHonor(NULL, 1, value)) 1083 itr->second->BonusHonor += value; 1084 } 812 1085 break; 813 1086 //used only in EY, but in MSG_PVP_LOG_DATA opcode … … 865 1138 bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime) 866 1139 { 867 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); 868 if(!goinfo) 1140 Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); 1141 if(!map) 1142 return false; 1143 1144 // must be created this way, adding to godatamap would add it to the base map of the instance 1145 // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created 1146 // so we must create it specific for this instance 1147 GameObject * go = new GameObject; 1148 if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) 869 1149 { 870 1150 sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); 1151 sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry); 1152 delete go; 871 1153 return false; 872 1154 } 873 874 uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); 875 1155 /* 1156 uint32 guid = go->GetGUIDLow(); 1157 1158 // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata 1159 // iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed 876 1160 GameObjectData& data = objmgr.NewGOData(guid); 877 1161 … … 887 1171 data.rotation3 = rotation3; 888 1172 data.spawntimesecs = respawnTime; 1173 data.spawnMask = 1; 889 1174 data.animprogress = 100; 890 1175 data.go_state = 1; 891 data.spawnMask = 1; 892 objmgr.AddGameobjectToGrid(guid, &data); 893 894 m_BgObjects[type] = MAKE_NEW_GUID(guid, entry, HIGHGUID_GAMEOBJECT); 895 1176 */ 1177 // add to world, so it can be later looked up from HashMapHolder 1178 go->AddToWorld(); 1179 m_BgObjects[type] = go->GetGUID(); 896 1180 return true; 897 1181 } … … 935 1219 void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) 936 1220 { 1221 Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); 1222 if(!map) 1223 return; 937 1224 if( respawntime == 0 ) 938 1225 { … … 943 1230 if( obj->getLootState() == GO_JUST_DEACTIVATED ) 944 1231 obj->SetLootState(GO_READY); 945 obj->Respawn(); 946 } 947 else 948 objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0); 1232 obj->SetRespawnTime(0); 1233 map->Add(obj); 1234 } 949 1235 } 950 1236 else … … 953 1239 if(obj) 954 1240 { 1241 map->Add(obj); 955 1242 obj->SetRespawnTime(respawntime); 956 1243 obj->SetLootState(GO_JUST_DEACTIVATED); 957 1244 } 958 else 959 objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime); 960 } 961 } 962 963 Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o) 964 { 965 // note: this should normally be FindMap 966 // but it's a hack to allow the battlegrounds to initialize at server startup 967 Map * map = MapManager::Instance().GetMap(GetMapId(), 0); 968 if(!map) return NULL; 1245 } 1246 } 1247 1248 Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime) 1249 { 1250 Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); 1251 if(!map) 1252 return NULL; 969 1253 970 1254 Creature* pCreature = new Creature; … … 990 1274 map->Add(pCreature); 991 1275 m_BgCreatures[type] = pCreature->GetGUID(); 1276 992 1277 return pCreature; 993 1278 } … … 1073 1358 void BattleGround::EndNow() 1074 1359 { 1360 RemoveFromBGFreeSlotQueue(); 1075 1361 SetStatus(STATUS_WAIT_LEAVE); 1076 1362 SetEndTime(TIME_TO_AUTOREMOVE); 1363 // inform invited players about the removal 1364 sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); 1077 1365 } 1078 1366 … … 1152 1440 player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE ); 1153 1441 } 1442 1443 // return the player's team based on battlegroundplayer info 1444 // used in same faction arena matches mainly 1445 uint32 BattleGround::GetPlayerTeam(uint64 guid) 1446 { 1447 std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid); 1448 if(itr!=m_Players.end()) 1449 return itr->second.Team; 1450 return 0; 1451 } 1452 1453 uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const 1454 { 1455 int count = 0; 1456 for(std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) 1457 { 1458 if(itr->second.Team == Team) 1459 { 1460 Player * pl = objmgr.GetPlayer(itr->first); 1461 if(pl && pl->isAlive()) 1462 ++count; 1463 } 1464 } 1465 return count; 1466 } -
trunk/src/game/BattleGround.h
r2 r9 142 142 BATTLEGROUND_EY = 7, 143 143 BATTLEGROUND_RL = 8 144 }; 145 146 // handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time 147 enum BattleGroundQueueTypeId 148 { 149 BATTLEGROUND_QUEUE_AV = 1, 150 BATTLEGROUND_QUEUE_WS = 2, 151 BATTLEGROUND_QUEUE_AB = 3, 152 BATTLEGROUND_QUEUE_EY = 4, 153 BATTLEGROUND_QUEUE_2v2 = 5, 154 BATTLEGROUND_QUEUE_3v3 = 6, 155 BATTLEGROUND_QUEUE_5v5 = 7, 144 156 }; 145 157 … … 196 208 }; 197 209 210 enum BattleGroundJoinError 211 { 212 BG_JOIN_ERR_OK = 0, 213 BG_JOIN_ERR_OFFLINE_MEMBER = 1, 214 BG_JOIN_ERR_GROUP_TOO_MANY = 2, 215 BG_JOIN_ERR_MIXED_FACTION = 3, 216 BG_JOIN_ERR_MIXED_LEVELS = 4, 217 BG_JOIN_ERR_MIXED_ARENATEAM = 5, 218 BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE = 6, 219 BG_JOIN_ERR_GROUP_DESERTER = 7, 220 BG_JOIN_ERR_ALL_QUEUES_USED = 8, 221 BG_JOIN_ERR_GROUP_NOT_ENOUGH = 9 222 }; 223 198 224 class BattleGroundScore 199 225 { … … 297 323 bool HasFreeSlotsForTeam(uint32 Team) const; 298 324 bool HasFreeSlots() const; 325 uint32 GetFreeSlotsForTeam(uint32 Team) const; 299 326 300 327 bool isArena() const { return m_IsArena; } … … 367 394 uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; } 368 395 uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; } 396 uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases 369 397 void UpdatePlayersCountByTeam(uint32 Team, bool remove) 370 398 { … … 375 403 } 376 404 405 // used for rated arena battles 406 void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; } 407 uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } 408 void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; } 409 int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } 410 377 411 /* Triggers handle */ 378 412 // must be implemented in BG subclass … … 391 425 392 426 virtual void AddPlayer(Player *plr); // must be implemented in BG subclass 427 393 428 virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); 394 429 // can be extended in in BG subclass … … 403 438 void SpawnBGObject(uint32 type, uint32 respawntime); 404 439 bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0); 405 Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o); 440 // void SpawnBGCreature(uint32 type, uint32 respawntime); 441 Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0); 406 442 bool DelCreature(uint32 type); 407 443 bool DelObject(uint32 type); … … 411 447 void DoorClose(uint32 type); 412 448 const char *GetMangosString(int32 entry); 449 450 virtual bool HandlePlayerUnderMap(Player * plr) {return false;} 451 452 // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player 453 uint32 GetPlayerTeam(uint64 guid); 454 455 void SetDeleteThis() {m_SetDeleteThis = true;} 413 456 414 457 protected: … … 444 487 uint32 m_Queue_type; 445 488 uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 489 bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque 490 bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave 446 491 // this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless 447 492 //uint8 m_BattleGroundType; // 3=BG, 4=arena … … 451 496 int32 m_StartDelayTime; 452 497 bool m_IsRated; // is this battle rated? 498 bool m_PrematureCountDown; 499 uint32 m_PrematureCountDownTimer; 453 500 char const *m_Name; 454 501 … … 468 515 /* Players count by team */ 469 516 uint32 m_PlayersCount[2]; 517 518 /* Arena team ids by team */ 519 uint32 m_ArenaTeamIds[2]; 520 521 int32 m_ArenaTeamRatingChanges[2]; 470 522 471 523 /* Limits */ -
trunk/src/game/BattleGroundAB.cpp
r2 r9 50 50 { 51 51 m_Events |= 0x01; 52 53 // setup here, only when at least one player has ported to the map 54 if(!SetupBattleGround()) 55 { 56 EndNow(); 57 return; 58 } 52 59 53 60 sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ..."); -
trunk/src/game/BattleGroundBE.cpp
r2 r9 48 48 { 49 49 m_Events |= 0x01; 50 // setup here, only when at least one player has ported to the map 51 if(!SetupBattleGround()) 52 { 53 EndNow(); 54 return; 55 } 50 56 for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++) 51 57 SpawnBGObject(i, RESPAWN_IMMEDIATELY); … … 87 93 if(Player *plr = objmgr.GetPlayer(itr->first)) 88 94 plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); 95 96 if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 97 EndBattleGround(HORDE); 98 else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) 99 EndBattleGround(ALLIANCE); 89 100 } 90 101 } … … 103 114 104 115 m_PlayerScores[plr->GetGUID()] = sc; 116 117 UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); 118 UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); 105 119 } 106 120 107 121 void BattleGroundBE::RemovePlayer(Player *plr, uint64 guid) 108 122 { 109 123 if(GetStatus() == STATUS_WAIT_LEAVE) 124 return; 125 126 UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); 127 UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); 128 129 if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 130 EndBattleGround(HORDE); 131 else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) 132 EndBattleGround(ALLIANCE); 110 133 } 111 134 … … 121 144 } 122 145 123 BattleGround::HandleKillPlayer(player, killer); 124 125 uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); 126 127 ++m_TeamKills[killer_team_index]; // add kills to killer's team 128 129 if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) 146 BattleGround::HandleKillPlayer(player,killer); 147 148 UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); 149 UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); 150 151 if(!GetAlivePlayersCountByTeam(ALLIANCE)) 130 152 { 131 153 // all opponents killed 132 EndBattleGround(killer->GetTeam()); 133 } 154 EndBattleGround(HORDE); 155 } 156 else if(!GetAlivePlayersCountByTeam(HORDE)) 157 { 158 // all opponents killed 159 EndBattleGround(ALLIANCE); 160 } 161 } 162 163 bool BattleGroundBE::HandlePlayerUnderMap(Player *player) 164 { 165 player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false); 166 return true; 134 167 } 135 168 … … 160 193 } 161 194 195 void BattleGroundBE::FillInitialWorldStates(WorldPacket &data) 196 { 197 data << uint32(0x9f1) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 198 data << uint32(0x9f0) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 199 data << uint32(0x9f3) << uint32(1); // 9 200 } 201 162 202 void BattleGroundBE::ResetBGSubclass() 163 203 { 164 m_TeamKills[BG_TEAM_ALLIANCE] = 0; 165 m_TeamKills[BG_TEAM_HORDE] = 0; 204 166 205 } 167 206 -
trunk/src/game/BattleGroundBE.h
r2 r9 65 65 bool SetupBattleGround(); 66 66 void ResetBGSubclass(); 67 virtual void FillInitialWorldStates(WorldPacket &d); 67 68 void HandleKillPlayer(Player* player, Player *killer); 69 bool HandlePlayerUnderMap(Player * plr); 68 70 69 71 /* Scorekeeping */ 70 72 void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); 71 72 private:73 uint32 m_TeamKills[2]; // count of kills for each team74 73 }; 75 74 #endif -
trunk/src/game/BattleGroundEY.cpp
r2 r9 54 54 { 55 55 m_Events |= 0x01; 56 57 // setup here, only when at least one player has ported to the map 58 if(!SetupBattleGround()) 59 { 60 EndNow(); 61 return; 62 } 56 63 57 64 SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); … … 573 580 void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) 574 581 { 575 // Drop allowed in any BG state 582 if(GetStatus() != STATUS_IN_PROGRESS) 583 { 584 // if not running, do not cast things at the dropper player, neither send unnecessary messages 585 // just take off the aura 586 if(IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID()) 587 { 588 SetFlagPicker(0); 589 Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); 590 } 591 return; 592 } 576 593 577 594 if(!IsFlagPickedup()) -
trunk/src/game/BattleGroundHandler.cpp
r2 r9 27 27 #include "ObjectAccessor.h" 28 28 #include "Object.h" 29 #include "Chat.h" 30 #include "Language.h" 29 31 #include "BattleGroundMgr.h" 30 32 #include "BattleGroundWS.h" 31 33 #include "BattleGround.h" 34 #include "ArenaTeam.h" 32 35 33 36 void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) … … 76 79 uint32 instanceId; 77 80 uint8 joinAsGroup; 81 Group * grp; 78 82 79 83 recv_data >> guid; // battlemaster guid … … 82 86 recv_data >> joinAsGroup; // join as group 83 87 84 sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT " for BG (Type: %u)", guid, bgTypeId); 85 86 if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? 87 return; 88 if(bgTypeId >= MAX_BATTLEGROUND_TYPES) 89 { 90 sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow()); 91 return; 92 } 93 94 sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); 95 96 // can do this, since it's battleground, not arena 97 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0); 88 98 89 99 // ignore if we already in BG or BG queue … … 98 108 return; 99 109 100 // check Deserter debuff 101 if( !_player->CanJoinToBattleground() ) 102 { 103 WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 104 data << (uint32) 0xFFFFFFFE; 105 _player->GetSession()->SendPacket(&data); 106 return; 107 } 108 109 // check existence 110 BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); 111 if(!bg) 112 return; 113 114 if(joinAsGroup && _player->GetGroup()) 115 { 116 Group *grp = _player->GetGroup(); 110 // get bg instance or bg template if instance not found 111 BattleGround * bg = 0; 112 if(instanceId) 113 BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); 114 115 if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) 116 { 117 sLog.outError("Battleground: no available bg / template found"); 118 return; 119 } 120 121 // check queueing conditions 122 if(!joinAsGroup) 123 { 124 // check Deserter debuff 125 if( !_player->CanJoinToBattleground() ) 126 { 127 WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 128 data << (uint32) 0xFFFFFFFE; 129 _player->GetSession()->SendPacket(&data); 130 return; 131 } 132 // check if already in queue 133 if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) 134 //player is already in this queue 135 return; 136 // check if has free queue slots 137 if(!_player->HasFreeBattleGroundQueueId()) 138 return; 139 } 140 else 141 { 142 grp = _player->GetGroup(); 143 // no group found, error 144 if(!grp) 145 return; 146 uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); 147 switch(err) 148 { 149 // TODO: add error-based feedback to players in all cases 150 case BG_JOIN_ERR_GROUP_TOO_MANY: 151 { 152 WorldPacket data; 153 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_TOO_LARGE), NULL); 154 SendPacket(&data); 155 } 156 return; 157 break; 158 case BG_JOIN_ERR_OFFLINE_MEMBER: 159 { 160 WorldPacket data; 161 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_OFFLINE_MEMBER), NULL); 162 SendPacket(&data); 163 } 164 return; 165 break; 166 case BG_JOIN_ERR_MIXED_FACTION: 167 { 168 WorldPacket data; 169 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_FACTION), NULL); 170 SendPacket(&data); 171 } 172 return; 173 break; 174 case BG_JOIN_ERR_MIXED_LEVELS: 175 { 176 WorldPacket data; 177 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_LEVELS), NULL); 178 SendPacket(&data); 179 } 180 return; 181 break; 182 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE: 183 { 184 WorldPacket data; 185 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE), NULL); 186 SendPacket(&data); 187 } 188 return; 189 break; 190 case BG_JOIN_ERR_GROUP_DESERTER: 191 { 192 WorldPacket data; 193 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_DESERTER), NULL); 194 SendPacket(&data); 195 } 196 return; 197 break; 198 case BG_JOIN_ERR_ALL_QUEUES_USED: 199 { 200 WorldPacket data; 201 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS), NULL); 202 SendPacket(&data); 203 } 204 return; 205 break; 206 // all ok, can join 207 case BG_JOIN_ERR_OK: 208 break; 209 // these aren't possible outcomes in bgs 210 case BG_JOIN_ERR_GROUP_NOT_ENOUGH: 211 case BG_JOIN_ERR_MIXED_ARENATEAM: 212 return; 213 break; 214 // not the above? shouldn't happen, don't let join 215 default: 216 return; 217 break; 218 }; 219 } 220 221 // if we're here, then the conditions to join a bg are met. We can proceed in joining. 222 223 // _player->GetGroup() was already checked, grp is already initialized 224 if(joinAsGroup /* && _player->GetGroup()*/) 225 { 226 sLog.outDebug("Battleground: the following players are joining as group:"); 227 GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); 117 228 for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) 118 229 { 119 230 Player *member = itr->getSource(); 120 if(!member) continue; 121 122 if( !member->CanJoinToBattleground() ) 123 { 124 WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 125 data << (uint32) 0xFFFFFFFE; 126 _player->GetSession()->SendPacket(&data); 127 continue; 128 } 129 if (member->InBattleGroundQueueForBattleGroundType(bgTypeId)) 130 //player is already in this queue 131 continue; 132 133 WorldPacket data; 134 // add to queue 135 uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId); 136 if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 137 { 138 // fill data packet 139 //member->GetSession()->SendPacket(data); 140 continue; 141 } 231 if(!member) continue; // this should never happen 232 233 uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue 142 234 143 235 // store entry point coords (same as leader entry point) 144 236 member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); 145 237 238 WorldPacket data; 146 239 // send status packet (in queue) 147 240 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); … … 149 242 sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); 150 243 member->GetSession()->SendPacket(&data); 151 sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId); 152 } 244 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); 245 sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); 246 } 247 sLog.outDebug("Battleground: group end"); 248 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); 153 249 } 154 250 else 155 251 { 156 if (_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) 157 //player is already in this queue 158 return; 159 uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId); 160 if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 161 { 162 WorldPacket data; 163 // fill data packet 164 //SendPacket(data); 165 return; 166 } 167 252 // already checked if queueSlot is valid, now just get it 253 uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); 168 254 // store entry point coords 169 255 _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); … … 173 259 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); 174 260 SendPacket(&data); 175 sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId); 261 262 GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); 263 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); 264 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); 265 sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); 176 266 } 177 267 } … … 247 337 recv_data >> bgTypeId; // id from DBC 248 338 249 if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? 250 return; 251 252 // can't be received if player not in BG queue 253 if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) 254 return; 339 if(bgTypeId >= MAX_BATTLEGROUND_TYPES) 340 { 341 sLog.outError("Battleground: invalid bgtype received."); 342 return; 343 } 255 344 256 345 BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); … … 270 359 sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); 271 360 272 uint8 unk1;361 uint8 type; // arenatype if arena 273 362 uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 363 uint32 instanceId; 274 364 uint32 bgTypeId; // type id from dbc 275 365 uint16 unk; // 0x1F90 constant? 276 366 uint8 action; // enter battle 0x1, leave queue 0x0 277 367 278 recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action; 279 280 if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? 281 return; 282 283 if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) 284 return; 285 286 BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); 368 recv_data >> type >> unk2 >> bgTypeId >> unk >> action; 369 370 if(bgTypeId >= MAX_BATTLEGROUND_TYPES) 371 { 372 sLog.outError("Battleground: invalid bgtype received."); 373 // update battleground slots for the player to fix his UI and sent data. 374 // this is a HACK, I don't know why the client starts sending invalid packets in the first place. 375 // it usually happens with extremely high latency (if debugging / stepping in the code for example) 376 if(_player->InBattleGroundQueue()) 377 { 378 // update all queues, send invitation info if player is invited, queue info if queued 379 for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 380 { 381 uint32 queue_id = _player->GetBattleGroundQueueId(i); 382 if(!queue_id) 383 continue; 384 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 385 // if the player is not in queue, contine 386 if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 387 continue; 388 389 // no group information, this should never happen 390 if(!itrPlayerStatus->second.GroupInfo) 391 continue; 392 393 BattleGround * bg = NULL; 394 395 // get possibly needed data from groupinfo 396 bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId; 397 uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; 398 uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated; 399 uint8 status = 0; 400 401 402 if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) 403 { 404 // not invited to bg, get template 405 bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 406 status = STATUS_WAIT_QUEUE; 407 } 408 else 409 { 410 // get the bg we're invited to 411 BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID); 412 status = STATUS_WAIT_JOIN; 413 } 414 415 // if bg not found, then continue 416 if(!bg) 417 continue; 418 419 // don't invite if already in the instance 420 if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) 421 continue; 422 423 // re - invite player with proper data 424 WorldPacket data; 425 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted); 426 SendPacket(&data); 427 } 428 } 429 return; 430 } 431 432 uint32 bgQueueTypeId = 0; 433 // get the bg what we were invited to 434 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; 435 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type); 436 itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 437 438 if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 439 { 440 sLog.outError("Battleground: itrplayerstatus not found."); 441 return; 442 } 443 instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; 444 445 // if action == 1, then instanceId is _required_ 446 if(!instanceId && action == 1) 447 { 448 sLog.outError("Battleground: instance not found."); 449 return; 450 } 451 452 BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); 453 454 // bg template might and must be used in case of leaving queue, when instance is not created yet 455 if(!bg && action == 0) 456 bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 457 287 458 if(!bg) 288 return; 289 290 uint32 queueSlot = 0; 291 WorldPacket data; 292 switch(action) 293 { 294 case 1: // port to battleground 295 // cheating? 296 if(!_player->IsInvitedForBattleGroundType(bgTypeId)) 297 return; 298 299 // check if player is not deserter 300 if( !_player->CanJoinToBattleground() ) 301 { 302 WorldPacket data2; 303 data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); 304 data2 << (uint32) 0xFFFFFFFE; 305 SendPacket(&data2); 306 return; 307 } 308 309 // if the player is dead, resurrect him before teleport 310 if(!_player->isAlive()) 311 { 312 _player->ResurrectPlayer(1.0f,false); 313 _player->SpawnCorpseBones(); 314 } 315 316 // leave current group 317 _player->RemoveFromGroup(); 318 319 // packet to player about BG status 320 queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); 321 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); 322 _player->GetSession()->SendPacket(&data); 323 324 // remove battleground queue status from BGmgr 325 sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false); 326 327 // this is still needed here if battleground "jumping" shouldn't add deserter debuff 328 // also this required to prevent stuck at old battleground after SetBattleGroundId set to new 329 if (BattleGround *currentBg = _player->GetBattleGround()) 330 currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); 331 332 _player->SetBattleGroundId(bg->GetTypeID()); 333 sBattleGroundMgr.SendToBattleGround(_player, bgTypeId); 334 bg->AddPlayer(_player); 335 break; 336 case 0: // leave queue 337 queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); 338 _player->RemoveBattleGroundQueueId(bgTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs 339 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); 340 sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true); 341 SendPacket(&data); 342 break; 343 default: 344 sLog.outError("Battleground port: unknown action %u", action); 345 break; 459 { 460 sLog.outError("Battleground: bg not found."); 461 return; 462 } 463 464 bgTypeId = bg->GetTypeID(); 465 466 if(_player->InBattleGroundQueue()) 467 { 468 uint32 queueSlot = 0; 469 uint32 team = 0; 470 uint32 arenatype = 0; 471 uint32 israted = 0; 472 uint32 rating = 0; 473 // get the team info from the queue 474 BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 475 if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end() 476 && pitr->second.GroupInfo ) 477 { 478 team = pitr->second.GroupInfo->Team; 479 arenatype = pitr->second.GroupInfo->ArenaType; 480 israted = pitr->second.GroupInfo->IsRated; 481 rating = pitr->second.GroupInfo->ArenaTeamRating; 482 } 483 else 484 { 485 sLog.outError("Battleground: Invalid player queue info!"); 486 return; 487 } 488 WorldPacket data; 489 switch(action) 490 { 491 case 1: // port to battleground 492 if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) 493 return; // cheating? 494 // resurrect the player 495 if(!_player->isAlive()) 496 { 497 _player->ResurrectPlayer(1.0f,false); 498 _player->SpawnCorpseBones(); 499 } 500 // stop taxi flight at port 501 if(_player->isInFlight()) 502 { 503 _player->GetMotionMaster()->MovementExpired(); 504 _player->m_taxi.ClearTaxiDestinations(); 505 } 506 _player->RemoveFromGroup(); 507 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); 508 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); 509 _player->GetSession()->SendPacket(&data); 510 // remove battleground queue status from BGmgr 511 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); 512 // this is still needed here if battleground "jumping" shouldn't add deserter debuff 513 // also this required to prevent stuck at old battleground after SetBattleGroundId set to new 514 if( BattleGround *currentBg = _player->GetBattleGround() ) 515 currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); 516 517 // set the destination instance id 518 _player->SetBattleGroundId(bg->GetInstanceID()); 519 // set the destination team 520 _player->SetBGTeam(team); 521 // bg->HandleBeforeTeleportToBattleGround(_player); 522 sBattleGroundMgr.SendToBattleGround(_player, instanceId); 523 // add only in HandleMoveWorldPortAck() 524 // bg->AddPlayer(_player,team); 525 sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); 526 break; 527 case 0: // leave queue 528 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); 529 _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs 530 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); 531 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); 532 // player left queue, we should update it, maybe now his group fits in 533 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(),arenatype,israted,rating); 534 SendPacket(&data); 535 sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId); 536 break; 537 default: 538 sLog.outError("Battleground port: unknown action %u", action); 539 break; 540 } 346 541 } 347 542 } … … 384 579 if(bg) 385 580 { 386 uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID()); 581 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 582 uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); 387 583 if((bg->GetStatus() <= STATUS_IN_PROGRESS)) 388 584 { … … 392 588 for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 393 589 { 394 uint32 queue_id = _player->GetBattleGroundQueueId(i); 395 if (i == queueSlot || !queue_id) 590 uint32 queue_id = _player->GetBattleGroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong 591 uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); 592 uint8 isRated = 0; 593 if (i == queueSlot || !queue_id) // we need to get the instance ids 396 594 continue; 397 BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id); 595 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 596 if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 597 continue; 598 if(itrPlayerStatus->second.GroupInfo) 599 { 600 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; 601 isRated = itrPlayerStatus->second.GroupInfo->IsRated; 602 } 603 BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); // try this 398 604 if(bg2) 399 605 { 400 606 //in this call is small bug, this call should be filled by player's waiting time in queue 401 607 //this call nulls all timers for client : 402 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0 );608 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated); 403 609 SendPacket(&data); 404 610 } … … 411 617 for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 412 618 { 413 if(uint32 queue_id = _player->GetBattleGroundQueueId(i)) 414 { 415 if(BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id)) 416 { 417 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); 418 SendPacket(&data); 419 } 420 } 421 } 422 } 619 uint32 queue_id = _player->GetBattleGroundQueueId(i); 620 if(!queue_id) 621 continue; 622 uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); 623 uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); 624 uint8 isRated = 0; 625 BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 626 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 627 if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 628 continue; 629 if(itrPlayerStatus->second.GroupInfo) 630 { 631 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; 632 isRated = itrPlayerStatus->second.GroupInfo->IsRated; 633 } 634 if(bg && queue_id) 635 { 636 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); 637 SendPacket(&data); 638 } 639 } 640 } 641 /* else // not sure if it needed... 642 { 643 for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 644 { 645 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0); 646 SendPacket(&data); 647 } 648 }*/ 423 649 } 424 650 … … 479 705 if(_player->InBattleGround()) 480 706 return; 481 482 for(int qId = 0; qId < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qId)483 {484 if(_player->GetBattleGroundQueueId(qId) != 0)485 return;486 }487 707 488 708 uint64 guid; // arena Battlemaster guid … … 490 710 uint8 asGroup; // asGroup 491 711 uint8 isRated; // isRated 712 Group * grp; 713 492 714 recv_data >> guid >> type >> asGroup >> isRated; 493 715 … … 500 722 501 723 uint8 arenatype = 0; 724 uint32 arenaRating = 0; 502 725 503 726 switch(type) … … 517 740 } 518 741 519 if(isRated && !_player->GetArenaTeamId(type)) // player not in arena team of that size 520 { 521 _player->GetSession()->SendNotInArenaTeamPacket(arenatype); 522 return; 523 } 524 525 if(asGroup && !_player->GetGroup()) // player not in group 526 return; 527 528 // check existence 529 BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA); 530 if(!bg) 531 return; 532 533 bg->SetArenaType(arenatype); 534 bg->SetRated(isRated); 535 536 if(asGroup && _player->GetGroup()) 537 { 538 Group *grp = _player->GetGroup(); 742 //check existance 743 BattleGround* bg = NULL; 744 if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) ) 745 { 746 sLog.outError("Battleground: template bg (all arenas) not found"); 747 return; 748 } 749 750 uint8 bgTypeId = bg->GetTypeID(); 751 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); 752 753 // check queueing conditions 754 if(!asGroup) 755 { 756 // check if already in queue 757 if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) 758 //player is already in this queue 759 return; 760 // check if has free queue slots 761 if(!_player->HasFreeBattleGroundQueueId()) 762 return; 763 } 764 else 765 { 766 grp = _player->GetGroup(); 767 // no group found, error 768 if(!grp) 769 return; 770 uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type); 771 switch(err) 772 { 773 // TODO: add error-based feedback to players in all cases 774 case BG_JOIN_ERR_GROUP_TOO_MANY: 775 { 776 WorldPacket data; 777 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_ARENA_GROUP_TOO_LARGE), NULL); 778 SendPacket(&data); 779 } 780 return; 781 break; 782 case BG_JOIN_ERR_GROUP_NOT_ENOUGH: 783 { 784 WorldPacket data; 785 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_ARENA_NOT_ENOUGH_PLAYERS), NULL); 786 SendPacket(&data); 787 } 788 return; 789 break; 790 case BG_JOIN_ERR_MIXED_ARENATEAM: 791 { 792 WorldPacket data; 793 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_ARENA_YOUR_TEAM_ONLY), NULL); 794 SendPacket(&data); 795 } 796 return; 797 break; 798 case BG_JOIN_ERR_OFFLINE_MEMBER: 799 { 800 WorldPacket data; 801 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_OFFLINE_MEMBER), NULL); 802 SendPacket(&data); 803 } 804 return; 805 break; 806 case BG_JOIN_ERR_MIXED_FACTION: 807 { 808 WorldPacket data; 809 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_FACTION), NULL); 810 SendPacket(&data); 811 } 812 return; 813 break; 814 case BG_JOIN_ERR_MIXED_LEVELS: 815 { 816 WorldPacket data; 817 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MIXED_LEVELS), NULL); 818 SendPacket(&data); 819 } 820 return; 821 break; 822 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE: 823 { 824 WorldPacket data; 825 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE), NULL); 826 SendPacket(&data); 827 } 828 return; 829 break; 830 case BG_JOIN_ERR_GROUP_DESERTER: 831 { 832 WorldPacket data; 833 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_DESERTER), NULL); 834 SendPacket(&data); 835 } 836 return; 837 break; 838 case BG_JOIN_ERR_ALL_QUEUES_USED: 839 { 840 WorldPacket data; 841 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS), NULL); 842 SendPacket(&data); 843 } 844 return; 845 break; 846 // all ok, can join 847 case BG_JOIN_ERR_OK: 848 break; 849 // not the above? shouldn't happen, don't let join 850 default: 851 return; 852 break; 853 }; 854 } 855 856 uint32 ateamId = 0; 857 858 if(isRated) 859 { 860 ateamId = _player->GetArenaTeamId(type); 861 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) 862 ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); 863 if(!at) 864 { 865 _player->GetSession()->SendNotInArenaTeamPacket(arenatype); 866 return; 867 } 868 // get the team rating for queueing 869 arenaRating = at->GetRating(); 870 // the arenateam id must match for everyone in the group 871 // get the personal ratings for queueing 872 uint32 avg_pers_rating = 0; 873 for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) 874 { 875 Player *member = itr->getSource(); 876 877 // calc avg personal rating 878 avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5); 879 } 880 881 if( arenatype ) 882 avg_pers_rating /= arenatype; 883 884 // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating 885 if(avg_pers_rating + 150 < arenaRating) 886 arenaRating = avg_pers_rating; 887 } 888 889 if(asGroup) 890 { 891 GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId); 892 sLog.outDebug("Battleground: arena join as group start"); 893 if(isRated) 894 sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype); 539 895 for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) 540 896 { … … 542 898 if(!member) continue; 543 899 544 /*if (!member->CanJoinToBattleground()) 545 //player has deserter aura .. do nothing 546 */ 547 548 if (member->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) 549 //player is already in this queue 550 continue; 551 552 // add to queue 553 uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA); 554 if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 555 { 556 WorldPacket data; 557 //fill data 558 //member->GetSession()->SendPacket(data); 559 continue; 560 } 900 uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue 561 901 562 902 // store entry point coords (same as leader entry point) … … 565 905 WorldPacket data; 566 906 // send status packet (in queue) 567 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0 );907 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); 568 908 member->GetSession()->SendPacket(&data); 569 sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA);909 sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); 570 910 member->GetSession()->SendPacket(&data); 571 sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA); 572 } 911 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); 912 sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); 913 } 914 sLog.outDebug("Battleground: arena join as group end"); 915 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); 573 916 } 574 917 else 575 918 { 576 /*if (!member->CanJoinToBattleground()) 577 //player has deserter aura .. do nothing 578 */ 579 580 if (_player->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) 581 //player is already in this queue 582 return; 583 584 uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA); 585 if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) 586 { 587 WorldPacket data; 588 //fill data (player is in 3 queues already) 589 //SendPacket(data); 590 return; 591 } 919 uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); 592 920 593 921 // store entry point coords … … 596 924 WorldPacket data; 597 925 // send status packet (in queue) 598 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0 );926 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); 599 927 SendPacket(&data); 600 sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA); 928 GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating); 929 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); 930 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); 931 sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); 601 932 } 602 933 } -
trunk/src/game/BattleGroundMgr.cpp
r2 r9 31 31 #include "Policies/SingletonImp.h" 32 32 #include "MapManager.h" 33 #include "Map.h" 34 #include "MapInstanced.h" 33 35 #include "ObjectMgr.h" 34 36 #include "ProgressBar.h" 35 37 #include "World.h" 38 #include "ArenaTeam.h" 36 39 #include "Chat.h" 37 40 … … 45 48 { 46 49 //queues are empty, we don't have to call clear() 50 /* for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) 51 { 52 //m_QueuedPlayers[i].Horde = 0; 53 //m_QueuedPlayers[i].Alliance = 0; 54 //m_QueuedPlayers[i].AverageTime = 0; 55 }*/ 56 } 57 58 BattleGroundQueue::~BattleGroundQueue() 59 { 47 60 for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) 48 61 { 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 62 m_QueuedPlayers[i].clear(); 60 } 61 } 62 63 void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) 63 for(QueuedGroupsList::iterator itr = m_QueuedGroups[i].begin(); itr!= m_QueuedGroups[i].end(); ++itr) 64 { 65 delete (*itr); 66 } 67 m_QueuedGroups[i].clear(); 68 } 69 } 70 71 // initialize eligible groups from the given source matching the given specifications 72 void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList *source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType, bool IsRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) 73 { 74 // clear from prev initialization 75 clear(); 76 BattleGroundQueue::QueuedGroupsList::iterator itr, next; 77 // iterate through the source 78 for(itr = source->begin(); itr!= source->end(); itr = next) 79 { 80 next = itr; 81 ++next; 82 if( (*itr)->BgTypeId == BgTypeId && // bg type must match 83 (*itr)->ArenaType == ArenaType && // arena type must match 84 (*itr)->IsRated == IsRated && // israted must match 85 (*itr)->IsInvitedToBGInstanceGUID == 0 && // leave out already invited groups 86 (*itr)->Team == side && // match side 87 (*itr)->Players.size() <= MaxPlayers && // the group must fit in the bg 88 ( !excludeTeam || (*itr)->ArenaTeamId != excludeTeam ) && // if excludeTeam is specified, leave out those arena team ids 89 ( !IsRated || (*itr)->Players.size() == MaxPlayers ) && // if rated, then pass only if the player count is exact NEEDS TESTING! (but now this should never happen) 90 ( (*itr)->JoinTime <= DisregardTime // pass if disregard time is greater than join time 91 || (*itr)->ArenaTeamRating == 0 // pass if no rating info 92 || ( (*itr)->ArenaTeamRating >= MinRating // pass if matches the rating range 93 && (*itr)->ArenaTeamRating <= MaxRating ) ) ) 94 { 95 // the group matches the conditions 96 // insert it in order of groupsize, and join time 97 uint32 size = (*itr)->Players.size(); 98 uint32 jointime = (*itr)->JoinTime; 99 bool inserted = false; 100 101 for(std::list<GroupQueueInfo *>::iterator elig_itr = begin(); elig_itr != end(); ++elig_itr) 102 { 103 // if the next one's size is smaller, then insert 104 // also insert if the next one's size is equal, but it joined the queue later 105 if( ((*elig_itr)->Players.size()<size) || 106 ((*elig_itr)->Players.size() == size && (*elig_itr)->JoinTime > jointime) ) 107 { 108 insert(elig_itr,(*itr)); 109 inserted = true; 110 break; 111 } 112 } 113 // if not inserted -> this is the smallest group -> push_back 114 if(!inserted) 115 { 116 push_back((*itr)); 117 } 118 } 119 } 120 } 121 122 // remove group from eligible groups 123 // used when building selection pools 124 void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo * ginfo) 125 { 126 for(std::list<GroupQueueInfo *>::iterator itr = begin(); itr != end(); ++itr) 127 { 128 if((*itr)==ginfo) 129 { 130 erase(itr); 131 return; 132 } 133 } 134 } 135 136 // selection pool initialization, used to clean up from prev selection 137 void BattleGroundQueue::SelectionPool::Init() 138 { 139 SelectedGroups.clear(); 140 MaxGroup = 0; 141 PlayerCount = 0; 142 } 143 144 // get the maximal group from the selection pool 145 // used when building the pool, and have to remove the largest 146 GroupQueueInfo * BattleGroundQueue::SelectionPool::GetMaximalGroup() 147 { 148 if(SelectedGroups.empty()) 149 { 150 sLog.outError("Getting max group when selection pool is empty, this should never happen."); 151 MaxGroup = NULL; 152 return 0; 153 } 154 // actually select the max group if it's not set 155 if(MaxGroup==0 && !SelectedGroups.empty()) 156 { 157 uint32 max_size = 0; 158 for(std::list<GroupQueueInfo *>::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) 159 { 160 if(max_size<(*itr)->Players.size()) 161 { 162 MaxGroup =(*itr); 163 max_size = MaxGroup->Players.size(); 164 } 165 } 166 } 167 return MaxGroup; 168 } 169 170 // remove group info from selection pool 171 // used when building selection pools and have to remove maximal group 172 void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo *ginfo) 173 { 174 // uninitiate max group info if needed 175 if(MaxGroup == ginfo) 176 MaxGroup = 0; 177 // find what to remove 178 for(std::list<GroupQueueInfo *>::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) 179 { 180 if((*itr)==ginfo) 181 { 182 SelectedGroups.erase(itr); 183 // decrease selected players count 184 PlayerCount -= ginfo->Players.size(); 185 return; 186 } 187 } 188 } 189 190 // add group to selection 191 // used when building selection pools 192 void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo) 193 { 194 SelectedGroups.push_back(ginfo); 195 // increase selected players count 196 PlayerCount+=ginfo->Players.size(); 197 if(!MaxGroup || ginfo->Players.size() > MaxGroup->Players.size()) 198 { 199 // update max group info if needed 200 MaxGroup = ginfo; 201 } 202 } 203 204 // add group to bg queue with the given leader and bg specifications 205 GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 arenaRating, uint32 arenateamid) 206 { 207 uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel(); 208 209 // create new ginfo 210 // cannot use the method like in addplayer, because that could modify an in-queue group's stats 211 // (e.g. leader leaving queue then joining as individual again) 212 GroupQueueInfo* ginfo = new GroupQueueInfo; 213 ginfo->BgTypeId = BgTypeId; 214 ginfo->ArenaType = ArenaType; 215 ginfo->ArenaTeamId = arenateamid; 216 ginfo->IsRated = isRated; 217 ginfo->IsInvitedToBGInstanceGUID = 0; // maybe this should be modifiable by function arguments to enable selection of running instances? 218 ginfo->JoinTime = getMSTime(); 219 ginfo->Team = leader->GetTeam(); 220 221 if(sBattleGroundMgr.GetMaxRatingDifference()) // if max difference is set, then store rating info for queue 222 ginfo->ArenaTeamRating = arenaRating; 223 else 224 ginfo->ArenaTeamRating = 0; // don't if it doesn't matter 225 226 ginfo->Players.clear(); 227 228 m_QueuedGroups[queue_id].push_back(ginfo); 229 230 // return ginfo, because it is needed to add players to this group info 231 return ginfo; 232 } 233 234 void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) 64 235 { 65 236 uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); … … 68 239 PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()]; 69 240 info.InviteTime = 0; 70 info.IsInvitedToBGInstanceGUID = 0;71 241 info.LastInviteTime = 0; 72 242 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 } 243 info.GroupInfo = ginfo; 244 245 // add the pinfo to ginfo's list 246 ginfo->Players[plr->GetGUID()] = &info; 115 247 } 116 248 … … 121 253 uint32 queue_id = 0; 122 254 QueuedPlayersMap::iterator itr; 255 GroupQueueInfo * group; 256 QueuedGroupsList::iterator group_itr; 123 257 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"); 258 if(plr) 259 { 260 queue_id = plr->GetBattleGroundQueueIdFromLevel(); 261 262 itr = m_QueuedPlayers[queue_id].find(guid); 263 if(itr != m_QueuedPlayers[queue_id].end()) 264 IsSet = true; 265 } 266 267 if(!IsSet) 268 { 269 // either player is offline, or he levelled up to another queue category 270 // sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); 128 271 for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) 129 272 { … … 137 280 } 138 281 } 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); 282 283 // couldn't find the player in bg queue, return 284 if(!IsSet) 285 { 286 sLog.outError("Battleground: couldn't find player to remove."); 287 return; 288 } 289 290 group = itr->second.GroupInfo; 291 292 for(group_itr=m_QueuedGroups[queue_id].begin(); group_itr != m_QueuedGroups[queue_id].end(); ++group_itr) 293 { 294 if(group == (GroupQueueInfo*)(*group_itr)) 295 break; 296 } 297 298 // variables are set (what about leveling up when in queue????) 299 // remove player from group 300 // if only player there, remove group 301 302 // remove player queue info from group queue info 303 std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid); 304 305 if(pitr != group->Players.end()) 306 group->Players.erase(pitr); 307 308 // check for iterator correctness 309 if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end()) 310 { 311 // used when player left the queue, NOT used when porting to bg 312 if (decreaseInvitedCount) 313 { 314 // if invited to bg, and should decrease invited count, then do it 315 if(group->IsInvitedToBGInstanceGUID) 316 { 317 BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); 164 318 if (bg) 165 bg->DecreaseInvitedCount(itr->second.Team); 166 } 167 } 319 bg->DecreaseInvitedCount(group->Team); 320 if (bg && !bg->GetPlayersSize() && !bg->GetInvitedCount(ALLIANCE) && !bg->GetInvitedCount(HORDE)) 321 { 322 // no more players on battleground, set delete it 323 bg->SetDeleteThis(); 324 } 325 } 326 // update the join queue, maybe now the player's group fits in a queue! 327 // not yet implemented (should store bgTypeId in group queue info?) 328 } 329 // remove player queue info 168 330 m_QueuedPlayers[queue_id].erase(itr); 331 // remove group queue info if needed 332 if(group->Players.empty()) 333 { 334 m_QueuedGroups[queue_id].erase(group_itr); 335 delete group; 336 } 337 // NEEDS TESTING! 338 // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too 339 // don't remove recursively if already invited to bg! 340 else if(!group->IsInvitedToBGInstanceGUID && decreaseInvitedCount && group->IsRated) 341 { 342 // remove next player, this is recursive 343 // first send removal information 344 if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) 345 { 346 BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); 347 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(group->BgTypeId,group->ArenaType); 348 uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); 349 plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs 350 WorldPacket data; 351 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); 352 plr2->GetSession()->SendPacket(&data); 353 } 354 // then actually delete, this may delete the group as well! 355 RemovePlayer(group->Players.begin()->first,decreaseInvitedCount); 356 } 357 } 358 } 359 360 bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side) 361 { 362 // set side if needed 363 if(side) 364 ginfo->Team = side; 365 366 if(!ginfo->IsInvitedToBGInstanceGUID) 367 { 368 // not yet invited 369 // set invitation 370 ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); 371 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 372 // loop through the players 373 for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) 374 { 375 // set status 376 itr->second->InviteTime = getMSTime(); 377 itr->second->LastInviteTime = getMSTime(); 378 379 // get the player 380 Player* plr = objmgr.GetPlayer(itr->first); 381 // if offline, skip him 382 if(!plr) 383 continue; 384 385 // invite the player 386 sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(),ginfo->Team); 387 388 WorldPacket data; 389 390 uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 391 392 sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID()); 393 394 // send status packet 395 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); 396 plr->GetSession()->SendPacket(&data); 397 } 398 return true; 399 } 400 401 return false; 402 } 403 404 // this function is responsible for the selection of queued groups when trying to create new battlegrounds 405 bool BattleGroundQueue::BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType, bool isRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) 406 { 407 uint32 side; 408 switch(mode) 409 { 410 case NORMAL_ALLIANCE: 411 case ONESIDE_ALLIANCE_TEAM1: 412 case ONESIDE_ALLIANCE_TEAM2: 413 side = ALLIANCE; 414 break; 415 case NORMAL_HORDE: 416 case ONESIDE_HORDE_TEAM1: 417 case ONESIDE_HORDE_TEAM2: 418 side = HORDE; 419 break; 420 default: 421 //unknown mode, return false 422 sLog.outDebug("Battleground: unknown selection pool build mode, returning..."); 423 return false; 424 break; 425 } 426 427 // inititate the groups eligible to create the bg 428 m_EligibleGroups.Init(&(m_QueuedGroups[queue_id]), bgTypeId, side, MaxPlayers, ArenaType, isRated, MinRating, MaxRating, DisregardTime, excludeTeam); 429 // init the selected groups (clear) 430 m_SelectionPools[mode].Init(); 431 while(!(m_EligibleGroups.empty())) 432 { 433 sLog.outDebug("m_EligibleGroups is not empty, continue building selection pool"); 434 // in decreasing group size, add groups to join if they fit in the MaxPlayersPerTeam players 435 for(EligibleGroups::iterator itr= m_EligibleGroups.begin(); itr!=m_EligibleGroups.end(); ++itr) 436 { 437 // get the maximal not yet checked group 438 GroupQueueInfo * MaxGroup = (*itr); 439 // if it fits in the maxplayer size, add it 440 if( (m_SelectionPools[mode].GetPlayerCount() + MaxGroup->Players.size()) <= MaxPlayers ) 441 { 442 m_SelectionPools[mode].AddGroup(MaxGroup); 443 } 444 } 445 if(m_SelectionPools[mode].GetPlayerCount()>=MinPlayers) 446 { 447 // the selection pool is set, return 448 sLog.outDebug("pool build succeeded, return true"); 449 return true; 450 } 451 // if the selection pool's not set, then remove the group with the highest player count, and try again with the rest. 452 GroupQueueInfo * MaxGroup = m_SelectionPools[mode].GetMaximalGroup(); 453 m_EligibleGroups.RemoveGroup(MaxGroup); 454 m_SelectionPools[mode].RemoveGroup(MaxGroup); 455 } 456 // failed to build a selection pool matching the given values 457 return false; 458 } 459 460 // used to remove the Enter Battle window if the battle has already, but someone still has it 461 // (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event 462 void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) 463 { 464 uint32 queue_id = bg->GetQueueType(); 465 uint32 bgInstanceId = bg->GetInstanceID(); 466 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 467 QueuedGroupsList::iterator itr, next; 468 for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next) 469 { 470 // must do this way, because the groupinfo will be deleted when all playerinfos are removed 471 GroupQueueInfo * ginfo = (*itr); 472 next = itr; 473 ++next; 474 // if group was invited to this bg instance, then remove all references 475 if(ginfo->IsInvitedToBGInstanceGUID == bgInstanceId) 476 { 477 // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop 478 uint32 to_remove = ginfo->Players.size(); 479 uint32 team = ginfo->Team; 480 for(int i = 0; i < to_remove; ++i) 481 { 482 // always remove the first one in the group 483 std::map<uint64, PlayerQueueInfo * >::iterator itr2 = ginfo->Players.begin(); 484 if(itr2 == ginfo->Players.end()) 485 { 486 sLog.outError("Empty Players in ginfo, this should never happen!"); 487 return; 488 } 489 490 // get the player 491 Player * plr = objmgr.GetPlayer(itr2->first); 492 if(!plr) 493 { 494 sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen."); 495 continue; 496 } 497 498 // get the queueslot 499 uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 500 if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 501 { 502 plr->RemoveBattleGroundQueueId(bgQueueTypeId); 503 // remove player from queue, this might delete the ginfo as well! don't use that pointer after this! 504 RemovePlayer(itr2->first, true); 505 // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups 506 // but updateing the queue can't hurt 507 Update(bgQueueTypeId, bg->GetQueueType()); 508 // send info to client 509 WorldPacket data; 510 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); 511 plr->GetSession()->SendPacket(&data); 512 } 513 } 514 } 169 515 } 170 516 } 171 517 172 518 /* 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 519 this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue 520 it must be called after fully adding the members of a group to ensure group joining 521 should be called after removeplayer functions in some cases 175 522 */ 176 void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id )523 void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating) 177 524 { 178 525 if (queue_id >= MAX_BATTLEGROUND_QUEUES) … … 184 531 185 532 //if no players in queue ... do nothing 186 if (this->m_Queued Players[queue_id].Alliance == 0 && this->m_QueuedPlayers[queue_id].Horde== 0)533 if (this->m_QueuedGroups[queue_id].size() == 0) 187 534 return; 188 535 536 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); 537 189 538 //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 { 539 BGFreeSlotQueueType::iterator itr, next; 540 for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) 541 { 542 next = itr; 543 ++next; 192 544 // battleground is running, so if: 193 545 // DO NOT allow queue manager to invite new player to running arena 194 if ((*itr)->isBattleGround() && (*itr)->Get QueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE)546 if ((*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) 195 547 { 196 548 //we must check both teams … … 198 550 // and iterator is invalid 199 551 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();) 552 for(QueuedGroupsList::iterator itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); ++itr) 553 { 554 // did the group join for this bg type? 555 if((*itr)->BgTypeId != bgTypeId) 556 continue; 557 // if so, check if fits in 558 if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size()) 204 559 { 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 } 560 // if group fits in, invite it 561 InviteGroupToBG((*itr),bg,(*itr)->Team); 258 562 } 259 563 } 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 template270 (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)564 565 if (!bg->HasFreeSlots()) 566 { 567 //remove BG from BGFreeSlotQueue 568 bg->RemoveFromBGFreeSlotQueue(); 569 } 570 } 571 } 572 573 // finished iterating through the bgs with free slots, maybe we need to create a new bg 574 575 BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 576 if(!bg_template) 577 { 578 sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId); 275 579 return; 276 if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam()) 277 { 580 } 581 582 // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!) 583 uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam(); 584 uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam(); 585 if(bg_template->isArena()) 586 { 587 if(sBattleGroundMgr.isArenaTesting()) 588 { 589 MaxPlayersPerTeam = 1; 590 MinPlayersPerTeam = 1; 591 } 592 else 593 { 594 switch(arenatype) 595 { 596 case ARENA_TYPE_2v2: 597 MaxPlayersPerTeam = 2; 598 MinPlayersPerTeam = 2; 599 break; 600 case ARENA_TYPE_3v3: 601 MaxPlayersPerTeam = 3; 602 MinPlayersPerTeam = 3; 603 break; 604 case ARENA_TYPE_5v5: 605 MaxPlayersPerTeam = 5; 606 MinPlayersPerTeam = 5; 607 break; 608 } 609 } 610 } 611 612 // found out the minimum and maximum ratings the newly added team should battle against 613 // arenaRating is the rating of the latest joined team 614 uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference(); 615 // if no rating is specified, set maxrating to 0 616 uint32 arenaMaxRating = (arenaRating == 0)? 0 : arenaRating + sBattleGroundMgr.GetMaxRatingDifference(); 617 uint32 discardTime = 0; 618 // if max rating difference is set and the time past since server startup is greater than the rating discard time 619 // (after what time the ratings aren't taken into account when making teams) then 620 // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account 621 // else leave the discard time on 0, this way all ratings will be discarded 622 if(sBattleGroundMgr.GetMaxRatingDifference() && getMSTime() >= sBattleGroundMgr.GetRatingDiscardTimer()) 623 discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer(); 624 625 // try to build the selection pools 626 bool bAllyOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_ALLIANCE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 627 if(bAllyOK) 628 sLog.outDebug("Battleground: ally pool succesfully build"); 629 else 630 sLog.outDebug("Battleground: ally pool wasn't created"); 631 bool bHordeOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_HORDE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 632 if(bHordeOK) 633 sLog.outDebug("Battleground: horde pool succesfully built"); 634 else 635 sLog.outDebug("Battleground: horde pool wasn't created"); 636 637 // if selection pools are ready, create the new bg 638 if (bAllyOK && bHordeOK) 639 { 640 BattleGround * bg2 = 0; 641 // special handling for arenas 642 if(bg_template->isArena()) 643 { 644 // Find a random arena, that can be created 645 uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; 646 uint32 arena_num = urand(0,2); 647 if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && 648 !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && 649 !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) 650 { 651 sLog.outError("Battleground: couldn't create arena"); 652 return; 653 } 654 655 // set the MaxPlayersPerTeam values based on arenatype 656 // setting the min player values isn't needed, since we won't be using that value later on. 657 if(sBattleGroundMgr.isArenaTesting()) 658 { 659 bg2->SetMaxPlayersPerTeam(1); 660 bg2->SetMaxPlayers(2); 661 } 662 else 663 { 664 switch(arenatype) 665 { 666 case ARENA_TYPE_2v2: 667 bg2->SetMaxPlayersPerTeam(2); 668 bg2->SetMaxPlayers(4); 669 break; 670 case ARENA_TYPE_3v3: 671 bg2->SetMaxPlayersPerTeam(3); 672 bg2->SetMaxPlayers(6); 673 break; 674 case ARENA_TYPE_5v5: 675 bg2->SetMaxPlayersPerTeam(5); 676 bg2->SetMaxPlayers(10); 677 break; 678 default: 679 break; 680 } 681 } 682 } 683 else 684 { 685 // create new battleground 686 bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId); 687 } 688 689 if(!bg2) 690 { 691 sLog.outError("Battleground: couldn't create bg %u",bgTypeId); 692 return; 693 } 694 695 // start the joining of the bg 278 696 bg2->SetStatus(STATUS_WAIT_JOIN); 279 697 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) 698 // initialize arena / rating info 699 bg2->SetArenaType(arenatype); 700 // set rating 701 bg2->SetRated(isRated); 702 703 std::list<GroupQueueInfo* >::iterator itr; 704 705 // invite groups from horde selection pool 706 for(itr = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_HORDE].SelectedGroups.end(); ++itr) 707 { 708 InviteGroupToBG((*itr),bg2,HORDE); 709 } 710 711 // invite groups from ally selection pools 712 for(itr = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.end(); ++itr) 713 { 714 InviteGroupToBG((*itr),bg2,ALLIANCE); 715 } 716 717 // start the battleground 718 bg2->StartBattleGround(); 719 } 720 721 // there weren't enough players for a "normal" match 722 // if arena, enable horde versus horde or alliance versus alliance teams here 723 724 else if(bg_template->isArena()) 725 { 726 bool bOneSideHordeTeam1 = false, bOneSideHordeTeam2 = false; 727 bool bOneSideAllyTeam1 = false, bOneSideAllyTeam2 = false; 728 bOneSideHordeTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 729 if(bOneSideHordeTeam1) 730 { 731 // one team has been selected, find out if other can be selected too 732 std::list<GroupQueueInfo* >::iterator itr; 733 // temporarily change the team side to enable building the next pool excluding the already selected groups 734 for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) 735 (*itr)->Team=ALLIANCE; 736 737 bOneSideHordeTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime, (*(m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); 738 739 // change back the team to horde 740 for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) 741 (*itr)->Team=HORDE; 742 743 if(!bOneSideHordeTeam2) 744 bOneSideHordeTeam1 = false; 745 } 746 if(!bOneSideHordeTeam1) 747 { 748 // check for one sided ally 749 bOneSideAllyTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); 750 if(bOneSideAllyTeam1) 751 { 752 // one team has been selected, find out if other can be selected too 753 std::list<GroupQueueInfo* >::iterator itr; 754 // temporarily change the team side to enable building the next pool excluding the already selected groups 755 for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) 756 (*itr)->Team=HORDE; 757 758 bOneSideAllyTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime,(*(m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); 759 760 // change back the team to ally 761 for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) 762 (*itr)->Team=ALLIANCE; 763 } 764 765 if(!bOneSideAllyTeam2) 766 bOneSideAllyTeam1 = false; 767 } 768 // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!! 769 if( (bOneSideHordeTeam1 && bOneSideHordeTeam2) || 770 (bOneSideAllyTeam1 && bOneSideAllyTeam2) ) 771 { 772 // which side has enough players? 773 uint32 side = 0; 774 SelectionPoolBuildMode mode1, mode2; 775 // find out what pools are we using 776 if(bOneSideAllyTeam1 && bOneSideAllyTeam2) 777 { 778 side = ALLIANCE; 779 mode1 = ONESIDE_ALLIANCE_TEAM1; 780 mode2 = ONESIDE_ALLIANCE_TEAM2; 781 } 782 else 783 { 784 side = HORDE; 785 mode1 = ONESIDE_HORDE_TEAM1; 786 mode2 = ONESIDE_HORDE_TEAM2; 787 } 788 789 // create random arena 790 uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; 791 uint32 arena_num = urand(0,2); 792 BattleGround* bg2 = NULL; 793 if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && 794 !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && 795 !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) 796 { 797 sLog.outError("Could not create arena."); 798 return; 799 } 800 801 sLog.outDebug("Battleground: One-faction arena created."); 802 // init stats 803 if(sBattleGroundMgr.isArenaTesting()) 804 { 805 bg2->SetMaxPlayersPerTeam(1); 806 bg2->SetMaxPlayers(2); 807 } 808 else 809 { 810 switch(arenatype) 315 811 { 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); 812 case ARENA_TYPE_2v2: 813 bg2->SetMaxPlayersPerTeam(2); 814 bg2->SetMaxPlayers(4); 815 break; 816 case ARENA_TYPE_3v3: 817 bg2->SetMaxPlayersPerTeam(3); 818 bg2->SetMaxPlayers(6); 819 break; 820 case ARENA_TYPE_5v5: 821 bg2->SetMaxPlayersPerTeam(5); 822 bg2->SetMaxPlayers(10); 823 break; 824 default: 825 break; 331 826 } 332 827 } 828 829 bg2->SetRated(isRated); 830 831 // assigned team of the other group 832 uint32 other_side; 833 if(side == ALLIANCE) 834 other_side = HORDE; 333 835 else 334 ++itr2; 335 } 336 bg2->StartBattleGround(); 836 other_side = ALLIANCE; 837 838 // start the joining of the bg 839 bg2->SetStatus(STATUS_WAIT_JOIN); 840 bg2->SetQueueType(queue_id); 841 // initialize arena / rating info 842 bg2->SetArenaType(arenatype); 843 844 std::list<GroupQueueInfo* >::iterator itr; 845 846 // invite players from the first group as horde players (actually green team) 847 for(itr = m_SelectionPools[mode1].SelectedGroups.begin(); itr != m_SelectionPools[mode1].SelectedGroups.end(); ++itr) 848 { 849 InviteGroupToBG((*itr),bg2,HORDE); 850 } 851 852 // invite players from the second group as ally players (actually gold team) 853 for(itr = m_SelectionPools[mode2].SelectedGroups.begin(); itr != m_SelectionPools[mode2].SelectedGroups.end(); ++itr) 854 { 855 InviteGroupToBG((*itr),bg2,ALLIANCE); 856 } 857 858 bg2->StartBattleGround(); 859 } 337 860 } 338 861 } … … 362 885 if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 363 886 { 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); 887 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 888 uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 889 if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 890 { 891 // 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 892 BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; 893 BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); 894 if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) 895 { 896 WorldPacket data; 897 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); 898 plr->GetSession()->SendPacket(&data); 899 } 372 900 } 373 901 } … … 397 925 return true; 398 926 399 uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); 400 if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue (base at player data 927 sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); 928 929 uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); 930 uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); 931 if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 401 932 { 402 933 // 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 934 BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].find(m_PlayerGuid); 935 if (qMapItr != sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) 936 { 937 plr->RemoveBattleGroundQueueId(bgQueueTypeId); 938 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); 939 sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgQueueTypeId, bg->GetQueueType()); 411 940 WorldPacket data; 412 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0);941 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); 413 942 plr->GetSession()->SendPacket(&data); 414 943 } 415 944 } 945 else 946 sLog.outDebug("Battleground: Player was already removed from queue"); 416 947 417 948 //event will be deleted … … 432 963 { 433 964 m_BattleGrounds.clear(); 965 m_AutoDistributePoints = (bool)sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS); 966 m_MaxRatingDifference = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); 967 m_RatingDiscardTimer = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); 968 m_PrematureFinishTimer = sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); 969 m_NextRatingDiscardUpdate = m_RatingDiscardTimer; 970 m_AutoDistributionTimeChecker = 0; 971 m_ArenaTesting = false; 434 972 } 435 973 436 974 BattleGroundMgr::~BattleGroundMgr() 437 975 { 438 for(std::map<uint32, BattleGround*>::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) 439 delete itr->second; 976 BattleGroundSet::iterator itr, next; 977 for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) 978 { 979 next = itr; 980 ++next; 981 BattleGround * bg = itr->second; 982 m_BattleGrounds.erase(itr); 983 delete bg; 984 } 440 985 m_BattleGrounds.clear(); 441 986 } 442 987 988 // used to update running battlegrounds, and delete finished ones 443 989 void BattleGroundMgr::Update(time_t diff) 444 990 { 445 for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) 991 BattleGroundSet::iterator itr, next; 992 for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) 993 { 994 next = itr; 995 ++next; 446 996 itr->second->Update(diff); 447 } 448 449 void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2) 997 // use the SetDeleteThis variable 998 // direct deletion caused crashes 999 if(itr->second->m_SetDeleteThis) 1000 { 1001 BattleGround * bg = itr->second; 1002 m_BattleGrounds.erase(itr); 1003 delete bg; 1004 } 1005 } 1006 // if rating difference counts, maybe force-update queues 1007 if(m_MaxRatingDifference) 1008 { 1009 // it's time to force update 1010 if(m_NextRatingDiscardUpdate < diff) 1011 { 1012 // forced update for level 70 rated arenas 1013 m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0); 1014 m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0); 1015 m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0); 1016 m_NextRatingDiscardUpdate = m_RatingDiscardTimer; 1017 } 1018 else 1019 m_NextRatingDiscardUpdate -= diff; 1020 } 1021 if(m_AutoDistributePoints) 1022 { 1023 if(m_AutoDistributionTimeChecker < diff) 1024 { 1025 if(time(NULL) > m_NextAutoDistributionTime) 1026 { 1027 DistributeArenaPoints(); 1028 m_NextAutoDistributionTime = time(NULL) + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); 1029 CharacterDatabase.PExecute("UPDATE saved_variables SET NextArenaPointDistributionTime = FROM_UNIXTIME('"I64FMTD"')",(uint64)m_NextAutoDistributionTime); 1030 } 1031 m_AutoDistributionTimeChecker = 600000; // check 10 minutes 1032 } 1033 else 1034 m_AutoDistributionTimeChecker -= diff; 1035 } 1036 } 1037 1038 void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype, uint8 israted) 450 1039 { 451 1040 // we can be in 3 queues in same time... … … 461 1050 *data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time 462 1051 // uint64 in client 463 *data << uint64( uint64( bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) );1052 *data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); 464 1053 *data << uint32(0); // unknown 465 1054 // alliance/horde for BG and skirmish/rated for Arenas 466 *data << uint8(bg->isArena() ? (bg->isRated() ? 1 : 0) : bg->GetTeamIndexByTeamId(team)); 1055 *data << uint8(bg->isArena() ? ( israted ? israted : bg->isRated() ) : bg->GetTeamIndexByTeamId(team)); 1056 /* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!! 1057 switch(bg->GetTypeID()) // value depends on bg id 1058 { 1059 case BATTLEGROUND_AV: 1060 *data << uint8(1); 1061 break; 1062 case BATTLEGROUND_WS: 1063 *data << uint8(2); 1064 break; 1065 case BATTLEGROUND_AB: 1066 *data << uint8(3); 1067 break; 1068 case BATTLEGROUND_NA: 1069 *data << uint8(4); 1070 break; 1071 case BATTLEGROUND_BE: 1072 *data << uint8(5); 1073 break; 1074 case BATTLEGROUND_AA: 1075 *data << uint8(6); 1076 break; 1077 case BATTLEGROUND_EY: 1078 *data << uint8(7); 1079 break; 1080 case BATTLEGROUND_RL: 1081 *data << uint8(8); 1082 break; 1083 default: // unknown 1084 *data << uint8(0); 1085 break; 1086 } 1087 1088 if(bg->isArena() && (StatusID == STATUS_WAIT_QUEUE)) 1089 *data << uint32(BATTLEGROUND_AA); // all arenas I don't think so. 1090 else 1091 *data << uint32(bg->GetTypeID()); // BG id from DBC 1092 1093 *data << uint16(0x1F90); // unk value 8080 1094 *data << uint32(bg->GetInstanceID()); // instance id 1095 1096 if(bg->isBattleGround()) 1097 *data << uint8(bg->GetTeamIndexByTeamId(team)); // team 1098 else 1099 *data << uint8(israted?israted:bg->isRated()); // is rated battle 1100 */ 467 1101 *data << uint32(StatusID); // status 468 1102 switch(StatusID) … … 494 1128 data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize())); 495 1129 *data << uint8(type); // seems to be type (battleground=0/arena=1) 1130 496 1131 if(type) // arena 497 1132 { 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 1133 // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H 1134 for(int i = 1; i >= 0; --i) 1135 { 1136 *data << uint32(3000-bg->m_ArenaTeamRatingChanges[i]); // rating change: showed value - 3000 1137 *data << uint32(3999); // huge thanks for TOM_RUS for this! 1138 sLog.outDebug("rating change: %d", bg->m_ArenaTeamRatingChanges[i]); 1139 } 1140 for(int i = 1; i >= 0; --i) 1141 { 1142 uint32 at_id = bg->m_ArenaTeamIds[i]; 1143 ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 1144 if(at) 1145 *data << at->GetName(); 1146 else//*/ 1147 *data << (uint8)0; 503 1148 } 504 1149 } … … 520 1165 *data << (uint64)itr->first; 521 1166 *data << (int32)itr->second->KillingBlows; 522 if(type) 523 { 524 // this value is team (green/gold)? 1167 Player *plr = objmgr.GetPlayer(itr->first); 1168 uint32 team = bg->GetPlayerTeam(itr->first); 1169 if(!team && plr) team = plr->GetTeam(); 1170 if(type == 0) 1171 { 1172 *data << (int32)itr->second->HonorableKills; 1173 *data << (int32)itr->second->Deaths; 1174 *data << (int32)(itr->second->BonusHonor); 1175 } 1176 else 1177 { 525 1178 // that part probably wrong 526 Player *plr = objmgr.GetPlayer(itr->first);527 1179 if(plr) 528 1180 { 529 if( plr->GetTeam()== HORDE)1181 if(team == HORDE) 530 1182 *data << uint8(0); 531 else if(plr->GetTeam() == ALLIANCE) 1183 else if(team == ALLIANCE) 1184 { 532 1185 *data << uint8(1); 1186 } 533 1187 else 534 1188 *data << uint8(0); … … 537 1191 *data << uint8(0); 538 1192 } 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 1193 *data << (int32)itr->second->DamageDone; // damage done 1194 *data << (int32)itr->second->HealingDone; // healing done 1195 switch(bg->GetTypeID()) // battleground specific things 548 1196 { 549 1197 case BATTLEGROUND_AV: … … 623 1271 } 624 1272 625 void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID )1273 void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team) 626 1274 { 627 1275 // set invited player counters: … … 629 1277 if(!bg) 630 1278 return; 631 632 bg->IncreaseInvitedCount(plr->GetTeam()); 633 plr->SetInviteForBattleGroundType(bg->GetTypeID()); 1279 bg->IncreaseInvitedCount(team); 1280 1281 plr->SetInviteForBattleGroundQueueType(BGQueueTypeId(bg->GetTypeID(),bg->GetArenaType()), bgInstanceGUID); 1282 1283 // set the arena teams for rated matches 1284 if(bg->isArena() && bg->isRated()) 1285 { 1286 switch(bg->GetArenaType()) 1287 { 1288 case ARENA_TYPE_2v2: 1289 bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(0)); 1290 break; 1291 case ARENA_TYPE_3v3: 1292 bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(1)); 1293 break; 1294 case ARENA_TYPE_5v5: 1295 bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(2)); 1296 break; 1297 default: 1298 break; 1299 } 1300 } 1301 634 1302 // create invite events: 635 1303 //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 1304 BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); 637 1305 plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2)); 638 BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam());1306 BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team); 639 1307 plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); 640 1308 } 641 1309 1310 BattleGround * BattleGroundMgr::GetBattleGroundTemplate(uint32 bgTypeId) 1311 { 1312 return BGFreeSlotQueue[bgTypeId].empty() ? NULL : BGFreeSlotQueue[bgTypeId].back(); 1313 } 1314 1315 // create a new battleground that will really be used to play 1316 BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId) 1317 { 1318 BattleGround *bg = NULL; 1319 1320 // get the template BG 1321 BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId); 1322 1323 if(!bg_template) 1324 { 1325 sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId); 1326 return 0; 1327 } 1328 1329 // create a copy of the BG template 1330 switch(bgTypeId) 1331 { 1332 case BATTLEGROUND_AV: 1333 bg = new BattleGroundAV(*(BattleGroundAV*)bg_template); 1334 break; 1335 case BATTLEGROUND_WS: 1336 bg = new BattleGroundWS(*(BattleGroundWS*)bg_template); 1337 break; 1338 case BATTLEGROUND_AB: 1339 bg = new BattleGroundAB(*(BattleGroundAB*)bg_template); 1340 break; 1341 case BATTLEGROUND_NA: 1342 bg = new BattleGroundNA(*(BattleGroundNA*)bg_template); 1343 break; 1344 case BATTLEGROUND_BE: 1345 bg = new BattleGroundBE(*(BattleGroundBE*)bg_template); 1346 break; 1347 case BATTLEGROUND_AA: 1348 bg = new BattleGroundAA(*(BattleGroundAA*)bg_template); 1349 break; 1350 case BATTLEGROUND_EY: 1351 bg = new BattleGroundEY(*(BattleGroundEY*)bg_template); 1352 break; 1353 case BATTLEGROUND_RL: 1354 bg = new BattleGroundRL(*(BattleGroundRL*)bg_template); 1355 break; 1356 default: 1357 //bg = new BattleGround; 1358 return 0; 1359 break; // placeholder for non implemented BG 1360 } 1361 1362 // generate a new instance id 1363 bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id 1364 1365 // reset the new bg (set status to status_wait_queue from status_none) 1366 bg->Reset(); 1367 1368 /* will be setup in BG::Update() when the first player is ported in 1369 if(!(bg->SetupBattleGround())) 1370 { 1371 sLog.outError("BattleGround: CreateNewBattleGround: SetupBattleGround failed for bg %u", bgTypeId); 1372 delete bg; 1373 return 0; 1374 } 1375 */ 1376 1377 // add BG to free slot queue 1378 bg->AddToBGFreeSlotQueue(); 1379 1380 // add bg to update list 1381 AddBattleGround(bg->GetInstanceID(), bg); 1382 1383 return bg; 1384 } 1385 1386 // used to create the BG templates 642 1387 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 1388 { … … 659 1404 660 1405 bg->SetMapId(MapID); 1406 661 1407 bg->Reset(); 662 if(!bg->SetupBattleGround())663 {664 delete bg;665 return 0;666 }667 1408 668 1409 BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId); … … 674 1415 675 1416 bg->SetTypeID(bgTypeId); 676 bg->SetInstanceID( bgTypeId); // temporary1417 bg->SetInstanceID(0); // template bg, instance id is 0 677 1418 bg->SetMinPlayersPerTeam(MinPlayersPerTeam); 678 1419 bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam); … … 683 1424 bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); 684 1425 bg->SetLevelRange(LevelMin, LevelMax); 685 //add BaggleGround instance to FreeSlotQueue 1426 1427 //add BattleGround instance to FreeSlotQueue (.back() will return the template!) 686 1428 bg->AddToBGFreeSlotQueue(); 687 1429 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(); 1430 // do NOT add to update list, since this is a template battleground! 1431 1432 // return some not-null value, bgTypeId is good enough for me 1433 return bgTypeId; 691 1434 } 692 1435 … … 808 1551 } 809 1552 1553 void BattleGroundMgr::InitAutomaticArenaPointDistribution() 1554 { 1555 if(m_AutoDistributePoints) 1556 { 1557 sLog.outDebug("Initializing Automatic Arena Point Distribution"); 1558 QueryResult * result = CharacterDatabase.Query("SELECT UNIX_TIMESTAMP(NextArenaPointDistributionTime) FROM saved_variables"); 1559 if(!result) 1560 { 1561 sLog.outDebug("Battleground: Next arena point distribution time not found in SavedVariables, reseting it now."); 1562 m_NextAutoDistributionTime = time(NULL) + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); 1563 CharacterDatabase.PExecute("INSERT INTO saved_variables (NextArenaPointDistributionTime) VALUES ( FROM_UNIXTIME('"I64FMTD"') )",(uint64)m_NextAutoDistributionTime); 1564 } 1565 else 1566 { 1567 m_NextAutoDistributionTime = (*result)[0].GetUInt64(); 1568 delete result; 1569 } 1570 sLog.outDebug("Automatic Arena Point Distribution initialized."); 1571 } 1572 } 1573 1574 void BattleGroundMgr::DistributeArenaPoints() 1575 { 1576 // used to distribute arena points based on last week's stats 1577 1578 CharacterDatabase.BeginTransaction(); 1579 // direct execute, because of the later GetUInt32ValueFromDB() calls 1580 // 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1581 CharacterDatabase.DirectPExecute("UPDATE characters b, arena_team_member a SET b.data = CONCAT( SUBSTRING_INDEX(b.data, ' ', '%u'),' ', CAST( IF ( ((CAST( SUBSTRING( b.data FROM (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) + 2) FOR (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - 1) ) AS UNSIGNED) + (SELECT MAX(c.points_to_add) FROM arena_team_member c WHERE c.guid = b.guid GROUP BY c.guid) ) < '%u'), CAST(SUBSTRING(b.data FROM (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) + 2) FOR (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) - 1) ) AS UNSIGNED) + (SELECT MAX(d.points_to_add) FROM arena_team_member d WHERE d.guid = b.guid GROUP BY d.guid), '%u') AS CHAR),' ',SUBSTRING(b.data FROM (CHAR_LENGTH(SUBSTRING_INDEX(b.data,' ','%u')) + 2))) WHERE b.guid = a.guid",PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY+1, PLAYER_FIELD_ARENA_CURRENCY, sWorld.getConfig(CONFIG_MAX_ARENA_POINTS),PLAYER_FIELD_ARENA_CURRENCY, PLAYER_FIELD_ARENA_CURRENCY+1, PLAYER_FIELD_ARENA_CURRENCY, sWorld.getConfig(CONFIG_MAX_ARENA_POINTS), PLAYER_FIELD_ARENA_CURRENCY+1); 1582 for(int i=0; i<3; ++i) 1583 { 1584 // reset weekly played matches 1585 uint32 position = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * i + 2; 1586 CharacterDatabase.DirectPExecute("UPDATE characters SET data = CONCAT( SUBSTRING_INDEX(data,' ','%u'),' ','0',' ',SUBSTRING(data FROM (CHAR_LENGTH(SUBSTRING_INDEX(data,' ','%u')) + 2)))",position, position + 1); 1587 } 1588 CharacterDatabase.DirectExecute("UPDATE arena_team_member SET points_to_add = '0', played_week = '0', wons_week = '0'"); 1589 CharacterDatabase.DirectExecute("UPDATE arena_team_stats SET games = '0', wins = '0'"); 1590 CharacterDatabase.CommitTransaction(); 1591 1592 QueryResult *result = CharacterDatabase.PQuery("SELECT guid, data FROM characters WHERE online = '1'"); 1593 if( result ) 1594 { 1595 do 1596 { 1597 Field *fields = result->Fetch(); 1598 1599 uint32 guid = fields[0].GetUInt32(); 1600 if(Player * pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER))) 1601 { 1602 Tokens data = StrSplit(fields[1].GetCppString(), " "); 1603 // update arena currency 1604 pl->SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_ARENA_CURRENCY)); 1605 // reset played this week count for all teams 1606 for(int i= 0; i < 3; ++i) 1607 pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * i + 2, 0); 1608 } 1609 1610 } while (result->NextRow()); 1611 1612 delete result; 1613 } 1614 1615 for(ObjectMgr::ArenaTeamSet::iterator titr = objmgr.GetArenaTeamSetBegin(); titr != objmgr.GetArenaTeamSetEnd(); ++titr) 1616 { 1617 if(ArenaTeam * at = (*titr)) 1618 { 1619 at->FinishWeek(); // set played this week etc values to 0 in memory, too 1620 // at->SaveToDB(); // no need, the modified values are already saved above 1621 at->NotifyStatsChanged(); // notify the players of the changes 1622 } 1623 } 1624 } 1625 810 1626 void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) 811 1627 { … … 843 1659 } 844 1660 845 void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId)846 { 847 BattleGround *bg = GetBattleGround( bgTypeId);1661 void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId) 1662 { 1663 BattleGround *bg = GetBattleGround(instanceId); 848 1664 if(bg) 849 1665 { 850 1666 uint32 mapid = bg->GetMapId(); 851 1667 float x, y, z, O; 852 bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O); 1668 uint32 team = pl->GetBGTeam(); 1669 if(team==0) 1670 team = pl->GetTeam(); 1671 bg->GetTeamStartLoc(team, x, y, z, O); 853 1672 854 1673 sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O); 855 1674 pl->TeleportTo(mapid, x, y, z, O); 1675 } 1676 else 1677 { 1678 sLog.outError("player %u trying to port to non-existent bg instance %u",pl->GetGUIDLow(), instanceId); 856 1679 } 857 1680 } … … 866 1689 pl->GetSession()->SendPacket(&data); 867 1690 } 1691 1692 void BattleGroundMgr::RemoveBattleGround(uint32 instanceID) 1693 { 1694 BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID); 1695 if(itr!=m_BattleGrounds.end()) 1696 m_BattleGrounds.erase(itr); 1697 } 1698 1699 bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const 1700 { 1701 return ( bgTypeId == BATTLEGROUND_AA || 1702 bgTypeId == BATTLEGROUND_BE || 1703 bgTypeId == BATTLEGROUND_NA || 1704 bgTypeId == BATTLEGROUND_RL ); 1705 } 1706 1707 bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const 1708 { 1709 return !IsArenaType(bgTypeId); 1710 } 1711 1712 uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const 1713 { 1714 switch(bgTypeId) 1715 { 1716 case BATTLEGROUND_WS: 1717 return BATTLEGROUND_QUEUE_WS; 1718 case BATTLEGROUND_AB: 1719 return BATTLEGROUND_QUEUE_AB; 1720 case BATTLEGROUND_AV: 1721 return BATTLEGROUND_QUEUE_AV; 1722 case BATTLEGROUND_EY: 1723 return BATTLEGROUND_QUEUE_EY; 1724 case BATTLEGROUND_AA: 1725 case BATTLEGROUND_NA: 1726 case BATTLEGROUND_RL: 1727 case BATTLEGROUND_BE: 1728 switch(arenaType) 1729 { 1730 case ARENA_TYPE_2v2: 1731 return BATTLEGROUND_QUEUE_2v2; 1732 case ARENA_TYPE_3v3: 1733 return BATTLEGROUND_QUEUE_3v3; 1734 case ARENA_TYPE_5v5: 1735 return BATTLEGROUND_QUEUE_5v5; 1736 default: 1737 return 0; 1738 } 1739 default: 1740 return 0; 1741 } 1742 } 1743 1744 uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const 1745 { 1746 switch(bgQueueTypeId) 1747 { 1748 case BATTLEGROUND_QUEUE_WS: 1749 return BATTLEGROUND_WS; 1750 case BATTLEGROUND_QUEUE_AB: 1751 return BATTLEGROUND_AB; 1752 case BATTLEGROUND_QUEUE_AV: 1753 return BATTLEGROUND_AV; 1754 case BATTLEGROUND_QUEUE_EY: 1755 return BATTLEGROUND_EY; 1756 case BATTLEGROUND_QUEUE_2v2: 1757 case BATTLEGROUND_QUEUE_3v3: 1758 case BATTLEGROUND_QUEUE_5v5: 1759 return BATTLEGROUND_AA; 1760 default: 1761 return 0; 1762 } 1763 } 1764 1765 uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const 1766 { 1767 switch(bgQueueTypeId) 1768 { 1769 case BATTLEGROUND_QUEUE_2v2: 1770 return ARENA_TYPE_2v2; 1771 case BATTLEGROUND_QUEUE_3v3: 1772 return ARENA_TYPE_3v3; 1773 case BATTLEGROUND_QUEUE_5v5: 1774 return ARENA_TYPE_5v5; 1775 default: 1776 return 0; 1777 } 1778 } 1779 1780 void BattleGroundMgr::ToggleArenaTesting() 1781 { 1782 m_ArenaTesting = !m_ArenaTesting; 1783 sWorld.SendWorldText(LANG_ARENA_TESTING, m_ArenaTesting ? "on" : "off"); 1784 } -
trunk/src/game/BattleGroundMgr.h
r2 r9 35 35 #define MAX_BATTLEGROUND_TYPES 9 // each BG type will be in array 36 36 37 struct PlayerQueueInfo 37 #define MAX_BATTLEGROUND_QUEUE_TYPES 8 38 39 #define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day 40 41 struct GroupQueueInfo; // type predefinition 42 struct PlayerQueueInfo // stores information for players in queue 38 43 { 39 44 uint32 InviteTime; // first invite time 40 45 uint32 LastInviteTime; // last invite time 46 uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes 47 GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo 48 }; 49 50 struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!) 51 { 52 std::map<uint64, PlayerQueueInfo*> Players; // player queue info map 53 uint32 Team; // Player team (ALLIANCE/HORDE) 54 bool IsRated; // rated 55 uint32 BgTypeId; // battleground type id 56 uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG 57 uint32 ArenaTeamId; // team id if rated match 58 uint32 JoinTime; // time when group was added 41 59 uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG 42 uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes 43 uint32 Team; // Player team (ALLIANCE/HORDE) 44 bool IsRated; 45 bool AsGroup; // uint32 GroupId; 46 uint8 ArenaType; 47 }; 48 49 struct PlayersCount 50 { 51 uint32 Alliance; 52 uint32 Horde; 53 }; 54 55 template<class _Kty, class _Ty> class bgqueue: public std::map<_Kty, _Ty> 56 { 57 public: 58 uint32 Alliance; 59 uint32 Horde; 60 //bool Ready; // not used now 61 //uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players) 62 }; 63 60 uint32 ArenaTeamRating; // if rated match, inited to the rating of the team 61 }; 62 63 class BattleGround; 64 64 class BattleGroundQueue 65 65 { … … 67 67 BattleGroundQueue(); 68 68 ~BattleGroundQueue(); 69 /* 70 uint32 GetType(); 71 void SetType(uint32 type);*/ 72 73 void Update(uint32 bgTypeId, uint32 queue_id); 74 75 void AddPlayer(Player *plr, uint32 bgTypeId); 69 70 void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0); 71 72 GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); 73 void AddPlayer(Player *plr, GroupQueueInfo * ginfo); 76 74 void RemovePlayer(uint64 guid, bool decreaseInvitedCount); 77 78 typedef bgqueue<uint64, PlayerQueueInfo> QueuedPlayersMap; 75 void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); 76 void BGEndedRemoveInvites(BattleGround * bg); 77 78 typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap; 79 79 QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; 80 typedef std::list<uint64> PlayerGuidsSortedByTimeQueue; 81 PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES]; 80 81 typedef std::list<GroupQueueInfo*> QueuedGroupsList; 82 QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES]; 83 84 // class to hold pointers to the groups eligible for a specific selection pool building mode 85 class EligibleGroups : public std::list<GroupQueueInfo *> 86 { 87 public: 88 void Init(QueuedGroupsList * source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); 89 void RemoveGroup(GroupQueueInfo * ginfo); 90 }; 91 92 EligibleGroups m_EligibleGroups; 93 94 // class to select and invite groups to bg 95 class SelectionPool 96 { 97 public: 98 void Init(); 99 void AddGroup(GroupQueueInfo * group); 100 GroupQueueInfo * GetMaximalGroup(); 101 void RemoveGroup(GroupQueueInfo * group); 102 uint32 GetPlayerCount() const {return PlayerCount;} 103 public: 104 std::list<GroupQueueInfo *> SelectedGroups; 105 private: 106 uint32 PlayerCount; 107 GroupQueueInfo * MaxGroup; 108 }; 109 110 enum SelectionPoolBuildMode 111 { 112 NORMAL_ALLIANCE, 113 NORMAL_HORDE, 114 ONESIDE_ALLIANCE_TEAM1, 115 ONESIDE_ALLIANCE_TEAM2, 116 ONESIDE_HORDE_TEAM1, 117 ONESIDE_HORDE_TEAM2, 118 119 NUM_SELECTION_POOL_TYPES 120 }; 121 122 SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES]; 123 124 bool BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); 125 126 private: 127 128 bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side); 82 129 }; 83 130 … … 97 144 uint64 m_PlayerGuid; 98 145 uint32 m_BgInstanceGUID; 99 100 146 }; 101 147 … … 116 162 uint32 m_PlayersTeam; 117 163 }; 118 119 164 120 165 class BattleGroundMgr … … 133 178 void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); 134 179 void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); 135 void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2 );180 void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); 136 181 void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); 137 182 138 183 /* Player invitation */ 139 184 // called from Queue update, or from Addplayer to queue 140 void InvitePlayer(Player* plr, uint32 bgInstanceGUID );185 void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); 141 186 142 187 /* Battlegrounds */ … … 144 189 BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; 145 190 146 BattleGround* GetBattleGround(uint 8ID)191 BattleGround* GetBattleGround(uint32 ID) 147 192 { 148 193 BattleGroundSet::iterator i = m_BattleGrounds.find(ID); … … 153 198 }; 154 199 200 BattleGround * GetBattleGroundTemplate(uint32 bgTypeId); 201 BattleGround * CreateNewBattleGround(uint32 bgTypeId); 202 155 203 uint32 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); 156 204 157 205 inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; 206 void RemoveBattleGround(uint32 instanceID); 158 207 159 208 void CreateInitialBattleGrounds(); … … 163 212 /* Battleground queues */ 164 213 //these queues are instantiated when creating BattlegroundMrg 165 BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_ TYPES]; // public, because we need to access them in BG handler code214 BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; // public, because we need to access them in BG handler code 166 215 167 216 BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES]; 168 217 169 218 void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); 219 220 bool IsArenaType(uint32 bgTypeId) const; 221 bool IsBattleGroundType(uint32 bgTypeId) const; 222 uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const; 223 uint32 BGTemplateId(uint32 bgQueueTypeId) const; 224 uint8 BGArenaType(uint32 bgQueueTypeId) const; 225 226 uint32 GetMaxRatingDifference() const {return m_MaxRatingDifference;} 227 uint32 GetRatingDiscardTimer() const {return m_RatingDiscardTimer;} 228 229 void InitAutomaticArenaPointDistribution(); 230 void DistributeArenaPoints(); 231 uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;} 232 void ToggleArenaTesting(); 233 const bool isArenaTesting() const { return m_ArenaTesting; } 170 234 171 235 private: … … 173 237 /* Battlegrounds */ 174 238 BattleGroundSet m_BattleGrounds; 239 uint32 m_MaxRatingDifference; 240 uint32 m_RatingDiscardTimer; 241 uint32 m_NextRatingDiscardUpdate; 242 bool m_AutoDistributePoints; 243 uint64 m_NextAutoDistributionTime; 244 uint32 m_AutoDistributionTimeChecker; 245 uint32 m_PrematureFinishTimer; 246 bool m_ArenaTesting; 175 247 }; 176 248 -
trunk/src/game/BattleGroundNA.cpp
r2 r9 48 48 { 49 49 m_Events |= 0x01; 50 // setup here, only when at least one player has ported to the map 51 if(!SetupBattleGround()) 52 { 53 EndNow(); 54 return; 55 } 50 56 for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++) 51 57 SpawnBGObject(i, RESPAWN_IMMEDIATELY); … … 73 79 for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++) 74 80 DoorOpen(i); 81 82 for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++) 83 SpawnBGObject(i, 60); 75 84 76 85 SendMessageToAll(LANG_ARENA_BEGUN); … … 81 90 if(Player *plr = objmgr.GetPlayer(itr->first)) 82 91 plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); 92 93 if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 94 EndBattleGround(HORDE); 95 else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) 96 EndBattleGround(ALLIANCE); 83 97 } 84 98 } … … 97 111 98 112 m_PlayerScores[plr->GetGUID()] = sc; 113 114 UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); 115 UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); 99 116 } 100 117 101 118 void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) 102 119 { 103 120 if(GetStatus() == STATUS_WAIT_LEAVE) 121 return; 122 123 UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); 124 UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); 125 126 if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 127 EndBattleGround(HORDE); 128 else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) 129 EndBattleGround(ALLIANCE); 104 130 } 105 131 … … 115 141 } 116 142 117 BattleGround::HandleKillPlayer(player, killer); 118 119 uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); 120 121 ++m_TeamKills[killer_team_index]; // add kills to killer's team 122 123 if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) 143 BattleGround::HandleKillPlayer(player,killer); 144 145 UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); 146 UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); 147 148 if(!GetAlivePlayersCountByTeam(ALLIANCE)) 124 149 { 125 150 // all opponents killed 126 EndBattleGround(killer->GetTeam()); 127 } 151 EndBattleGround(HORDE); 152 } 153 else if(!GetAlivePlayersCountByTeam(HORDE)) 154 { 155 // all opponents killed 156 EndBattleGround(ALLIANCE); 157 } 158 } 159 160 bool BattleGroundNA::HandlePlayerUnderMap(Player *player) 161 { 162 player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false); 163 return true; 128 164 } 129 165 … … 150 186 } 151 187 188 void BattleGroundNA::FillInitialWorldStates(WorldPacket &data) 189 { 190 data << uint32(0xa0f) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 191 data << uint32(0xa10) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 192 data << uint32(0xa11) << uint32(1); // 9 193 } 194 152 195 void BattleGroundNA::ResetBGSubclass() 153 196 { 154 m_TeamKills[BG_TEAM_ALLIANCE] = 0; 155 m_TeamKills[BG_TEAM_HORDE] = 0; 197 156 198 } 157 199 … … 159 201 { 160 202 // gates 161 if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) 162 || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY) 163 || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) 164 || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)) 203 if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) 204 || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) 205 || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) 206 || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) 207 // buffs 208 || !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) 209 || !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) 165 210 { 166 211 sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); -
trunk/src/game/BattleGroundNA.h
r2 r9 27 27 BG_NA_OBJECT_DOOR_3 = 2, 28 28 BG_NA_OBJECT_DOOR_4 = 3, 29 BG_NA_OBJECT_MAX = 4 29 BG_NA_OBJECT_BUFF_1 = 4, 30 BG_NA_OBJECT_BUFF_2 = 5, 31 BG_NA_OBJECT_MAX = 6 30 32 }; 31 33 … … 35 37 BG_NA_OBJECT_TYPE_DOOR_2 = 183980, 36 38 BG_NA_OBJECT_TYPE_DOOR_3 = 183977, 37 BG_NA_OBJECT_TYPE_DOOR_4 = 183979 39 BG_NA_OBJECT_TYPE_DOOR_4 = 183979, 40 BG_NA_OBJECT_TYPE_BUFF_1 = 184663, 41 BG_NA_OBJECT_TYPE_BUFF_2 = 184664 38 42 }; 39 43 … … 62 66 bool SetupBattleGround(); 63 67 virtual void ResetBGSubclass(); 68 virtual void FillInitialWorldStates(WorldPacket &d); 64 69 void HandleKillPlayer(Player* player, Player *killer); 65 66 private: 67 uint32 m_TeamKills[2]; // count of kills for each team 70 bool HandlePlayerUnderMap(Player * plr); 68 71 }; 69 72 #endif -
trunk/src/game/BattleGroundRL.cpp
r2 r9 48 48 m_Events |= 0x01; 49 49 50 // setup here, only when at least one player has ported to the map 51 if(!SetupBattleGround()) 52 { 53 EndNow(); 54 return; 55 } 56 50 57 for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) 51 58 SpawnBGObject(i, RESPAWN_IMMEDIATELY); … … 73 80 for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) 74 81 DoorOpen(i); 82 83 for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++) 84 SpawnBGObject(i, 60); 75 85 76 86 SendMessageToAll(LANG_ARENA_BEGUN); … … 81 91 if(Player *plr = objmgr.GetPlayer(itr->first)) 82 92 plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); 93 94 if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 95 EndBattleGround(HORDE); 96 else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) 97 EndBattleGround(ALLIANCE); 83 98 } 84 99 } … … 97 112 98 113 m_PlayerScores[plr->GetGUID()] = sc; 114 115 UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); 116 UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); 99 117 } 100 118 101 119 void BattleGroundRL::RemovePlayer(Player *plr, uint64 guid) 102 120 { 103 121 if(GetStatus() == STATUS_WAIT_LEAVE) 122 return; 123 124 UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); 125 UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); 126 127 if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) 128 EndBattleGround(HORDE); 129 else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) 130 EndBattleGround(ALLIANCE); 104 131 } 105 132 … … 115 142 } 116 143 117 BattleGround::HandleKillPlayer(player, killer); 118 119 uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); 120 121 ++m_TeamKills[killer_team_index]; // add kills to killer's team 122 123 if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) 144 BattleGround::HandleKillPlayer(player,killer); 145 146 UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); 147 UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); 148 149 if(!GetAlivePlayersCountByTeam(ALLIANCE)) 124 150 { 125 151 // all opponents killed 126 EndBattleGround(killer->GetTeam()); 127 } 152 EndBattleGround(HORDE); 153 } 154 else if(!GetAlivePlayersCountByTeam(HORDE)) 155 { 156 // all opponents killed 157 EndBattleGround(ALLIANCE); 158 } 159 } 160 161 bool BattleGroundRL::HandlePlayerUnderMap(Player *player) 162 { 163 player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false); 164 return true; 128 165 } 129 166 … … 151 188 } 152 189 190 void BattleGroundRL::FillInitialWorldStates(WorldPacket &data) 191 { 192 data << uint32(0xbb8) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 193 data << uint32(0xbb9) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 194 data << uint32(0xbba) << uint32(1); // 9 195 } 196 153 197 void BattleGroundRL::ResetBGSubclass() 154 198 { 155 m_TeamKills[BG_TEAM_ALLIANCE] = 0; 156 m_TeamKills[BG_TEAM_HORDE] = 0; 199 157 200 } 158 201 … … 160 203 { 161 204 // gates 162 if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY) 163 || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY)) 205 if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY) 206 || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY) 207 // buffs 208 || !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) 209 || !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) 164 210 { 165 211 sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); -
trunk/src/game/BattleGroundRL.h
r2 r9 25 25 BG_RL_OBJECT_DOOR_1 = 0, 26 26 BG_RL_OBJECT_DOOR_2 = 1, 27 BG_RL_OBJECT_MAX = 2 27 BG_RL_OBJECT_BUFF_1 = 2, 28 BG_RL_OBJECT_BUFF_2 = 3, 29 BG_RL_OBJECT_MAX = 4 28 30 }; 29 31 … … 31 33 { 32 34 BG_RL_OBJECT_TYPE_DOOR_1 = 185918, 33 BG_RL_OBJECT_TYPE_DOOR_2 = 185917 35 BG_RL_OBJECT_TYPE_DOOR_2 = 185917, 36 BG_RL_OBJECT_TYPE_BUFF_1 = 184663, 37 BG_RL_OBJECT_TYPE_BUFF_2 = 184664 34 38 }; 35 39 … … 58 62 bool SetupBattleGround(); 59 63 virtual void ResetBGSubclass(); 64 virtual void FillInitialWorldStates(WorldPacket &d); 60 65 void HandleKillPlayer(Player* player, Player *killer); 61 62 private: 63 uint32 m_TeamKills[2]; // count of kills for each team 66 bool HandlePlayerUnderMap(Player * plr); 64 67 }; 65 68 #endif -
trunk/src/game/BattleGroundWS.cpp
r2 r9 50 50 m_Events |= 0x01; 51 51 52 // setup here, only when at least one player has ported to the map 53 if(!SetupBattleGround()) 54 { 55 EndNow(); 56 return; 57 } 58 52 59 for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++) 53 60 { … … 286 293 void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) 287 294 { 288 // Drop allowed in any BG state 295 if(GetStatus() != STATUS_IN_PROGRESS) 296 { 297 // if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages 298 // just take off the aura 299 if(Source->GetTeam() == ALLIANCE) 300 { 301 if(!this->IsHordeFlagPickedup()) 302 return; 303 if(GetHordeFlagPickerGUID() == Source->GetGUID()) 304 { 305 SetHordeFlagPicker(0); 306 Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); 307 } 308 } 309 else 310 { 311 if(!this->IsAllianceFlagPickedup()) 312 return; 313 if(GetAllianceFlagPickerGUID() == Source->GetGUID()) 314 { 315 SetAllianceFlagPicker(0); 316 Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); 317 } 318 } 319 return; 320 } 289 321 290 322 const char *message = ""; -
trunk/src/game/Chat.cpp
r6 r9 164 164 { "anim", SEC_GAMEMASTER, &ChatHandler::HandleAnimCommand, "", NULL }, 165 165 { "lootrecipient", SEC_GAMEMASTER, &ChatHandler::HandleGetLootRecipient, "", NULL }, 166 { "arena", SEC_ADMINISTRATOR, &ChatHandler::HandleDebugArenaCommand, "", NULL }, 166 167 { NULL, 0, NULL, "", NULL } 167 168 }; … … 512 513 { "damage", SEC_ADMINISTRATOR, &ChatHandler::HandleDamageCommand, "", NULL }, 513 514 { "combatstop", SEC_GAMEMASTER, &ChatHandler::HandleCombatStopCommand, "", NULL }, 515 { "flusharenapoints", SEC_ADMINISTRATOR, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL }, 514 516 515 517 { NULL, 0, NULL, "", NULL } -
trunk/src/game/Chat.h
r6 r9 381 381 bool HandleComeToMeCommand(const char *args); 382 382 bool HandleCombatStopCommand(const char *args); 383 bool HandleFlushArenaPointsCommand(const char *args); 383 384 384 385 //! Development Commands … … 393 394 bool HandleGetItemState(const char * args); 394 395 bool HandleGetLootRecipient(const char * args); 396 bool HandleDebugArenaCommand(const char * args); 395 397 396 398 Player* getSelectedPlayer(); -
trunk/src/game/Group.cpp
r2 r9 1245 1245 } 1246 1246 1247 uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) 1248 { 1249 // check for min / max count 1250 uint32 memberscount = GetMembersCount(); 1251 if(memberscount < MinPlayerCount) 1252 return BG_JOIN_ERR_GROUP_NOT_ENOUGH; 1253 if(memberscount > MaxPlayerCount) 1254 return BG_JOIN_ERR_GROUP_TOO_MANY; 1255 1256 // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.) 1257 Player * reference = GetFirstMember()->getSource(); 1258 // no reference found, can't join this way 1259 if(!reference) 1260 return BG_JOIN_ERR_OFFLINE_MEMBER; 1261 1262 uint32 bgQueueId = reference->GetBattleGroundQueueIdFromLevel(); 1263 uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); 1264 uint32 team = reference->GetTeam(); 1265 1266 // check every member of the group to be able to join 1267 for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) 1268 { 1269 Player *member = itr->getSource(); 1270 // offline member? don't let join 1271 if(!member) 1272 return BG_JOIN_ERR_OFFLINE_MEMBER; 1273 // don't allow cross-faction join as group 1274 if(member->GetTeam() != team) 1275 return BG_JOIN_ERR_MIXED_FACTION; 1276 // not in the same battleground level braket, don't let join 1277 if(member->GetBattleGroundQueueIdFromLevel() != bgQueueId) 1278 return BG_JOIN_ERR_MIXED_LEVELS; 1279 // don't let join rated matches if the arena team id doesn't match 1280 if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) 1281 return BG_JOIN_ERR_MIXED_ARENATEAM; 1282 // don't let join if someone from the group is already in that bg queue 1283 if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueType)) 1284 return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE; 1285 // check for deserter debuff in case not arena queue 1286 if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground()) 1287 return BG_JOIN_ERR_GROUP_DESERTER; 1288 // check if member can join any more battleground queues 1289 if(!member->HasFreeBattleGroundQueueId()) 1290 return BG_JOIN_ERR_ALL_QUEUES_USED; 1291 } 1292 return BG_JOIN_ERR_OK; 1293 } 1294 1247 1295 //=================================================== 1248 1296 //============== Roll =============================== -
trunk/src/game/Group.h
r2 r9 233 233 } 234 234 void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } 235 uint32 CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot); 235 236 236 237 void ChangeMembersGroup(const uint64 &guid, const uint8 &group); -
trunk/src/game/Language.h
r6 r9 608 608 LANG_PLAYER_AFK_DEFAULT = 710, 609 609 610 LANG_BG_QUEUE_ANNOUNCE_SELF = 711, 611 LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, 610 LANG_BG_GROUP_TOO_LARGE = 711, 611 LANG_ARENA_GROUP_TOO_LARGE = 712, 612 LANG_ARENA_YOUR_TEAM_ONLY = 713, 613 LANG_ARENA_NOT_ENOUGH_PLAYERS = 714, 614 LANG_ARENA_GOLD_WINS = 715, 615 LANG_ARENA_GREEN_WINS = 716, 616 LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 717, 617 LANG_BG_GROUP_OFFLINE_MEMBER = 718, 618 LANG_BG_GROUP_MIXED_FACTION = 719, 619 LANG_BG_GROUP_MIXED_LEVELS = 720, 620 LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 721, 621 LANG_BG_GROUP_MEMBER_DESERTER = 722, 622 LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 723, 623 624 LANG_CANNOT_TELE_TO_BG = 724, 625 LANG_CANNOT_SUMMON_TO_BG = 725, 626 LANG_CANNOT_GO_TO_BG_GM = 726, 627 LANG_CANNOT_GO_TO_BG_FROM_BG = 727, 628 629 LANG_ARENA_TESTING = 728 630 612 631 }; 613 632 #endif -
trunk/src/game/Level1.cpp
r6 r9 316 316 Map* pMap = MapManager::Instance().GetMap(m_session->GetPlayer()->GetMapId(),m_session->GetPlayer()); 317 317 318 if(pMap->Instanceable()) 318 if(pMap->IsBattleGroundOrArena()) 319 { 320 // cannot summon to bg 321 SendSysMessage(LANG_CANNOT_SUMMON_TO_BG); 322 SetSentErrorMessage(true); 323 return false; 324 } 325 else if(pMap->IsDungeon()) 319 326 { 320 327 Map* cMap = MapManager::Instance().GetMap(chr->GetMapId(),chr); … … 402 409 { 403 410 Map* cMap = MapManager::Instance().GetMap(chr->GetMapId(),chr); 404 if(cMap->Instanceable()) 411 if(cMap->IsBattleGroundOrArena()) 412 { 413 // only allow if gm mode is on 414 if (!_player->isGameMaster()) 415 { 416 SendSysMessage(LANG_CANNOT_GO_TO_BG_GM); 417 SetSentErrorMessage(true); 418 return false; 419 } 420 // if already in a bg, don't let port to other 421 else if (_player->GetBattleGroundId()) 422 { 423 SendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG); 424 SetSentErrorMessage(true); 425 return false; 426 } 427 // all's well, set bg id 428 // when porting out from the bg, it will be reset to 0 429 _player->SetBattleGroundId(chr->GetBattleGroundId()); 430 } 431 else if(cMap->IsDungeon()) 405 432 { 406 433 Map* pMap = MapManager::Instance().GetMap(_player->GetMapId(),_player); … … 1586 1613 // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r 1587 1614 GameTele const* tele = extractGameTeleFromLink((char*)args); 1588 1589 1615 if (!tele) 1590 1616 { 1591 1617 SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); 1618 SetSentErrorMessage(true); 1619 return false; 1620 } 1621 1622 MapEntry const * me = sMapStore.LookupEntry(tele->mapId); 1623 if(!me || me->IsBattleGroundOrArena()) 1624 { 1625 SendSysMessage(LANG_CANNOT_TELE_TO_BG); 1592 1626 SetSentErrorMessage(true); 1593 1627 return false; … … 1866 1900 } 1867 1901 1902 MapEntry const * me = sMapStore.LookupEntry(tele->mapId); 1903 if(!me || me->IsBattleGroundOrArena()) 1904 { 1905 SendSysMessage(LANG_CANNOT_TELE_TO_BG); 1906 SetSentErrorMessage(true); 1907 return false; 1908 } 1909 1868 1910 Player *chr = objmgr.GetPlayer(name.c_str()); 1869 1911 if (chr) … … 1928 1970 } 1929 1971 1972 MapEntry const * me = sMapStore.LookupEntry(tele->mapId); 1973 if(!me || me->IsBattleGroundOrArena()) 1974 { 1975 SendSysMessage(LANG_CANNOT_TELE_TO_BG); 1976 SetSentErrorMessage(true); 1977 return false; 1978 } 1930 1979 Group *grp = player->GetGroup(); 1931 1980 if(!grp) -
trunk/src/game/Level3.cpp
r6 r9 47 47 #include "Util.h" 48 48 #include "ItemEnchantmentMgr.h" 49 #include "BattleGroundMgr.h" 49 50 #include "InstanceSaveMgr.h" 50 51 #include "InstanceData.h" … … 5458 5459 return true; 5459 5460 } 5461 5462 bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/) 5463 { 5464 sBattleGroundMgr.DistributeArenaPoints(); 5465 return true; 5466 } -
trunk/src/game/MapInstanced.cpp
r2 r9 142 142 Player* player = (Player*)obj; 143 143 144 // TODO: battlegrounds and arenas 144 if(IsBattleGroundOrArena()) 145 { 146 // instantiate or find existing bg map for player 147 // the instance id is set in battlegroundid 148 NewInstanceId = player->GetBattleGroundId(); 149 assert(NewInstanceId); 150 map = _FindMap(NewInstanceId); 151 if(!map) 152 map = CreateBattleGround(NewInstanceId); 153 return map; 154 } 145 155 146 156 InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty()); -
trunk/src/game/MapManager.cpp
r2 r9 108 108 109 109 const MapEntry* entry = sMapStore.LookupEntry(id); 110 if (entry && entry->I sDungeon())110 if (entry && entry->Instanceable()) 111 111 { 112 112 m = new MapInstanced(id, i_gridCleanUpDelay, 0); -
trunk/src/game/MiscHandler.cpp
r2 r9 847 847 return; 848 848 849 if (BattleGround * bg = _player->GetBattleGround()) 850 if(bg->isArena()) 851 return; 852 849 853 // body not released yet 850 854 if(!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) -
trunk/src/game/MovementHandler.cpp
r2 r9 131 131 132 132 // battleground state preper 133 if(_player->InBattleGround()) 133 // only add to bg group and object, if the player was invited (else he entered through command) 134 if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) 134 135 { 135 136 BattleGround *bg = _player->GetBattleGround(); 136 137 if(bg) 137 138 { 139 bg->AddPlayer(_player); 138 140 if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg 139 141 { 140 if(!bg->GetBgRaid(_player->GetTeam())) // first player joined 142 // get the team this way, because arenas might 'override' the teams. 143 uint32 team = bg->GetPlayerTeam(_player->GetGUID()); 144 if(!team) 145 team = _player->GetTeam(); 146 if(!bg->GetBgRaid(team)) // first player joined 141 147 { 142 148 Group *group = new Group; 143 bg->SetBgRaid( _player->GetTeam(), group);149 bg->SetBgRaid(team, group); 144 150 group->Create(_player->GetGUIDLow(), _player->GetName()); 145 151 } 146 152 else // raid already exist 147 153 { 148 bg->GetBgRaid( _player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName());154 bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName()); 149 155 } 150 156 } … … 366 372 if(movementInfo.z < -500.0f) 367 373 { 368 // NOTE: this is actually called many times while falling 369 // even after the player has been teleported away 370 // TODO: discard movement packets after the player is rooted 371 if(GetPlayer()->isAlive()) 372 { 373 GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); 374 // change the death state to CORPSE to prevent the death timer from 375 // starting in the next player update 376 GetPlayer()->KillPlayer(); 377 GetPlayer()->BuildPlayerRepop(); 378 } 379 380 // cancel the death timer here if started 381 GetPlayer()->RepopAtGraveyard(); 374 if(GetPlayer()->InBattleGround() 375 && GetPlayer()->GetBattleGround() 376 && GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player)) 377 { 378 // do nothing, the handle already did if returned true 379 } 380 else 381 { 382 // NOTE: this is actually called many times while falling 383 // even after the player has been teleported away 384 // TODO: discard movement packets after the player is rooted 385 if(GetPlayer()->isAlive()) 386 { 387 GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); 388 // change the death state to CORPSE to prevent the death timer from 389 // starting in the next player update 390 GetPlayer()->KillPlayer(); 391 GetPlayer()->BuildPlayerRepop(); 392 } 393 394 // cancel the death timer here if started 395 GetPlayer()->RepopAtGraveyard(); 396 } 382 397 } 383 398 } -
trunk/src/game/ObjectMgr.h
r6 r9 311 311 void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); } 312 312 void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); } 313 ArenaTeamSet::iterator GetArenaTeamSetBegin() { return mArenaTeamSet.begin(); } 314 ArenaTeamSet::iterator GetArenaTeamSetEnd() { return mArenaTeamSet.end(); } 313 315 314 316 static CreatureInfo const *GetCreatureTemplate( uint32 id ); -
trunk/src/game/Player.cpp
r6 r9 347 347 for (int j=0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; j++) 348 348 { 349 m_bgBattleGroundQueueID[j].bg Type = 0;350 m_bgBattleGroundQueueID[j].invited = false;349 m_bgBattleGroundQueueID[j].bgQueueType = 0; 350 m_bgBattleGroundQueueID[j].invitedToInstance = 0; 351 351 } 352 352 m_bgTeam = 0; … … 1440 1440 1441 1441 // don't let enter battlegrounds without assigned battleground id (for example through areatrigger)... 1442 if(!InBattleGround() && mEntry->IsBattleGround() && !GetSession()->GetSecurity()) 1442 // don't let gm level > 1 either 1443 if(!InBattleGround() && mEntry->IsBattleGroundOrArena()) 1443 1444 return false; 1444 1445 … … 3453 3454 if(guild) 3454 3455 guild->DelMember(guid); 3456 } 3457 3458 // remove from arena teams 3459 uint32 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_2v2); 3460 if(at_id != 0) 3461 { 3462 ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 3463 if(at) 3464 at->DelMember(playerguid); 3465 } 3466 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_3v3); 3467 if(at_id != 0) 3468 { 3469 ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 3470 if(at) 3471 at->DelMember(playerguid); 3472 } 3473 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_5v5); 3474 if(at_id != 0) 3475 { 3476 ArenaTeam * at = objmgr.GetArenaTeamById(at_id); 3477 if(at) 3478 at->DelMember(playerguid); 3455 3479 } 3456 3480 … … 5884 5908 UpdateHonorFields(); 5885 5909 5910 // do not reward honor in arenas, but return true to enable onkill spellproc 5911 if(InBattleGround() && GetBattleGround() && GetBattleGround()->isArena()) 5912 return true; 5913 5886 5914 if(honor <= 0) 5887 5915 { … … 6047 6075 uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) 6048 6076 { 6049 // need fix it!6050 6077 QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid FROM arena_team_member WHERE guid='%u'", GUID_LOPART(guid)); 6051 6078 if(result) 6052 6079 { 6053 // init id to 0, check the arena type before assigning a value to id 6054 uint32 id = 0; 6080 bool found = false; 6081 // init id to find the type of the arenateam 6082 uint32 id = (*result)[0].GetUInt32(); 6055 6083 do 6056 6084 { … … 6063 6091 { 6064 6092 // if the type matches, we've found the id 6065 id = (*result)[0].GetUInt32();6093 found = true; 6066 6094 break; 6067 6095 } … … 6069 6097 } while(result->NextRow()); 6070 6098 delete result; 6071 return id;6099 if(found) return id; 6072 6100 } 6073 6101 // no arenateam for the specified guid, return 0 … … 7710 7738 break; 7711 7739 case 3698: // Nagrand Arena 7712 data << uint32(0xa0f) << uint32(0x0); // 7 7713 data << uint32(0xa10) << uint32(0x0); // 8 7714 data << uint32(0xa11) << uint32(0x0); // 9 7740 if (bg && bg->GetTypeID() == BATTLEGROUND_NA) 7741 bg->FillInitialWorldStates(data); 7742 else 7743 { 7744 data << uint32(0xa0f) << uint32(0x0); // 7 7745 data << uint32(0xa10) << uint32(0x0); // 8 7746 data << uint32(0xa11) << uint32(0x0); // 9 show 7747 } 7715 7748 break; 7716 7749 case 3702: // Blade's Edge Arena 7717 data << uint32(0x9f0) << uint32(0x0); // 7 7718 data << uint32(0x9f1) << uint32(0x0); // 8 7719 data << uint32(0x9f3) << uint32(0x0); // 9 7750 if (bg && bg->GetTypeID() == BATTLEGROUND_BE) 7751 bg->FillInitialWorldStates(data); 7752 else 7753 { 7754 data << uint32(0x9f0) << uint32(0x0); // 7 gold 7755 data << uint32(0x9f1) << uint32(0x0); // 8 green 7756 data << uint32(0x9f3) << uint32(0x0); // 9 show 7757 } 7720 7758 break; 7721 7759 case 3968: // Ruins of Lordaeron 7722 data << uint32(0xbb8) << uint32(0x0); // 7 7723 data << uint32(0xbb9) << uint32(0x0); // 8 7724 data << uint32(0xbba) << uint32(0x0); // 9 7760 if (bg && bg->GetTypeID() == BATTLEGROUND_RL) 7761 bg->FillInitialWorldStates(data); 7762 else 7763 { 7764 data << uint32(0xbb8) << uint32(0x0); // 7 gold 7765 data << uint32(0xbb9) << uint32(0x0); // 8 green 7766 data << uint32(0xbba) << uint32(0x0); // 9 show 7767 } 7725 7768 break; 7726 7769 case 3703: // Shattrath City … … 14711 14754 UpdateHonorFields(); 14712 14755 14713 // Must saved before enter into BattleGround 14714 if(InBattleGround()) 14756 // players aren't saved on battleground maps 14757 uint32 mapid = IsBeingTeleported() ? GetTeleportDest().mapid : GetMapId(); 14758 const MapEntry * me = sMapStore.LookupEntry(mapid); 14759 if(!me || me->IsBattleGroundOrArena()) 14715 14760 return; 14716 14761 … … 17461 17506 bool Player::GetBGAccessByLevel(uint32 bgTypeId) const 17462 17507 { 17463 BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); 17508 // get a template bg instead of running one 17509 BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); 17464 17510 if(!bg) 17465 17511 return false; -
trunk/src/game/Player.h
r6 r9 1803 1803 uint32 GetBattleGroundQueueIdFromLevel() const; 1804 1804 1805 uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgType; } 1806 uint32 GetBattleGroundQueueIndex(uint32 bgType) const 1805 bool InBattleGroundQueue() const 1806 { 1807 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1808 if (m_bgBattleGroundQueueID[i].bgQueueType != 0) 1809 return true; 1810 return false; 1811 } 1812 1813 uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgQueueType; } 1814 uint32 GetBattleGroundQueueIndex(uint32 bgQueueType) const 1807 1815 { 1808 1816 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1809 if (m_bgBattleGroundQueueID[i].bg Type == bgType)1817 if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) 1810 1818 return i; 1811 1819 return PLAYER_MAX_BATTLEGROUND_QUEUES; 1812 1820 } 1813 bool IsInvitedForBattleGround Type(uint32 bgType) const1821 bool IsInvitedForBattleGroundQueueType(uint32 bgQueueType) const 1814 1822 { 1815 1823 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1816 if (m_bgBattleGroundQueueID[i].bg Type == bgType)1817 return m_bgBattleGroundQueueID[i].invited ;1824 if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) 1825 return m_bgBattleGroundQueueID[i].invitedToInstance != 0; 1818 1826 return PLAYER_MAX_BATTLEGROUND_QUEUES; 1819 1827 } 1820 bool InBattleGroundQueueForBattleGround Type(uint32 bgType) const1821 { 1822 return GetBattleGroundQueueIndex(bg Type) < PLAYER_MAX_BATTLEGROUND_QUEUES;1828 bool InBattleGroundQueueForBattleGroundQueueType(uint32 bgQueueType) const 1829 { 1830 return GetBattleGroundQueueIndex(bgQueueType) < PLAYER_MAX_BATTLEGROUND_QUEUES; 1823 1831 } 1824 1832 … … 1828 1836 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1829 1837 { 1830 if (m_bgBattleGroundQueueID[i].bg Type == 0 || m_bgBattleGroundQueueID[i].bgType == val)1838 if (m_bgBattleGroundQueueID[i].bgQueueType == 0 || m_bgBattleGroundQueueID[i].bgQueueType == val) 1831 1839 { 1832 m_bgBattleGroundQueueID[i].bg Type = val;1833 m_bgBattleGroundQueueID[i].invited = false;1840 m_bgBattleGroundQueueID[i].bgQueueType = val; 1841 m_bgBattleGroundQueueID[i].invitedToInstance = 0; 1834 1842 return i; 1835 1843 } … … 1837 1845 return PLAYER_MAX_BATTLEGROUND_QUEUES; 1838 1846 } 1847 bool HasFreeBattleGroundQueueId() 1848 { 1849 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1850 if (m_bgBattleGroundQueueID[i].bgQueueType == 0) 1851 return true; 1852 return false; 1853 } 1839 1854 void RemoveBattleGroundQueueId(uint32 val) 1840 1855 { 1841 1856 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1842 1857 { 1843 if (m_bgBattleGroundQueueID[i].bg Type == val)1858 if (m_bgBattleGroundQueueID[i].bgQueueType == val) 1844 1859 { 1845 m_bgBattleGroundQueueID[i].bg Type = 0;1846 m_bgBattleGroundQueueID[i].invited = false;1860 m_bgBattleGroundQueueID[i].bgQueueType = 0; 1861 m_bgBattleGroundQueueID[i].invitedToInstance = 0; 1847 1862 return; 1848 1863 } 1849 1864 } 1850 1865 } 1851 void SetInviteForBattleGround Type(uint32 bgType)1866 void SetInviteForBattleGroundQueueType(uint32 bgQueueType, uint32 instanceId) 1852 1867 { 1853 1868 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1854 if (m_bgBattleGroundQueueID[i].bgType == bgType) 1855 m_bgBattleGroundQueueID[i].invited = true; 1856 } 1857 1869 if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) 1870 m_bgBattleGroundQueueID[i].invitedToInstance = instanceId; 1871 } 1872 bool IsInvitedForBattleGroundInstance(uint32 instanceId) const 1873 { 1874 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) 1875 if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId) 1876 return true; 1877 return false; 1878 } 1858 1879 uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; } 1859 1880 float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; } … … 2035 2056 struct BgBattleGroundQueueID_Rec 2036 2057 { 2037 uint32 bg Type;2038 bool invited;2058 uint32 bgQueueType; 2059 uint32 invitedToInstance; 2039 2060 }; 2040 2061 BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; … … 2050 2071 uint32 m_contestedPvPTimer; 2051 2072 2052 uint32 m_bgTeam; 2073 uint32 m_bgTeam; // what side the player will be added to 2053 2074 2054 2075 /*********************************************************/ -
trunk/src/game/SpellEffects.cpp
r6 r9 2519 2519 } 2520 2520 2521 if(BattleGround* bg = sBattleGroundMgr.GetBattleGround (bgType))2521 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType)) 2522 2522 bg->SendRewardMarkByMail(player,newitemid,no_space); 2523 2523 } -
trunk/src/game/Unit.cpp
r6 r9 594 594 if (health <= damage) 595 595 { 596 // battleground things597 if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround()))598 {599 Player *killed = ((Player*)pVictim);600 Player *killer = NULL;601 if(GetTypeId() == TYPEID_PLAYER)602 killer = ((Player*)this);603 else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())604 {605 Unit *owner = GetOwner();606 if(owner && owner->GetTypeId() == TYPEID_PLAYER)607 killer = ((Player*)owner);608 }609 610 if(killer)611 if(BattleGround *bg = killed->GetBattleGround())612 bg->HandleKillPlayer(killed, killer); // drop flags and etc613 }614 615 596 DEBUG_LOG("DealDamage: victim just died"); 616 597 … … 750 731 751 732 he->DuelComplete(DUEL_INTERUPTED); 733 } 734 735 // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill) 736 if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround())) 737 { 738 Player *killed = ((Player*)pVictim); 739 Player *killer = NULL; 740 if(GetTypeId() == TYPEID_PLAYER) 741 killer = ((Player*)this); 742 else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) 743 { 744 Unit *owner = GetOwner(); 745 if(owner && owner->GetTypeId() == TYPEID_PLAYER) 746 killer = ((Player*)owner); 747 } 748 749 if(killer) 750 if(BattleGround *bg = killed->GetBattleGround()) 751 bg->HandleKillPlayer(killed, killer); // drop flags and etc 752 752 } 753 753 } … … 4141 4141 AuraMap::iterator iter = m_Auras.begin(); 4142 4142 RemoveAura(iter); 4143 } 4144 } 4145 4146 void Unit::RemoveArenaAuras(bool onleave) 4147 { 4148 // in join, remove positive buffs, on end, remove negative 4149 // used to remove positive visible auras in arenas 4150 for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) 4151 { 4152 if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras 4153 && !iter->second->IsPassive() // don't remove passive auras 4154 && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable) 4155 && (iter->second->IsPositive() ^ onleave)) // remove positive buffs on enter, negative buffs on leave 4156 RemoveAura(iter); 4157 else 4158 ++iter; 4143 4159 } 4144 4160 } -
trunk/src/game/Unit.h
r6 r9 1004 1004 1005 1005 void RemoveAllAuras(); 1006 void RemoveArenaAuras(bool onleave = false); 1006 1007 void RemoveAllAurasOnDeath(); 1007 1008 void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime); -
trunk/src/game/World.cpp
r6 r9 630 630 631 631 m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true); 632 m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", true);633 m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false);634 632 635 633 m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true); … … 770 768 m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300); 771 769 770 771 m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0); 772 m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer",300000); 773 m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false); 774 m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7); 775 776 m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("BattleGround.PrematureFinishTimer", 0); 772 777 773 778 m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); … … 1157 1162 sLog.outString( "Starting BattleGround System" ); 1158 1163 sBattleGroundMgr.CreateInitialBattleGrounds(); 1164 sBattleGroundMgr.InitAutomaticArenaPointDistribution(); 1159 1165 1160 1166 //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager -
trunk/src/game/World.h
r6 r9 102 102 CONFIG_INSTANCE_IGNORE_RAID, 103 103 CONFIG_BATTLEGROUND_CAST_DESERTER, 104 CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,105 CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,106 104 CONFIG_INSTANCE_RESET_TIME_HOUR, 107 105 CONFIG_INSTANCE_UNLOAD_DELAY, … … 160 158 CONFIG_LISTEN_RANGE_TEXTEMOTE, 161 159 CONFIG_LISTEN_RANGE_YELL, 160 CONFIG_ARENA_MAX_RATING_DIFFERENCE, 161 CONFIG_ARENA_RATING_DISCARD_TIMER, 162 CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, 163 CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, 164 CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, 162 165 CONFIG_VALUE_COUNT 163 166 }; -
trunk/src/game/debugcmds.cpp
r2 r9 31 31 #include "Language.h" 32 32 #include "MapManager.h" 33 #include "BattleGroundMgr.h" 33 34 34 35 bool ChatHandler::HandleDebugInArcCommand(const char* /*args*/) … … 513 514 return true; 514 515 } 516 517 bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) 518 { 519 sBattleGroundMgr.ToggleArenaTesting(); 520 return true; 521 } -
trunk/src/shared/Database/DBCStructure.h
r6 r9 472 472 // Helpers 473 473 bool IsExpansionMap() const { return addon != 0; } 474 bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; } 475 // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable 474 475 476 476 bool IsDungeon() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; } 477 bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID || map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; } 477 478 bool IsRaid() const { return map_type == MAP_RAID; } 478 479 bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; } -
trunk/src/trinitycore/trinitycore.conf.dist
r2 r9 438 438 # 0 (false) 439 439 # 440 # Battleground.QueueAnnouncer.Enable441 # Enable queue announcer posting to chat442 # Default: 1 (true)443 # 0 (false)444 #445 # Battleground.QueueAnnouncer.PlayerOnly446 # Enable queue announcer posting to chat447 # Default: 0 (false)448 # 1 (true)449 #450 440 # CastUnstuck 451 441 # Allow cast or not Unstuck spell at .start or client Help option use … … 538 528 ActivateWeather = 1 539 529 Battleground.CastDeserter = 1 540 Battleground.QueueAnnouncer.Enable = 1541 Battleground.QueueAnnouncer.PlayerOnly = 0542 530 CastUnstuck = 1 543 531 Instance.IgnoreLevel = 0 … … 1026 1014 Ra.MinLevel = 3 1027 1015 Ra.Secure = 1 1016 1017 ################################################################################################################### 1018 # 1019 # Rated arena matches config 1020 # 1021 # MaxRatingDifference: the maximum rating difference between two groups in rated matches 1022 # Default: 0 (disable, rating difference is discarded) 1023 # 1024 # RatingDiscardTimer: after the specified milliseconds has passed, 1025 # rating information will be discarded when selecting teams for matches 1026 # also initiates an update by this timer 1027 # Default: 60000 1028 # 1029 # AutoDistributePoints: set if arena points should be distributed automatically, or by GM command 1030 # Default: 0 (disable) (recommended): use gm command or sql query to distribute the points 1031 # 1 (enable): arena points are distributed automatically 1032 # 1033 # AutoDistributeInterval: how often should the distribution take place 1034 # if automatic distribution is enabled 1035 # in days 1036 # Default: 7 (weekly) 1037 # 1038 ################################################################################################################### 1039 1040 Arena.MaxRatingDifference = 0 1041 Arena.RatingDiscardTimer = 60000 1042 Arena.AutoDistributePoints = 0 1043 Arena.AutoDistributeInterval = 7 1044 1045 ################################################################################################################### 1046 # 1047 # Battleground config 1048 # 1049 # PrematureFinishTimer: the time to end the bg if there are less than minplayersperteam on one side 1050 # in milliseconds, 0 - disabled 1051 # Default: 0 1052 # 1053 ################################################################################################################### 1054 1055 BattleGround.PrematureFinishTimer = 0