feat(Core/Battleground): split Arena and Battleground score (#10616)

This commit is contained in:
Kargatum
2022-02-18 05:20:04 +07:00
committed by GitHub
parent dbd7680f5b
commit 5143872aed
41 changed files with 1750 additions and 1766 deletions
@@ -0,0 +1,8 @@
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1645123941917942700');
DELETE FROM `acore_string` WHERE `entry` BETWEEN 600 AND 704;
DELETE FROM `acore_string` WHERE `entry` BETWEEN 724 AND 726;
DELETE FROM `acore_string` WHERE `entry` BETWEEN 753 AND 755;
DELETE FROM `acore_string` WHERE `entry` BETWEEN 1205 AND 1299;
DELETE FROM `acore_string` WHERE `entry` BETWEEN 1326 AND 1330;
DELETE FROM `acore_string` WHERE `entry` = 1333;
@@ -442,7 +442,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
return false; return false;
} }
TeamId winnerTeam = bg->GetWinner(); TeamId winnerTeam = GetTeamId(bg->GetWinner());
if (winnerTeam == TEAM_NEUTRAL) if (winnerTeam == TEAM_NEUTRAL)
{ {
return false; return false;
+9 -9
View File
@@ -231,7 +231,7 @@ void Battlefield::InvitePlayerToQueue(Player* player)
void Battlefield::InvitePlayersInQueueToWar() void Battlefield::InvitePlayersInQueueToWar()
{ {
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
{ {
GuidUnorderedSet copy(m_PlayersInQueue[team]); GuidUnorderedSet copy(m_PlayersInQueue[team]);
for (GuidUnorderedSet::const_iterator itr = copy.begin(); itr != copy.end(); ++itr) for (GuidUnorderedSet::const_iterator itr = copy.begin(); itr != copy.end(); ++itr)
@@ -252,7 +252,7 @@ void Battlefield::InvitePlayersInQueueToWar()
void Battlefield::InvitePlayersInZoneToWar() void Battlefield::InvitePlayersInZoneToWar()
{ {
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (GuidUnorderedSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) for (GuidUnorderedSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
{ {
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
@@ -310,7 +310,7 @@ void Battlefield::InitStalker(uint32 entry, float x, float y, float z, float o)
void Battlefield::KickAfkPlayers() void Battlefield::KickAfkPlayers()
{ {
// xinef: optimization, dont lookup player twice // xinef: optimization, dont lookup player twice
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (GuidUnorderedSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) for (GuidUnorderedSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
if (player->isAFK() && player->GetZoneId() == GetZoneId() && !player->IsGameMaster()) if (player->isAFK() && player->GetZoneId() == GetZoneId() && !player->IsGameMaster())
@@ -331,7 +331,7 @@ void Battlefield::StartBattle()
if (m_isActive) if (m_isActive)
return; return;
for (int team = 0; team < BG_TEAMS_COUNT; team++) for (int team = 0; team < PVP_TEAMS_COUNT; team++)
{ {
m_PlayersInWar[team].clear(); m_PlayersInWar[team].clear();
m_Groups[team].clear(); m_Groups[team].clear();
@@ -378,7 +378,7 @@ void Battlefield::DoPlaySoundToAll(uint32 SoundID)
data.Initialize(SMSG_PLAY_SOUND, 4); data.Initialize(SMSG_PLAY_SOUND, 4);
data << uint32(SoundID); data << uint32(SoundID);
for (int team = 0; team < BG_TEAMS_COUNT; team++) for (int team = 0; team < PVP_TEAMS_COUNT; team++)
for (GuidUnorderedSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) for (GuidUnorderedSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
@@ -449,7 +449,7 @@ void Battlefield::TeamCastSpell(TeamId team, int32 spellId)
void Battlefield::BroadcastPacketToZone(WorldPacket& data) const void Battlefield::BroadcastPacketToZone(WorldPacket& data) const
{ {
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (GuidUnorderedSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) for (GuidUnorderedSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
@@ -457,7 +457,7 @@ void Battlefield::BroadcastPacketToZone(WorldPacket& data) const
void Battlefield::BroadcastPacketToQueue(WorldPacket& data) const void Battlefield::BroadcastPacketToQueue(WorldPacket& data) const
{ {
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (GuidUnorderedSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr) for (GuidUnorderedSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
@@ -465,7 +465,7 @@ void Battlefield::BroadcastPacketToQueue(WorldPacket& data) const
void Battlefield::BroadcastPacketToWar(WorldPacket& data) const void Battlefield::BroadcastPacketToWar(WorldPacket& data) const
{ {
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
for (GuidUnorderedSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) for (GuidUnorderedSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
@@ -487,7 +487,7 @@ void Battlefield::SendWarningToPlayer(Player* player, uint32 entry)
void Battlefield::SendUpdateWorldState(uint32 field, uint32 value) void Battlefield::SendUpdateWorldState(uint32 field, uint32 value)
{ {
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i) for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i)
for (GuidUnorderedSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr) for (GuidUnorderedSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
player->SendUpdateWorldState(field, value); player->SendUpdateWorldState(field, value);
+7 -7
View File
@@ -57,7 +57,7 @@ enum BattlefieldSounds
constexpr auto BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL = 1000; constexpr auto BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL = 1000;
const uint32 BattlefieldFactions[BG_TEAMS_COUNT] = const uint32 BattlefieldFactions[PVP_TEAMS_COUNT] =
{ {
1732, // Alliance 1732, // Alliance
1735 // Horde 1735 // Horde
@@ -372,11 +372,11 @@ protected:
BfCapturePointVector m_capturePoints; BfCapturePointVector m_capturePoints;
// Players info maps // Players info maps
GuidUnorderedSet m_players[BG_TEAMS_COUNT]; // Players in zone GuidUnorderedSet m_players[PVP_TEAMS_COUNT]; // Players in zone
GuidUnorderedSet m_PlayersInQueue[BG_TEAMS_COUNT]; // Players in the queue GuidUnorderedSet m_PlayersInQueue[PVP_TEAMS_COUNT]; // Players in the queue
GuidUnorderedSet m_PlayersInWar[BG_TEAMS_COUNT]; // Players in WG combat GuidUnorderedSet m_PlayersInWar[PVP_TEAMS_COUNT]; // Players in WG combat
PlayerTimerMap m_InvitedPlayers[BG_TEAMS_COUNT]; PlayerTimerMap m_InvitedPlayers[PVP_TEAMS_COUNT];
PlayerTimerMap m_PlayersWillBeKick[BG_TEAMS_COUNT]; PlayerTimerMap m_PlayersWillBeKick[PVP_TEAMS_COUNT];
// Variables that must exist for each battlefield // Variables that must exist for each battlefield
uint32 m_TypeId; // See enum BattlefieldTypes uint32 m_TypeId; // See enum BattlefieldTypes
@@ -403,7 +403,7 @@ protected:
uint32 m_StartGroupingTimer; // Timer for invite players in area 15 minute before start battle uint32 m_StartGroupingTimer; // Timer for invite players in area 15 minute before start battle
bool m_StartGrouping; // bool for know if all players in area has been invited bool m_StartGrouping; // bool for know if all players in area has been invited
GuidUnorderedSet m_Groups[BG_TEAMS_COUNT]; // Contain different raid group GuidUnorderedSet m_Groups[PVP_TEAMS_COUNT]; // Contain different raid group
std::vector<uint64> m_Data64; std::vector<uint64> m_Data64;
std::vector<uint32> m_Data32; std::vector<uint32> m_Data32;
@@ -315,7 +315,7 @@ void BattlefieldWG::UpdateCounterVehicle(bool init)
// Update vehicle count WorldState to player // Update vehicle count WorldState to player
void BattlefieldWG::UpdateVehicleCountWG() void BattlefieldWG::UpdateVehicleCountWG()
{ {
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i) for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i)
for (GuidUnorderedSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr) for (GuidUnorderedSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
{ {
@@ -328,7 +328,7 @@ void BattlefieldWG::UpdateVehicleCountWG()
void BattlefieldWG::CapturePointTaken(uint32 areaId) void BattlefieldWG::CapturePointTaken(uint32 areaId)
{ {
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i) for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i)
for (GuidUnorderedSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr) for (GuidUnorderedSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (Player* player = ObjectAccessor::FindPlayer(*itr))
if (player->GetAreaId() == areaId) if (player->GetAreaId() == areaId)
+328
View File
@@ -0,0 +1,328 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Arena.h"
#include "ArenaTeamMgr.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "World.h"
#include "WorldSession.h"
#include "Pet.h"
#include "ScriptMgr.h"
//#include "WorldStatePackets.h"
void ArenaScore::AppendToPacket(WorldPacket& data)
{
data << PlayerGuid;
data << uint32(KillingBlows);
data << uint8(PvPTeamId);
data << uint32(DamageDone);
data << uint32(HealingDone);
BuildObjectivesBlock(data);
}
void ArenaScore::BuildObjectivesBlock(WorldPacket& data)
{
data << uint32(0); // Objectives Count
}
void ArenaTeamScore::BuildRatingInfoBlock(WorldPacket& data)
{
uint32 ratingLost = std::abs(std::min(RatingChange, 0));
uint32 ratingWon = std::max(RatingChange, 0);
// should be old rating, new rating, and client will calculate rating change itself
data << uint32(ratingLost);
data << uint32(ratingWon);
data << uint32(MatchmakerRating);
}
void ArenaTeamScore::BuildTeamInfoBlock(WorldPacket& data)
{
data << TeamName;
}
Arena::Arena()
{
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
StartMessageIds[BG_STARTING_EVENT_FIRST] = ARENA_TEXT_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = ARENA_TEXT_START_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = ARENA_TEXT_START_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = ARENA_TEXT_START_BATTLE_HAS_BEGUN;
}
void Arena::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores.emplace(player->GetGUID().GetCounter(), new ArenaScore(player->GetGUID(), player->GetBgTeamId()));
if (player->GetBgTeamId() == TEAM_ALLIANCE) // gold
{
if (player->GetTeamId() == TEAM_HORDE)
player->CastSpell(player, SPELL_HORDE_GOLD_FLAG, true);
else
player->CastSpell(player, SPELL_ALLIANCE_GOLD_FLAG, true);
}
else // green
{
if (player->GetTeamId() == TEAM_HORDE)
player->CastSpell(player, SPELL_HORDE_GREEN_FLAG, true);
else
player->CastSpell(player, SPELL_ALLIANCE_GREEN_FLAG, true);
}
UpdateArenaWorldState();
}
void Arena::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
UpdateArenaWorldState();
CheckWinConditions();
}
void Arena::FillInitialWorldStates(WorldPacket& data)
{
data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN) << uint32(GetAlivePlayersCountByTeam(TEAM_HORDE));
data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD) << uint32(GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
}
void Arena::UpdateArenaWorldState()
{
UpdateWorldState(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN, GetAlivePlayersCountByTeam(TEAM_HORDE));
UpdateWorldState(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD, GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
}
void Arena::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
Battleground::HandleKillPlayer(player, killer);
UpdateArenaWorldState();
CheckWinConditions();
}
void Arena::RemovePlayerAtLeave(Player* player)
{
if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
if (auto const& member = Acore::Containers::MapGetValuePtr(m_Players, player->GetGUID()))
{
// if the player was a match participant, calculate rating
auto teamId = member->GetBgTeamId();
ArenaTeam* winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeamId(teamId)));
ArenaTeam* loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(teamId));
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
loserArenaTeam->MemberLost(player, GetArenaMatchmakerRating(GetOtherTeamId(teamId)));
}
}
// remove player
Battleground::RemovePlayerAtLeave(player);
}
void Arena::CheckWinConditions()
{
if (!GetAlivePlayersCountByTeam(TEAM_ALLIANCE) && GetPlayersCountByTeam(TEAM_HORDE))
EndBattleground(TEAM_HORDE);
else if (GetPlayersCountByTeam(TEAM_ALLIANCE) && !GetAlivePlayersCountByTeam(TEAM_HORDE))
EndBattleground(TEAM_ALLIANCE);
}
void Arena::EndBattleground(TeamId winnerTeamId)
{
if (isRated())
{
uint32 startDelay = GetStartDelayTime();
bool bValidArena = GetStatus() == STATUS_IN_PROGRESS && GetStartTime() >= startDelay + 15000; // pussywizard: only if arena lasted at least 15 secs
uint32 loserTeamRating = 0;
uint32 loserMatchmakerRating = 0;
int32 loserChange = 0;
int32 loserMatchmakerChange = 0;
uint32 winnerTeamRating = 0;
uint32 winnerMatchmakerRating = 0;
int32 winnerChange = 0;
int32 winnerMatchmakerChange = 0;
ArenaTeam* winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winnerTeamId == TEAM_NEUTRAL ? TEAM_HORDE : winnerTeamId));
ArenaTeam* loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winnerTeamId == TEAM_NEUTRAL ? TEAM_ALLIANCE : GetOtherTeamId(winnerTeamId)));
auto SaveArenaLogs = [&]()
{
// pussywizard: arena logs in database
uint32 fightId = sArenaTeamMgr->GetNextArenaLogId();
uint32 currOnline = sWorld->GetActiveSessionCount();
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_FIGHT);
stmt2->SetData(0, fightId);
stmt2->SetData(1, GetArenaType());
stmt2->SetData(2, ((GetStartTime() <= startDelay ? 0 : GetStartTime() - startDelay) / 1000));
stmt2->SetData(3, winnerArenaTeam->GetId());
stmt2->SetData(4, loserArenaTeam->GetId());
stmt2->SetData(5, (uint16)winnerTeamRating);
stmt2->SetData(6, (uint16)winnerMatchmakerRating);
stmt2->SetData(7, (int16)winnerChange);
stmt2->SetData(8, (uint16)loserTeamRating);
stmt2->SetData(9, (uint16)loserMatchmakerRating);
stmt2->SetData(10, (int16)loserChange);
stmt2->SetData(11, currOnline);
trans->Append(stmt2);
uint8 memberId = 0;
for (auto const& [playerGuid, arenaLogEntryData] : ArenaLogEntries)
{
stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_MEMBERSTATS);
stmt2->SetData(0, fightId);
stmt2->SetData(1, ++memberId);
stmt2->SetData(2, arenaLogEntryData.Name);
stmt2->SetData(3, arenaLogEntryData.Guid);
stmt2->SetData(4, arenaLogEntryData.ArenaTeamId);
stmt2->SetData(5, arenaLogEntryData.Acc);
stmt2->SetData(6, arenaLogEntryData.IP);
stmt2->SetData(7, arenaLogEntryData.DamageDone);
stmt2->SetData(8, arenaLogEntryData.HealingDone);
stmt2->SetData(9, arenaLogEntryData.KillingBlows);
trans->Append(stmt2);
}
CharacterDatabase.CommitTransaction(trans);
};
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
{
loserTeamRating = loserArenaTeam->GetRating();
loserMatchmakerRating = GetArenaMatchmakerRating(GetOtherTeamId(winnerTeamId));
winnerTeamRating = winnerArenaTeam->GetRating();
winnerMatchmakerRating = GetArenaMatchmakerRating(winnerTeamId);
if (winnerTeamId != TEAM_NEUTRAL)
{
winnerMatchmakerChange = bValidArena ? winnerArenaTeam->WonAgainst(winnerMatchmakerRating, loserMatchmakerRating, winnerChange, GetBgMap()) : 0;
loserMatchmakerChange = loserArenaTeam->LostAgainst(loserMatchmakerRating, winnerMatchmakerRating, loserChange, GetBgMap());
sScriptMgr->OnAfterArenaRatingCalculation(this, winnerMatchmakerChange, loserMatchmakerChange, winnerChange, loserChange);
LOG_DEBUG("bg.arena", "match Type: {} --- Winner: old rating: {}, rating gain: {}, old MMR: {}, MMR gain: {} --- Loser: old rating: {}, rating loss: {}, old MMR: {}, MMR loss: {} ---",
GetArenaType(), winnerTeamRating, winnerChange, winnerMatchmakerRating, winnerMatchmakerChange,
loserTeamRating, loserChange, loserMatchmakerRating, loserMatchmakerChange);
SetArenaMatchmakerRating(winnerTeamId, winnerMatchmakerRating + winnerMatchmakerChange);
SetArenaMatchmakerRating(GetOtherTeamId(winnerTeamId), loserMatchmakerRating + loserMatchmakerChange);
// bg team that the client expects is different to TeamId
// alliance 1, horde 0
uint8 winnerTeam = winnerTeamId == TEAM_ALLIANCE ? PVP_TEAM_ALLIANCE : PVP_TEAM_HORDE;
uint8 loserTeam = winnerTeamId == TEAM_ALLIANCE ? PVP_TEAM_HORDE : PVP_TEAM_ALLIANCE;
_arenaTeamScores[winnerTeam].Assign(winnerChange, winnerMatchmakerRating, winnerArenaTeam->GetName());
_arenaTeamScores[loserTeam].Assign(loserChange, loserMatchmakerRating, loserArenaTeam->GetName());
LOG_DEBUG("bg.arena", "Arena match Type: {} for Team1Id: {} - Team2Id: {} ended. WinnerTeamId: {}. Winner rating: +{}, Loser rating: {}",
GetArenaType(), GetArenaTeamIdForTeam(TEAM_ALLIANCE), GetArenaTeamIdForTeam(TEAM_HORDE), winnerArenaTeam->GetId(), winnerChange, loserChange);
}
else // Deduct 16 points from each teams arena-rating if there are no winners after 45+2 minutes
{
// pussywizard: in case of a draw, the following is always true:
// winnerArenaTeam => TEAM_HORDE, loserArenaTeam => TEAM_ALLIANCE
winnerTeamRating = winnerArenaTeam->GetRating();
winnerMatchmakerRating = GetArenaMatchmakerRating(TEAM_HORDE);
loserTeamRating = loserArenaTeam->GetRating();
loserMatchmakerRating = GetArenaMatchmakerRating(TEAM_ALLIANCE);
winnerMatchmakerChange = 0;
loserMatchmakerChange = 0;
winnerChange = ARENA_TIMELIMIT_POINTS_LOSS;
loserChange = ARENA_TIMELIMIT_POINTS_LOSS;
_arenaTeamScores[PVP_TEAM_ALLIANCE].Assign(ARENA_TIMELIMIT_POINTS_LOSS, winnerMatchmakerRating, winnerArenaTeam->GetName());
_arenaTeamScores[PVP_TEAM_HORDE].Assign(ARENA_TIMELIMIT_POINTS_LOSS, loserMatchmakerRating, loserArenaTeam->GetName());
winnerArenaTeam->FinishGame(ARENA_TIMELIMIT_POINTS_LOSS, GetBgMap());
loserArenaTeam->FinishGame(ARENA_TIMELIMIT_POINTS_LOSS, GetBgMap());
}
}
SaveArenaLogs();
uint8 aliveWinners = GetAlivePlayersCountByTeam(winnerTeamId);
for (auto const& [playerGuid, player] : GetPlayers())
{
auto const& bgTeamId = player->GetBgTeamId();
// per player calculation
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
{
if (bgTeamId == winnerTeamId)
{
if (bValidArena)
{
// update achievement BEFORE personal rating update
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId());
// Last standing - Rated 5v5 arena & be solely alive player
if (GetArenaType() == ARENA_TYPE_5v5 && aliveWinners == 1 && player->IsAlive())
{
player->CastSpell(player, SPELL_LAST_MAN_STANDING, true);
}
winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange);
}
}
else
{
loserArenaTeam->MemberLost(player, winnerMatchmakerRating, loserMatchmakerChange);
// Arena lost => reset the win_rated_arena having the "no_lose" condition
player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE, 0);
}
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA, GetMapId());
}
}
// save the stat changes
if (bValidArena)
{
winnerArenaTeam->SaveToDB();
winnerArenaTeam->NotifyStatsChanged();
}
loserArenaTeam->SaveToDB();
loserArenaTeam->NotifyStatsChanged();
}
// end battleground
Battleground::EndBattleground(winnerTeamId);
}
+66
View File
@@ -0,0 +1,66 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENA_H
#define _ARENA_H
#include "Battleground.h"
enum ArenaBroadcastTexts
{
ARENA_TEXT_START_ONE_MINUTE = 15740,
ARENA_TEXT_START_THIRTY_SECONDS = 15741,
ARENA_TEXT_START_FIFTEEN_SECONDS = 15739,
ARENA_TEXT_START_BATTLE_HAS_BEGUN = 15742,
};
enum ArenaSpellIds
{
SPELL_ALLIANCE_GOLD_FLAG = 32724,
SPELL_ALLIANCE_GREEN_FLAG = 32725,
SPELL_HORDE_GOLD_FLAG = 35774,
SPELL_HORDE_GREEN_FLAG = 35775,
SPELL_LAST_MAN_STANDING = 26549 // Achievement Credit
};
enum ArenaWorldStates
{
ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN = 3600,
ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD = 3601
};
class AC_GAME_API Arena : public Battleground
{
protected:
Arena();
void AddPlayer(Player* player) override;
void RemovePlayer(Player* /*player*/) override;
void FillInitialWorldStates(WorldPacket& data) override;
void UpdateArenaWorldState();
void HandleKillPlayer(Player* player, Player* killer) override;
private:
void RemovePlayerAtLeave(Player* player) override;
void CheckWinConditions() override;
void EndBattleground(TeamId winnerTeamId) override;
};
#endif // WARHEAD_ARENA_H
@@ -0,0 +1,75 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENA_SCORE_H
#define _ARENA_SCORE_H
#include "BattlegroundScore.h"
#include "StringFormat.h"
struct AC_GAME_API ArenaScore : public BattlegroundScore
{
friend class Arena;
protected:
ArenaScore(ObjectGuid playerGuid, TeamId team) :
BattlegroundScore(playerGuid), PvPTeamId(team == TEAM_ALLIANCE ? PVP_TEAM_ALLIANCE : PVP_TEAM_HORDE) { }
void AppendToPacket(WorldPacket& data) final override;
void BuildObjectivesBlock(WorldPacket& data) final override;
// For Logging purpose
std::string ToString() const override
{
return Acore::StringFormatFmt("Damage done: {}, Healing done: {}, Killing blows: {}", DamageDone, HealingDone, KillingBlows);
}
uint8 PvPTeamId;
};
struct AC_GAME_API ArenaTeamScore
{
friend class Arena;
friend class Battleground;
protected:
ArenaTeamScore() = default;
virtual ~ArenaTeamScore() = default;
void Reset()
{
RatingChange = 0;
MatchmakerRating = 0;
TeamName = {};
}
void Assign(int32 ratingChange, uint32 matchMakerRating, std::string_view teamName)
{
RatingChange = ratingChange;
MatchmakerRating = matchMakerRating;
TeamName = teamName;
}
void BuildRatingInfoBlock(WorldPacket& data);
void BuildTeamInfoBlock(WorldPacket& data);
int32 RatingChange = 0;
uint32 MatchmakerRating = 0;
std::string TeamName{};
};
#endif // WARHEAD_ARENA_SCORE_H
+141 -357
View File
@@ -26,7 +26,9 @@
#include "BattlegroundRL.h" #include "BattlegroundRL.h"
#include "BattlegroundRV.h" #include "BattlegroundRV.h"
#include "Chat.h" #include "Chat.h"
#include "ChatTextBuilder.h"
#include "Creature.h" #include "Creature.h"
#include "CreatureTextMgr.h"
#include "Formulas.h" #include "Formulas.h"
#include "GameGraveyard.h" #include "GameGraveyard.h"
#include "GridNotifiersImpl.h" #include "GridNotifiersImpl.h"
@@ -118,6 +120,20 @@ void Battleground::BroadcastWorker(Do& _do)
_do(itr->second); _do(itr->second);
} }
void BattlegroundScore::AppendToPacket(WorldPacket& data)
{
data << PlayerGuid;
data << uint32(KillingBlows);
data << uint32(HonorableKills);
data << uint32(Deaths);
data << uint32(BonusHonor);
data << uint32(DamageDone);
data << uint32(HealingDone);
BuildObjectivesBlock(data);
}
Battleground::Battleground() Battleground::Battleground()
{ {
m_RealTypeID = BATTLEGROUND_TYPE_NONE; m_RealTypeID = BATTLEGROUND_TYPE_NONE;
@@ -129,7 +145,7 @@ Battleground::Battleground()
m_LastResurrectTime = 0; m_LastResurrectTime = 0;
m_ArenaType = 0; m_ArenaType = 0;
m_IsArena = false; m_IsArena = false;
m_WinnerId = TEAM_NEUTRAL; m_WinnerId = PVP_TEAM_NEUTRAL;
m_StartTime = 0; m_StartTime = 0;
m_ResetStatTimer = 0; m_ResetStatTimer = 0;
m_ValidStartPositionTimer = 0; m_ValidStartPositionTimer = 0;
@@ -138,7 +154,6 @@ Battleground::Battleground()
m_IsRated = false; m_IsRated = false;
m_BuffChange = false; m_BuffChange = false;
m_IsRandom = false; m_IsRandom = false;
m_Name = "";
m_LevelMin = 0; m_LevelMin = 0;
m_LevelMax = 0; m_LevelMax = 0;
m_SetDeleteThis = false; m_SetDeleteThis = false;
@@ -151,24 +166,9 @@ Battleground::Battleground()
m_StartMaxDist = 0.0f; m_StartMaxDist = 0.0f;
ScriptId = 0; ScriptId = 0;
m_TeamStartLocX[TEAM_ALLIANCE] = 0;
m_TeamStartLocX[TEAM_HORDE] = 0;
m_TeamStartLocY[TEAM_ALLIANCE] = 0;
m_TeamStartLocY[TEAM_HORDE] = 0;
m_TeamStartLocZ[TEAM_ALLIANCE] = 0;
m_TeamStartLocZ[TEAM_HORDE] = 0;
m_TeamStartLocO[TEAM_ALLIANCE] = 0;
m_TeamStartLocO[TEAM_HORDE] = 0;
m_ArenaTeamIds[TEAM_ALLIANCE] = 0; m_ArenaTeamIds[TEAM_ALLIANCE] = 0;
m_ArenaTeamIds[TEAM_HORDE] = 0; m_ArenaTeamIds[TEAM_HORDE] = 0;
m_ArenaTeamRatingChanges[TEAM_ALLIANCE] = 0;
m_ArenaTeamRatingChanges[TEAM_HORDE] = 0;
m_ArenaTeamMMR[TEAM_ALLIANCE] = 0; m_ArenaTeamMMR[TEAM_ALLIANCE] = 0;
m_ArenaTeamMMR[TEAM_HORDE] = 0; m_ArenaTeamMMR[TEAM_HORDE] = 0;
@@ -193,11 +193,11 @@ Battleground::Battleground()
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M; StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S; StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set to some default existing values
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; StartMessageIds[BG_STARTING_EVENT_FIRST] = BG_TEXT_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; StartMessageIds[BG_STARTING_EVENT_SECOND] = BG_TEXT_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; StartMessageIds[BG_STARTING_EVENT_THIRD] = BG_TEXT_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; StartMessageIds[BG_STARTING_EVENT_FOURTH] = BG_TEXT_BATTLE_HAS_BEGUN;
// pussywizard: // pussywizard:
m_UpdateTimer = 0; m_UpdateTimer = 0;
@@ -205,6 +205,8 @@ Battleground::Battleground()
Battleground::~Battleground() Battleground::~Battleground()
{ {
LOG_DEBUG("bg.battleground", "> Remove Battleground {} {} {}", GetName(), GetBgTypeID(), GetInstanceID());
_reviveEvents.KillAllEvents(false); _reviveEvents.KillAllEvents(false);
// remove objects and creatures // remove objects and creatures
@@ -229,8 +231,8 @@ Battleground::~Battleground()
m_Map = nullptr; m_Map = nullptr;
} }
for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr) for (auto const& itr : PlayerScores)
delete itr->second; delete itr.second;
} }
void Battleground::Update(uint32 diff) void Battleground::Update(uint32 diff)
@@ -267,8 +269,7 @@ void Battleground::Update(uint32 diff)
{ {
if (GetStartTime() >= 46 * MINUTE * IN_MILLISECONDS) // pussywizard: 1min startup + 45min allowed duration if (GetStartTime() >= 46 * MINUTE * IN_MILLISECONDS) // pussywizard: 1min startup + 45min allowed duration
{ {
UpdateArenaWorldState(); EndBattleground(PVP_TEAM_NEUTRAL);
CheckArenaAfterTimerConditions();
return; return;
} }
} }
@@ -304,19 +305,20 @@ inline void Battleground::_CheckSafePositions(uint32 diff)
return; return;
m_ValidStartPositionTimer += diff; m_ValidStartPositionTimer += diff;
if (m_ValidStartPositionTimer >= CHECK_PLAYER_POSITION_INVERVAL) if (m_ValidStartPositionTimer >= CHECK_PLAYER_POSITION_INVERVAL)
{ {
m_ValidStartPositionTimer = 0; m_ValidStartPositionTimer = 0;
float x, y, z, o; for (auto const& [playerGuid, player] : GetPlayers())
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
{ {
Position pos = itr->second->GetPosition(); Position pos = player->GetPosition();
GetTeamStartLoc(itr->second->GetBgTeamId(), x, y, z, o); Position const* startPos = GetTeamStartPosition(player->GetBgTeamId());
if (pos.GetExactDistSq(x, y, z) > maxDist)
if (pos.GetExactDistSq(startPos) > maxDist)
{ {
LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending {} back to start location (map: {}) (possible exploit)", itr->second->GetName(), GetMapId()); LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending {} back to start location (map: {}) (possible exploit)", player->GetName(), GetMapId());
itr->second->TeleportTo(GetMapId(), x, y, z, o); player->TeleportTo(GetMapId(), startPos->GetPositionX(), startPos->GetPositionY(), startPos->GetPositionZ(), startPos->GetOrientation());
} }
} }
} }
@@ -465,20 +467,26 @@ inline void Battleground::_ProcessJoin(uint32 diff)
StartingEventCloseDoors(); StartingEventCloseDoors();
SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FIRST]); SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FIRST]);
// First start warning - 2 or 1 minute // First start warning - 2 or 1 minute
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL); if (StartMessageIds[BG_STARTING_EVENT_FIRST])
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
} }
// After 1 minute or 30 seconds, warning is signaled // After 1 minute or 30 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2)) else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
{ {
m_Events |= BG_STARTING_EVENT_2; m_Events |= BG_STARTING_EVENT_2;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
if (StartMessageIds[BG_STARTING_EVENT_SECOND])
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
} }
// After 30 or 15 seconds, warning is signaled // After 30 or 15 seconds, warning is signaled
else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3)) else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
{ {
m_Events |= BG_STARTING_EVENT_3; m_Events |= BG_STARTING_EVENT_3;
SendMessageToAll(StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
if (StartMessageIds[BG_STARTING_EVENT_THIRD])
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
if (isArena()) if (isArena())
switch (GetBgTypeID()) switch (GetBgTypeID())
@@ -514,7 +522,9 @@ inline void Battleground::_ProcessJoin(uint32 diff)
StartingEventOpenDoors(); StartingEventOpenDoors();
SendWarningToAll(StartMessageIds[BG_STARTING_EVENT_FOURTH]); if (StartMessageIds[BG_STARTING_EVENT_FOURTH])
SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_FOURTH], CHAT_MSG_BG_SYSTEM_NEUTRAL);
SetStatus(STATUS_IN_PROGRESS); SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FOURTH]); SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FOURTH]);
@@ -556,7 +566,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
for (SpectatorList::const_iterator itr = m_Spectators.begin(); itr != m_Spectators.end(); ++itr) for (SpectatorList::const_iterator itr = m_Spectators.begin(); itr != m_Spectators.end(); ++itr)
ArenaSpectator::HandleResetCommand(*itr); ArenaSpectator::HandleResetCommand(*itr);
CheckArenaWinConditions(); CheckWinConditions();
// pussywizard: arena spectator stuff // pussywizard: arena spectator stuff
if (GetStatus() == STATUS_IN_PROGRESS) if (GetStatus() == STATUS_IN_PROGRESS)
@@ -591,7 +601,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
// Announce BG starting // Announce BG starting
if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE)) if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), std::min(GetMinLevel(), (uint32)80), std::min(GetMaxLevel(), (uint32)80)); sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName().c_str(), std::min(GetMinLevel(), (uint32)80), std::min(GetMaxLevel(), (uint32)80));
sScriptMgr->OnBattlegroundStart(this); sScriptMgr->OnBattlegroundStart(this);
} }
@@ -618,12 +628,16 @@ inline void Battleground::_ProcessLeave(uint32 diff)
} }
} }
void Battleground::SetTeamStartLoc(TeamId teamId, float X, float Y, float Z, float O) void Battleground::SetTeamStartPosition(TeamId teamId, Position const& pos)
{ {
m_TeamStartLocX[teamId] = X; ASSERT(teamId < TEAM_NEUTRAL);
m_TeamStartLocY[teamId] = Y; _startPosition[teamId] = pos;
m_TeamStartLocZ[teamId] = Z; }
m_TeamStartLocO[teamId] = O;
Position const* Battleground::GetTeamStartPosition(TeamId teamId) const
{
ASSERT(teamId < TEAM_NEUTRAL);
return &_startPosition[teamId];
} }
void Battleground::SendPacketToAll(WorldPacket const* packet) void Battleground::SendPacketToAll(WorldPacket const* packet)
@@ -639,6 +653,24 @@ void Battleground::SendPacketToTeam(TeamId teamId, WorldPacket const* packet, Pl
itr->second->GetSession()->SendPacket(packet); itr->second->GetSession()->SendPacket(packet);
} }
void Battleground::SendChatMessage(Creature* source, uint8 textId, WorldObject* target /*= nullptr*/)
{
sCreatureTextMgr->SendChat(source, textId, target);
}
void Battleground::SendBroadcastText(uint32 id, ChatMsg msgType, WorldObject const* target)
{
if (!sObjectMgr->GetBroadcastText(id))
{
LOG_ERROR("bg.battleground", "Battleground::SendBroadcastText: `broadcast_text` (ID: {}) was not found", id);
return;
}
Acore::BroadcastTextBuilder builder(nullptr, msgType, id, GENDER_MALE, target);
Acore::LocalizedPacketDo<Acore::BroadcastTextBuilder> localizer(builder);
BroadcastWorker(localizer);
}
void Battleground::PlaySoundToAll(uint32 soundID) void Battleground::PlaySoundToAll(uint32 soundID)
{ {
WorldPacket data; WorldPacket data;
@@ -728,7 +760,7 @@ void Battleground::UpdateWorldState(uint32 variable, uint32 value)
SendPacketToAll(worldstate.Write()); SendPacketToAll(worldstate.Write());
} }
void Battleground::EndBattleground(TeamId winnerTeamId) void Battleground::EndBattleground(PvPTeamId winnerTeamId)
{ {
// xinef: if this is true, it means that endbattleground is called second time // xinef: if this is true, it means that endbattleground is called second time
// skip to avoid double rating reduce / add // skip to avoid double rating reduce / add
@@ -736,34 +768,22 @@ void Battleground::EndBattleground(TeamId winnerTeamId)
// set as fast as possible // set as fast as possible
if (GetStatus() == STATUS_WAIT_LEAVE) if (GetStatus() == STATUS_WAIT_LEAVE)
return; return;
uint32 startDelay = GetStartDelayTime();
bool bValidArena = isArena() && isRated() && GetStatus() == STATUS_IN_PROGRESS && GetStartTime() >= startDelay + 15000; // pussywizard: only if arena lasted at least 15 secs
SetStatus(STATUS_WAIT_LEAVE); SetStatus(STATUS_WAIT_LEAVE);
ArenaTeam* winnerArenaTeam = nullptr;
ArenaTeam* loserArenaTeam = nullptr;
uint32 loserTeamRating = 0;
uint32 loserMatchmakerRating = 0;
int32 loserChange = 0;
int32 loserMatchmakerChange = 0;
uint32 winnerTeamRating = 0;
uint32 winnerMatchmakerRating = 0;
int32 winnerChange = 0;
int32 winnerMatchmakerChange = 0;
int32 winmsg_id = 0;
SetWinner(winnerTeamId); SetWinner(winnerTeamId);
if (winnerTeamId == TEAM_ALLIANCE) if (winnerTeamId == PVP_TEAM_ALLIANCE)
{ {
winmsg_id = isBattleground() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS; if (isBattleground())
SendBroadcastText(BG_TEXT_ALLIANCE_WINS, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
} }
else if (winnerTeamId == TEAM_HORDE) else if (winnerTeamId == PVP_TEAM_HORDE)
{ {
winmsg_id = isBattleground() ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS; if (isBattleground())
SendBroadcastText(BG_TEXT_HORDE_WINS, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
} }
@@ -782,7 +802,7 @@ void Battleground::EndBattleground(TeamId winnerTeamId)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_BATTLEGROUND); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_BATTLEGROUND);
stmt->SetData(0, battlegroundId); stmt->SetData(0, battlegroundId);
stmt->SetData(1, GetPvPTeamId(GetWinner())); stmt->SetData(1, GetWinner());
stmt->SetData(2, GetUniqueBracketId()); stmt->SetData(2, GetUniqueBracketId());
stmt->SetData(3, GetBgTypeID(true)); stmt->SetData(3, GetBgTypeID(true));
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
@@ -791,151 +811,17 @@ void Battleground::EndBattleground(TeamId winnerTeamId)
//we must set it this way, because end time is sent in packet! //we must set it this way, because end time is sent in packet!
m_EndTime = TIME_TO_AUTOREMOVE; m_EndTime = TIME_TO_AUTOREMOVE;
// arena rating calculation
if (isArena() && isRated())
{
winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winnerTeamId == TEAM_NEUTRAL ? TEAM_HORDE : winnerTeamId));
loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winnerTeamId == TEAM_NEUTRAL ? TEAM_ALLIANCE : GetOtherTeamId(winnerTeamId)));
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
{
if (winnerTeamId != TEAM_NEUTRAL)
{
loserTeamRating = loserArenaTeam->GetRating();
loserMatchmakerRating = GetArenaMatchmakerRating(GetOtherTeamId(winnerTeamId));
winnerTeamRating = winnerArenaTeam->GetRating();
winnerMatchmakerRating = GetArenaMatchmakerRating(winnerTeamId);
winnerMatchmakerChange = bValidArena ? winnerArenaTeam->WonAgainst(winnerMatchmakerRating, loserMatchmakerRating, winnerChange, GetBgMap()) : 0;
loserMatchmakerChange = loserArenaTeam->LostAgainst(loserMatchmakerRating, winnerMatchmakerRating, loserChange, GetBgMap());
sScriptMgr->OnAfterArenaRatingCalculation(this, winnerMatchmakerChange, loserMatchmakerChange, winnerChange, loserChange);
SetArenaMatchmakerRating(winnerTeamId, winnerMatchmakerRating + winnerMatchmakerChange);
SetArenaMatchmakerRating(GetOtherTeamId(winnerTeamId), loserMatchmakerRating + loserMatchmakerChange);
SetArenaTeamRatingChangeForTeam(winnerTeamId, winnerChange);
SetArenaTeamRatingChangeForTeam(GetOtherTeamId(winnerTeamId), loserChange);
// pussywizard: arena logs in database
uint32 fightId = sArenaTeamMgr->GetNextArenaLogId();
uint32 currOnline = (uint32)(sWorld->GetActiveSessionCount());
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_FIGHT);
stmt2->SetData(0, fightId);
stmt2->SetData(1, m_ArenaType);
stmt2->SetData(2, ((GetStartTime() <= startDelay ? 0 : GetStartTime() - startDelay) / 1000));
stmt2->SetData(3, winnerArenaTeam->GetId());
stmt2->SetData(4, loserArenaTeam->GetId());
stmt2->SetData(5, (uint16)winnerTeamRating);
stmt2->SetData(6, (uint16)winnerMatchmakerRating);
stmt2->SetData(7, (int16)winnerChange);
stmt2->SetData(8, (uint16)loserTeamRating);
stmt2->SetData(9, (uint16)loserMatchmakerRating);
stmt2->SetData(10, (int16)loserChange);
stmt2->SetData(11, currOnline);
trans->Append(stmt2);
uint8 memberId = 0;
for (Battleground::ArenaLogEntryDataMap::const_iterator itr = ArenaLogEntries.begin(); itr != ArenaLogEntries.end(); ++itr)
{
stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_MEMBERSTATS);
stmt2->SetData(0, fightId);
stmt2->SetData(1, ++memberId);
stmt2->SetData(2, itr->second.Name);
stmt2->SetData(3, itr->second.Guid);
stmt2->SetData(4, itr->second.ArenaTeamId);
stmt2->SetData(5, itr->second.Acc);
stmt2->SetData(6, itr->second.IP);
stmt2->SetData(7, itr->second.DamageDone);
stmt2->SetData(8, itr->second.HealingDone);
stmt2->SetData(9, itr->second.KillingBlows);
trans->Append(stmt2);
}
CharacterDatabase.CommitTransaction(trans);
}
// Deduct 16 points from each teams arena-rating if there are no winners after 45+2 minutes
else
{
// pussywizard: in case of a draw, the following is always true:
// winnerArenaTeam => TEAM_HORDE, loserArenaTeam => TEAM_ALLIANCE
winnerTeamRating = winnerArenaTeam->GetRating();
winnerMatchmakerRating = GetArenaMatchmakerRating(TEAM_HORDE);
loserTeamRating = loserArenaTeam->GetRating();
loserMatchmakerRating = GetArenaMatchmakerRating(TEAM_ALLIANCE);
winnerMatchmakerChange = 0;
loserMatchmakerChange = 0;
winnerChange = ARENA_TIMELIMIT_POINTS_LOSS;
loserChange = ARENA_TIMELIMIT_POINTS_LOSS;
SetArenaTeamRatingChangeForTeam(TEAM_ALLIANCE, ARENA_TIMELIMIT_POINTS_LOSS);
SetArenaTeamRatingChangeForTeam(TEAM_HORDE, ARENA_TIMELIMIT_POINTS_LOSS);
winnerArenaTeam->FinishGame(ARENA_TIMELIMIT_POINTS_LOSS, GetBgMap());
loserArenaTeam->FinishGame(ARENA_TIMELIMIT_POINTS_LOSS, GetBgMap());
// pussywizard: arena logs in database
uint32 fightId = sArenaTeamMgr->GetNextArenaLogId();
uint32 currOnline = (uint32)(sWorld->GetActiveSessionCount());
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
CharacterDatabasePreparedStatement* stmt3 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_FIGHT);
stmt3->SetData(0, fightId);
stmt3->SetData(1, m_ArenaType);
stmt3->SetData(2, ((GetStartTime() <= startDelay ? 0 : GetStartTime() - startDelay) / 1000));
stmt3->SetData(3, winnerArenaTeam->GetId());
stmt3->SetData(4, loserArenaTeam->GetId());
stmt3->SetData(5, (uint16)winnerTeamRating);
stmt3->SetData(6, (uint16)winnerMatchmakerRating);
stmt3->SetData(7, (int16)winnerChange);
stmt3->SetData(8, (uint16)loserTeamRating);
stmt3->SetData(9, (uint16)loserMatchmakerRating);
stmt3->SetData(10, (int16)loserChange);
stmt3->SetData(11, currOnline);
trans->Append(stmt3);
uint8 memberId = 0;
for (Battleground::ArenaLogEntryDataMap::const_iterator itr = ArenaLogEntries.begin(); itr != ArenaLogEntries.end(); ++itr)
{
stmt3 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_MEMBERSTATS);
stmt3->SetData(0, fightId);
stmt3->SetData(1, ++memberId);
stmt3->SetData(2, itr->second.Name);
stmt3->SetData(3, itr->second.Guid);
stmt3->SetData(4, itr->second.ArenaTeamId);
stmt3->SetData(5, itr->second.Acc);
stmt3->SetData(6, itr->second.IP);
stmt3->SetData(7, itr->second.DamageDone);
stmt3->SetData(8, itr->second.HealingDone);
stmt3->SetData(9, itr->second.KillingBlows);
trans->Append(stmt3);
}
CharacterDatabase.CommitTransaction(trans);
}
}
else
{
SetArenaTeamRatingChangeForTeam(TEAM_ALLIANCE, 0);
SetArenaTeamRatingChangeForTeam(TEAM_HORDE, 0);
}
}
WorldPacket pvpLogData; WorldPacket pvpLogData;
sBattlegroundMgr->BuildPvpLogDataPacket(&pvpLogData, this); BuildPvPLogDataPacket(pvpLogData);
uint8 aliveWinners = GetAlivePlayersCountByTeam(winnerTeamId); for (auto const& [playerGuid, player] : m_Players)
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{ {
Player* player = itr->second;
TeamId bgTeamId = player->GetBgTeamId(); TeamId bgTeamId = player->GetBgTeamId();
// should remove spirit of redemption // should remove spirit of redemption
if (player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) if (player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT); player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
// Last standing - Rated 5v5 arena & be solely alive player
if (bgTeamId == winnerTeamId && isArena() && isRated() && GetArenaType() == ARENA_TYPE_5v5 && aliveWinners == 1 && player->IsAlive() && bValidArena)
player->CastSpell(player, SPELL_THE_LAST_STANDING, true);
if (!player->IsAlive()) if (!player->IsAlive())
{ {
player->ResurrectPlayer(1.0f); player->ResurrectPlayer(1.0f);
@@ -948,38 +834,12 @@ void Battleground::EndBattleground(TeamId winnerTeamId)
player->getHostileRefMgr().deleteReferences(); player->getHostileRefMgr().deleteReferences();
} }
// per player calculation
if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
{
if (bgTeamId == winnerTeamId)
{
if (bValidArena)
{
// update achievement BEFORE personal rating update
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId());
winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange);
}
}
else
{
loserArenaTeam->MemberLost(player, winnerMatchmakerRating, loserMatchmakerChange);
// Arena lost => reset the win_rated_arena having the "no_lose" condition
player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE, 0);
}
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA, GetMapId());
}
uint32 winner_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST); uint32 winner_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST);
uint32 loser_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST); uint32 loser_kills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST);
uint32 winner_arena = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_FIRST); uint32 winner_arena = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_ARENA_FIRST);
// Reward winner team // Reward winner team
if (bgTeamId == winnerTeamId) if (bgTeamId == GetTeamId(winnerTeamId))
{ {
if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetBgTypeID(true))) if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)))
{ {
@@ -1001,7 +861,7 @@ void Battleground::EndBattleground(TeamId winnerTeamId)
UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(loser_kills)); UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(loser_kills));
} }
sScriptMgr->OnBattlegroundEndReward(this, player, winnerTeamId); sScriptMgr->OnBattlegroundEndReward(this, player, GetTeamId(winnerTeamId));
player->ResetAllPowers(); player->ResetAllPowers();
player->CombatStopWithPets(true); player->CombatStopWithPets(true);
@@ -1013,11 +873,11 @@ void Battleground::EndBattleground(TeamId winnerTeamId)
if (isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE)) if (isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE))
{ {
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_PLAYER); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_PLAYER);
BattlegroundScoreMap::const_iterator score = PlayerScores.find(player->GetGUID()); auto const& score = PlayerScores.find(player->GetGUID().GetCounter());
stmt->SetData(0, battlegroundId); stmt->SetData(0, battlegroundId);
stmt->SetData(1, player->GetGUID().GetCounter()); stmt->SetData(1, player->GetGUID().GetCounter());
stmt->SetData(2, bgTeamId == winnerTeamId); stmt->SetData(2, bgTeamId == GetTeamId(winnerTeamId));
stmt->SetData(3, score->second->GetKillingBlows()); stmt->SetData(3, score->second->GetKillingBlows());
stmt->SetData(4, score->second->GetDeaths()); stmt->SetData(4, score->second->GetDeaths());
stmt->SetData(5, score->second->GetHonorableKills()); stmt->SetData(5, score->second->GetHonorableKills());
@@ -1040,21 +900,7 @@ void Battleground::EndBattleground(TeamId winnerTeamId)
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, player->GetMapId()); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, player->GetMapId());
} }
if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam) sScriptMgr->OnBattlegroundEnd(this, GetTeamId(winnerTeamId));
{
// save the stat changes
if (bValidArena) winnerArenaTeam->SaveToDB();
loserArenaTeam->SaveToDB();
// send updated arena team stats to players
// this way all arena team members will get notified, not only the ones who participated in this match
if (bValidArena) winnerArenaTeam->NotifyStatsChanged();
loserArenaTeam->NotifyStatsChanged();
}
if (winmsg_id)
SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL);
sScriptMgr->OnBattlegroundEnd(this, winnerTeamId);
} }
uint32 Battleground::GetBonusHonorFromKill(uint32 kills) const uint32 Battleground::GetBonusHonorFromKill(uint32 kills) const
@@ -1084,7 +930,7 @@ void Battleground::RemovePlayerAtLeave(Player* player)
} }
// delete player score if exists // delete player score if exists
BattlegroundScoreMap::iterator itr2 = PlayerScores.find(player->GetGUID()); auto const& itr2 = PlayerScores.find(player->GetGUID().GetCounter());
if (itr2 != PlayerScores.end()) if (itr2 != PlayerScores.end())
{ {
delete itr2->second; delete itr2->second;
@@ -1115,15 +961,6 @@ void Battleground::RemovePlayerAtLeave(Player* player)
player->ClearAfkReports(); player->ClearAfkReports();
//left a rated match in progress, consider as loser
if (isArena() && isRated() && status == STATUS_IN_PROGRESS && teamId != TEAM_NEUTRAL)
{
ArenaTeam* winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeamId(teamId)));
ArenaTeam* loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(teamId));
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
loserArenaTeam->MemberLost(player, GetArenaMatchmakerRating(GetOtherTeamId(teamId)));
}
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetCurrentBattlegroundQueueSlot(), STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetCurrentBattlegroundQueueSlot(), STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL);
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
@@ -1157,7 +994,7 @@ void Battleground::RemovePlayerAtLeave(Player* player)
// this method is called when creating bg // this method is called when creating bg
void Battleground::Init() void Battleground::Init()
{ {
SetWinner(TEAM_NEUTRAL); SetWinner(PVP_TEAM_NEUTRAL);
SetStatus(STATUS_WAIT_QUEUE); SetStatus(STATUS_WAIT_QUEUE);
SetStartTime(0); SetStartTime(0);
SetEndTime(0); SetEndTime(0);
@@ -1176,10 +1013,14 @@ void Battleground::Init()
m_Players.clear(); m_Players.clear();
for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr) for (auto const& itr : PlayerScores)
delete itr->second; delete itr.second;
PlayerScores.clear(); PlayerScores.clear();
for (auto& itr : _arenaTeamScores)
itr.Reset();
ResetBGSubclass(); ResetBGSubclass();
} }
@@ -1220,27 +1061,12 @@ void Battleground::AddPlayer(Player* player)
// add arena specific auras // add arena specific auras
if (isArena()) if (isArena())
{ {
player->RemoveArenaEnchantments(TEMP_ENCHANTMENT_SLOT);
if (teamId == TEAM_ALLIANCE) // gold
{
if (player->GetTeamId() == TEAM_HORDE)
player->CastSpell(player, SPELL_HORDE_GOLD_FLAG, true);
else
player->CastSpell(player, SPELL_ALLIANCE_GOLD_FLAG, true);
}
else // green
{
if (player->GetTeamId() == TEAM_HORDE)
player->CastSpell(player, SPELL_HORDE_GREEN_FLAG, true);
else
player->CastSpell(player, SPELL_ALLIANCE_GREEN_FLAG, true);
}
// restore pets health before remove // restore pets health before remove
if (Pet* pet = player->GetPet()) if (Pet* pet = player->GetPet())
if (pet->IsAlive()) if (pet->IsAlive())
pet->SetHealth(pet->GetMaxHealth()); pet->SetHealth(pet->GetMaxHealth());
player->RemoveArenaEnchantments(TEMP_ENCHANTMENT_SLOT);
player->DestroyConjuredItems(true); player->DestroyConjuredItems(true);
player->UnsummonPetTemporaryIfAny(); player->UnsummonPetTemporaryIfAny();
@@ -1360,7 +1186,7 @@ bool Battleground::HasFreeSlots() const
{ {
if (GetStatus() != STATUS_WAIT_JOIN && GetStatus() != STATUS_IN_PROGRESS) if (GetStatus() != STATUS_WAIT_JOIN && GetStatus() != STATUS_IN_PROGRESS)
return false; return false;
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i) for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i)
if (GetFreeSlotsForTeam((TeamId)i) > 0) if (GetFreeSlotsForTeam((TeamId)i) > 0)
return true; return true;
return false; return false;
@@ -1388,65 +1214,48 @@ void Battleground::ReadyMarkerClicked(Player* p)
} }
} }
void Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) void Battleground::BuildPvPLogDataPacket(WorldPacket& data)
{ {
//this procedure is called from virtual function implemented in bg subclass uint8 type = (isArena() ? 1 : 0);
BattlegroundScoreMap::const_iterator itr = PlayerScores.find(player->GetGUID());
if (itr == PlayerScores.end()) // player not found...
return;
switch (type) data.Initialize(MSG_PVP_LOG_DATA, 1 + 1 + 4 + 40 * GetPlayerScores()->size());
data << uint8(type); // type (battleground = 0 / arena = 1)
if (type) // arena
{ {
case SCORE_KILLING_BLOWS: // Killing blows for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i)
itr->second->KillingBlows += value; _arenaTeamScores[i].BuildRatingInfoBlock(data);
if (isArena() && isRated())
{ for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i)
ArenaLogEntryDataMap::iterator itr2 = ArenaLogEntries.find(player->GetGUID()); _arenaTeamScores[i].BuildTeamInfoBlock(data);
if (itr2 != ArenaLogEntries.end())
itr2->second.KillingBlows += value;
} }
break;
case SCORE_DEATHS: // Deaths if (GetStatus() == STATUS_WAIT_LEAVE)
itr->second->Deaths += value;
break;
case SCORE_HONORABLE_KILLS: // Honorable kills
itr->second->HonorableKills += value;
break;
case SCORE_BONUS_HONOR: // Honor bonus
// do not add honor in arenas
if (isBattleground())
{ {
// reward honor instantly data << uint8(1); // bg ended
if (doAddHonor) data << uint8(GetWinner()); // who win
}
else
data << uint8(0); // bg not ended
data << uint32(GetPlayerScores()->size());
for (auto const& score : PlayerScores)
score.second->AppendToPacket(data);
}
bool Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
auto const& itr = PlayerScores.find(player->GetGUID().GetCounter());
if (itr == PlayerScores.end()) // player not found...
return false;
if (type == SCORE_BONUS_HONOR && doAddHonor && isBattleground())
player->RewardHonor(nullptr, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false player->RewardHonor(nullptr, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false
else else
itr->second->BonusHonor += value; itr->second->UpdateScore(type, value);
}
break; return true;
// used only in EY, but in MSG_PVP_LOG_DATA opcode
case SCORE_DAMAGE_DONE: // Damage Done
itr->second->DamageDone += value;
if (isArena() && isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
ArenaLogEntryDataMap::iterator itr2 = ArenaLogEntries.find(player->GetGUID());
if (itr2 != ArenaLogEntries.end())
itr2->second.DamageDone += value;
}
break;
case SCORE_HEALING_DONE: // Healing Done
itr->second->HealingDone += value;
if (isArena() && isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
ArenaLogEntryDataMap::iterator itr2 = ArenaLogEntries.find(player->GetGUID());
if (itr2 != ArenaLogEntries.end())
itr2->second.HealingDone += value;
}
break;
default:
LOG_ERROR("bg.battleground", "Battleground::UpdatePlayerScore: unknown score type ({}) for BG (map: {}, instance id: {})!",
type, m_MapId, m_InstanceID);
break;
}
} }
void Battleground::AddPlayerToResurrectQueue(ObjectGuid npc_guid, ObjectGuid player_guid) void Battleground::AddPlayerToResurrectQueue(ObjectGuid npc_guid, ObjectGuid player_guid)
@@ -1920,7 +1729,7 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player)
WorldPacket data; WorldPacket data;
BlockMovement(player); BlockMovement(player);
sBattlegroundMgr->BuildPvpLogDataPacket(&data, this); BuildPvPLogDataPacket(data);
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetCurrentBattlegroundQueueSlot(), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBgTeamId()); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetCurrentBattlegroundQueueSlot(), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBgTeamId());
@@ -1954,31 +1763,6 @@ int32 Battleground::GetObjectType(ObjectGuid guid)
return -1; return -1;
} }
void Battleground::HandleKillUnit(Creature* /*victim*/, Player* /*killer*/)
{
}
void Battleground::CheckArenaAfterTimerConditions()
{
EndBattleground(TEAM_NEUTRAL);
}
void Battleground::CheckArenaWinConditions()
{
if (isArena() && GetStatus() <= STATUS_WAIT_JOIN) // pussywizard
return;
if (!GetAlivePlayersCountByTeam(TEAM_ALLIANCE) && GetPlayersCountByTeam(TEAM_HORDE))
EndBattleground(TEAM_HORDE);
else if (GetPlayersCountByTeam(TEAM_ALLIANCE) && !GetAlivePlayersCountByTeam(TEAM_HORDE))
EndBattleground(TEAM_ALLIANCE);
}
void Battleground::UpdateArenaWorldState()
{
UpdateWorldState(0xe10, GetAlivePlayersCountByTeam(TEAM_HORDE));
UpdateWorldState(0xe11, GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
}
void Battleground::SetBgRaid(TeamId teamId, Group* bg_raid) void Battleground::SetBgRaid(TeamId teamId, Group* bg_raid)
{ {
Group*& old_raid = m_BgRaids[teamId]; Group*& old_raid = m_BgRaids[teamId];
+59 -114
View File
@@ -18,6 +18,7 @@
#ifndef __BATTLEGROUND_H #ifndef __BATTLEGROUND_H
#define __BATTLEGROUND_H #define __BATTLEGROUND_H
#include "ArenaScore.h"
#include "Common.h" #include "Common.h"
#include "DBCEnums.h" #include "DBCEnums.h"
#include "GameObject.h" #include "GameObject.h"
@@ -53,6 +54,17 @@ enum BattlegroundDesertionType
BG_DESERTION_TYPE_INVITE_LOGOUT = 4, // player is invited to join and logs out BG_DESERTION_TYPE_INVITE_LOGOUT = 4, // player is invited to join and logs out
}; };
enum BattlegroundBroadcastTexts
{
BG_TEXT_ALLIANCE_WINS = 10633,
BG_TEXT_HORDE_WINS = 10634,
BG_TEXT_START_TWO_MINUTES = 18193,
BG_TEXT_START_ONE_MINUTE = 18194,
BG_TEXT_START_HALF_MINUTE = 18195,
BG_TEXT_BATTLE_HAS_BEGUN = 18196,
};
enum BattlegroundSounds enum BattlegroundSounds
{ {
SOUND_HORDE_WINS = 8454, SOUND_HORDE_WINS = 8454,
@@ -111,17 +123,12 @@ enum BattlegroundSpells
SPELL_SPIRIT_HEAL = 22012, // Spirit Heal SPELL_SPIRIT_HEAL = 22012, // Spirit Heal
SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual
SPELL_ARENA_PREPARATION = 32727, // use this one, 32728 not correct SPELL_ARENA_PREPARATION = 32727, // use this one, 32728 not correct
SPELL_ALLIANCE_GOLD_FLAG = 32724,
SPELL_ALLIANCE_GREEN_FLAG = 32725,
SPELL_HORDE_GOLD_FLAG = 35774,
SPELL_HORDE_GREEN_FLAG = 35775,
SPELL_PREPARATION = 44521, // Preparation SPELL_PREPARATION = 44521, // Preparation
SPELL_SPIRIT_HEAL_MANA = 44535, // Spirit Heal SPELL_SPIRIT_HEAL_MANA = 44535, // Spirit Heal
SPELL_RECENTLY_DROPPED_FLAG = 42792, // Recently Dropped Flag SPELL_RECENTLY_DROPPED_FLAG = 42792, // Recently Dropped Flag
SPELL_AURA_PLAYER_INACTIVE = 43681, // Inactive SPELL_AURA_PLAYER_INACTIVE = 43681, // Inactive
SPELL_HONORABLE_DEFENDER_25Y = 68652, // +50% honor when standing at a capture point that you control, 25yards radius (added in 3.2) SPELL_HONORABLE_DEFENDER_25Y = 68652, // +50% honor when standing at a capture point that you control, 25yards radius (added in 3.2)
SPELL_HONORABLE_DEFENDER_60Y = 66157, // +50% honor when standing at a capture point that you control, 60yards radius (added in 3.2), probably for 40+ player battlegrounds SPELL_HONORABLE_DEFENDER_60Y = 66157 // +50% honor when standing at a capture point that you control, 60yards radius (added in 3.2), probably for 40+ player battlegrounds
SPELL_THE_LAST_STANDING = 26549, // Arena achievement related
}; };
enum BattlegroundReputations enum BattlegroundReputations
@@ -180,11 +187,6 @@ enum BattlegroundStatus
STATUS_WAIT_LEAVE = 4 // means some faction has won BG and it is ending STATUS_WAIT_LEAVE = 4 // means some faction has won BG and it is ending
}; };
enum BattlegroundTeams
{
BG_TEAMS_COUNT = 2
};
struct BattlegroundObjectInfo struct BattlegroundObjectInfo
{ {
BattlegroundObjectInfo() = default; BattlegroundObjectInfo() = default;
@@ -194,35 +196,7 @@ struct BattlegroundObjectInfo
uint32 spellid{0}; uint32 spellid{0};
}; };
enum ScoreType enum ArenaType : uint8
{
SCORE_KILLING_BLOWS = 1,
SCORE_DEATHS = 2,
SCORE_HONORABLE_KILLS = 3,
SCORE_BONUS_HONOR = 4,
//EY, but in MSG_PVP_LOG_DATA opcode!
SCORE_DAMAGE_DONE = 5,
SCORE_HEALING_DONE = 6,
//WS
SCORE_FLAG_CAPTURES = 7,
SCORE_FLAG_RETURNS = 8,
//AB and IC
SCORE_BASES_ASSAULTED = 9,
SCORE_BASES_DEFENDED = 10,
//AV
SCORE_GRAVEYARDS_ASSAULTED = 11,
SCORE_GRAVEYARDS_DEFENDED = 12,
SCORE_TOWERS_ASSAULTED = 13,
SCORE_TOWERS_DEFENDED = 14,
SCORE_MINES_CAPTURED = 15,
SCORE_LEADERS_KILLED = 16,
SCORE_SECONDARY_OBJECTIVES = 17,
//SOTA
SCORE_DESTROYED_DEMOLISHER = 18,
SCORE_DESTROYED_WALL = 19,
};
enum ArenaType
{ {
ARENA_TYPE_2v2 = 2, ARENA_TYPE_2v2 = 2,
ARENA_TYPE_3v3 = 3, ARENA_TYPE_3v3 = 3,
@@ -251,43 +225,15 @@ enum BattlegroundStartingEventsIds
BG_STARTING_EVENT_THIRD = 2, BG_STARTING_EVENT_THIRD = 2,
BG_STARTING_EVENT_FOURTH = 3 BG_STARTING_EVENT_FOURTH = 3
}; };
#define BG_STARTING_EVENT_COUNT 4
struct BattlegroundScore constexpr auto BG_STARTING_EVENT_COUNT = 4;
{
BattlegroundScore(Player* player) : KillingBlows(0), Deaths(0), HonorableKills(0), BonusHonor(0),
DamageDone(0), HealingDone(0), player(player)
{ }
virtual ~BattlegroundScore() = default; //virtual destructor is used when deleting score from scores map
uint32 KillingBlows;
uint32 Deaths;
uint32 HonorableKills;
uint32 BonusHonor;
uint32 DamageDone;
uint32 HealingDone;
Player* player;
[[nodiscard]] uint32 GetKillingBlows() const { return KillingBlows; }
[[nodiscard]] uint32 GetDeaths() const { return Deaths; }
[[nodiscard]] uint32 GetHonorableKills() const { return HonorableKills; }
[[nodiscard]] uint32 GetBonusHonor() const { return BonusHonor; }
[[nodiscard]] uint32 GetDamageDone() const { return DamageDone; }
[[nodiscard]] uint32 GetHealingDone() const { return HealingDone; }
[[nodiscard]] virtual uint32 GetAttr1() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr2() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr3() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr4() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr5() const { return 0; }
};
class ArenaLogEntryData class ArenaLogEntryData
{ {
public: public:
ArenaLogEntryData() = default; ArenaLogEntryData() = default;
void Fill(const char* name, ObjectGuid::LowType guid, uint32 acc, uint32 arenaTeamId, std::string ip)
void Fill(std::string_view name, ObjectGuid::LowType guid, uint32 acc, uint32 arenaTeamId, std::string ip)
{ {
Name = std::string(name); Name = std::string(name);
Guid = guid; Guid = guid;
@@ -296,11 +242,11 @@ public:
IP = ip; IP = ip;
} }
std::string Name; std::string Name{};
ObjectGuid::LowType Guid{0}; ObjectGuid::LowType Guid{0};
uint32 Acc; uint32 Acc{0};
uint32 ArenaTeamId{0}; uint32 ArenaTeamId{0};
std::string IP; std::string IP{};
uint32 DamageDone{0}; uint32 DamageDone{0};
uint32 HealingDone{0}; uint32 HealingDone{0};
uint32 KillingBlows{0}; uint32 KillingBlows{0};
@@ -344,6 +290,7 @@ public:
{ {
return true; return true;
} }
virtual void Init(); virtual void Init();
virtual void StartingEventCloseDoors() { } virtual void StartingEventCloseDoors() { }
virtual void StartingEventOpenDoors() { } virtual void StartingEventOpenDoors() { }
@@ -357,7 +304,7 @@ public:
/* Battleground */ /* Battleground */
// Get methods: // Get methods:
[[nodiscard]] char const* GetName() const { return m_Name; } [[nodiscard]] std::string GetName() const { return m_Name; }
[[nodiscard]] BattlegroundTypeId GetBgTypeID(bool GetRandom = false) const { return GetRandom ? m_RandomTypeID : m_RealTypeID; } [[nodiscard]] BattlegroundTypeId GetBgTypeID(bool GetRandom = false) const { return GetRandom ? m_RandomTypeID : m_RealTypeID; }
[[nodiscard]] uint32 GetInstanceID() const { return m_InstanceID; } [[nodiscard]] uint32 GetInstanceID() const { return m_InstanceID; }
[[nodiscard]] BattlegroundStatus GetStatus() const { return m_Status; } [[nodiscard]] BattlegroundStatus GetStatus() const { return m_Status; }
@@ -374,14 +321,14 @@ public:
[[nodiscard]] int32 GetStartDelayTime() const { return m_StartDelayTime; } [[nodiscard]] int32 GetStartDelayTime() const { return m_StartDelayTime; }
[[nodiscard]] uint8 GetArenaType() const { return m_ArenaType; } [[nodiscard]] uint8 GetArenaType() const { return m_ArenaType; }
[[nodiscard]] TeamId GetWinner() const { return m_WinnerId; } [[nodiscard]] PvPTeamId GetWinner() const { return m_WinnerId; }
[[nodiscard]] uint32 GetScriptId() const { return ScriptId; } [[nodiscard]] uint32 GetScriptId() const { return ScriptId; }
[[nodiscard]] uint32 GetBonusHonorFromKill(uint32 kills) const; [[nodiscard]] uint32 GetBonusHonorFromKill(uint32 kills) const;
bool IsRandom() { return m_IsRandom; } bool IsRandom() { return m_IsRandom; }
// Set methods: // Set methods:
void SetName(char const* Name) { m_Name = Name; } void SetName(std::string_view name) { m_Name = std::string(name); }
void SetBgTypeID(BattlegroundTypeId TypeID) { m_RealTypeID = TypeID; } void SetBgTypeID(BattlegroundTypeId TypeID) { m_RealTypeID = TypeID; }
void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; } void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; }
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
@@ -394,7 +341,7 @@ public:
void SetRated(bool state) { m_IsRated = state; } void SetRated(bool state) { m_IsRated = state; }
void SetArenaType(uint8 type) { m_ArenaType = type; } void SetArenaType(uint8 type) { m_ArenaType = type; }
void SetArenaorBGType(bool _isArena) { m_IsArena = _isArena; } void SetArenaorBGType(bool _isArena) { m_IsArena = _isArena; }
void SetWinner(TeamId winner) { m_WinnerId = winner; } void SetWinner(PvPTeamId winner) { m_WinnerId = winner; }
void SetScriptId(uint32 scriptId) { ScriptId = scriptId; } void SetScriptId(uint32 scriptId) { ScriptId = scriptId; }
void SetRandom(bool isRandom) { m_IsRandom = isRandom; } void SetRandom(bool isRandom) { m_IsRandom = isRandom; }
@@ -433,12 +380,11 @@ public:
void ReadyMarkerClicked(Player* p); // pussywizard void ReadyMarkerClicked(Player* p); // pussywizard
GuidSet readyMarkerClickedSet; // pussywizard GuidSet readyMarkerClickedSet; // pussywizard
typedef std::map<ObjectGuid, BattlegroundScore*> BattlegroundScoreMap; typedef std::unordered_map<ObjectGuid::LowType, BattlegroundScore*> BattlegroundScoreMap;
typedef std::map<ObjectGuid, ArenaLogEntryData> ArenaLogEntryDataMap;// pussywizard typedef std::unordered_map<ObjectGuid, ArenaLogEntryData> ArenaLogEntryDataMap; // pussywizard
ArenaLogEntryDataMap ArenaLogEntries; // pussywizard ArenaLogEntryDataMap ArenaLogEntries; // pussywizard
[[nodiscard]] BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const { return PlayerScores.begin(); } [[nodiscard]] BattlegroundScoreMap const* GetPlayerScores() const { return &PlayerScores; }
[[nodiscard]] BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const { return PlayerScores.end(); } [[nodiscard]] std::size_t GetPlayerScoresSize() const { return PlayerScores.size(); }
[[nodiscard]] uint32 GetPlayerScoresSize() const { return PlayerScores.size(); }
[[nodiscard]] uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); } [[nodiscard]] uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); }
@@ -462,14 +408,8 @@ public:
[[nodiscard]] BattlegroundMap* GetBgMap() const { ASSERT(m_Map); return m_Map; } [[nodiscard]] BattlegroundMap* GetBgMap() const { ASSERT(m_Map); return m_Map; }
[[nodiscard]] BattlegroundMap* FindBgMap() const { return m_Map; } [[nodiscard]] BattlegroundMap* FindBgMap() const { return m_Map; }
void SetTeamStartLoc(TeamId teamId, float X, float Y, float Z, float O); void SetTeamStartPosition(TeamId teamId, Position const& pos);
void GetTeamStartLoc(TeamId teamId, float& X, float& Y, float& Z, float& O) const Position const* GetTeamStartPosition(TeamId teamId) const;
{
X = m_TeamStartLocX[teamId];
Y = m_TeamStartLocY[teamId];
Z = m_TeamStartLocZ[teamId];
O = m_TeamStartLocO[teamId];
}
void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; } void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; }
[[nodiscard]] float GetStartMaxDist() const { return m_StartMaxDist; } [[nodiscard]] float GetStartMaxDist() const { return m_StartMaxDist; }
@@ -481,6 +421,9 @@ public:
void SendPacketToAll(WorldPacket const* packet); void SendPacketToAll(WorldPacket const* packet);
void YellToAll(Creature* creature, const char* text, uint32 language); void YellToAll(Creature* creature, const char* text, uint32 language);
void SendChatMessage(Creature* source, uint8 textId, WorldObject* target = nullptr);
void SendBroadcastText(uint32 id, ChatMsg msgType, WorldObject const* target = nullptr);
template<class Do> template<class Do>
void BroadcastWorker(Do& _do); void BroadcastWorker(Do& _do);
@@ -493,7 +436,14 @@ public:
void UpdateWorldState(uint32 variable, uint32 value); void UpdateWorldState(uint32 variable, uint32 value);
virtual void EndBattleground(TeamId winnerTeamId); void EndBattleground(PvPTeamId winnerTeamId);
// deprecated, need delete
virtual void EndBattleground(TeamId winnerTeamId)
{
EndBattleground(GetPvPTeamId(winnerTeamId));
}
void BlockMovement(Player* player); void BlockMovement(Player* player);
void SendWarningToAll(uint32 entry, ...); void SendWarningToAll(uint32 entry, ...);
@@ -507,7 +457,8 @@ public:
[[nodiscard]] Group* GetBgRaid(TeamId teamId) const { return m_BgRaids[teamId]; } [[nodiscard]] Group* GetBgRaid(TeamId teamId) const { return m_BgRaids[teamId]; }
void SetBgRaid(TeamId teamId, Group* bg_raid); void SetBgRaid(TeamId teamId, Group* bg_raid);
virtual void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true); void BuildPvPLogDataPacket(WorldPacket& data);
virtual bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
[[nodiscard]] uint32 GetPlayersCountByTeam(TeamId teamId) const { return m_PlayersCount[teamId]; } [[nodiscard]] uint32 GetPlayersCountByTeam(TeamId teamId) const { return m_PlayersCount[teamId]; }
[[nodiscard]] uint32 GetAlivePlayersCountByTeam(TeamId teamId) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases [[nodiscard]] uint32 GetAlivePlayersCountByTeam(TeamId teamId) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
@@ -519,23 +470,20 @@ public:
++m_PlayersCount[teamId]; ++m_PlayersCount[teamId];
} }
virtual void CheckWinConditions() { }
// used for rated arena battles // used for rated arena battles
void SetArenaTeamIdForTeam(TeamId teamId, uint32 ArenaTeamId) { m_ArenaTeamIds[teamId] = ArenaTeamId; } void SetArenaTeamIdForTeam(TeamId teamId, uint32 ArenaTeamId) { m_ArenaTeamIds[teamId] = ArenaTeamId; }
[[nodiscard]] uint32 GetArenaTeamIdForTeam(TeamId teamId) const { return m_ArenaTeamIds[teamId]; } [[nodiscard]] uint32 GetArenaTeamIdForTeam(TeamId teamId) const { return m_ArenaTeamIds[teamId]; }
void SetArenaTeamRatingChangeForTeam(TeamId teamId, int32 RatingChange) { m_ArenaTeamRatingChanges[teamId] = RatingChange; }
[[nodiscard]] int32 GetArenaTeamRatingChangeForTeam(TeamId teamId) const { return m_ArenaTeamRatingChanges[teamId]; }
void SetArenaMatchmakerRating(TeamId teamId, uint32 MMR) { m_ArenaTeamMMR[teamId] = MMR; } void SetArenaMatchmakerRating(TeamId teamId, uint32 MMR) { m_ArenaTeamMMR[teamId] = MMR; }
[[nodiscard]] uint32 GetArenaMatchmakerRating(TeamId teamId) const { return m_ArenaTeamMMR[teamId]; } [[nodiscard]] uint32 GetArenaMatchmakerRating(TeamId teamId) const { return m_ArenaTeamMMR[teamId]; }
void CheckArenaAfterTimerConditions();
void CheckArenaWinConditions();
virtual void UpdateArenaWorldState();
// Triggers handle // Triggers handle
// must be implemented in BG subclass // must be implemented in BG subclass
virtual void HandleAreaTrigger(Player* /*player*/, uint32 /*trigger*/) {} virtual void HandleAreaTrigger(Player* /*player*/, uint32 /*trigger*/) {}
// must be implemented in BG subclass if need AND call base class generic code // must be implemented in BG subclass if need AND call base class generic code
virtual void HandleKillPlayer(Player* player, Player* killer); virtual void HandleKillPlayer(Player* player, Player* killer);
virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/); virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/) { }
// Battleground events // Battleground events
virtual void EventPlayerDroppedFlag(Player* /*player*/) {} virtual void EventPlayerDroppedFlag(Player* /*player*/) {}
@@ -555,7 +503,7 @@ public:
void AddOrSetPlayerToCorrectBgGroup(Player* player, TeamId teamId); void AddOrSetPlayerToCorrectBgGroup(Player* player, TeamId teamId);
void RemovePlayerAtLeave(Player* player); virtual void RemovePlayerAtLeave(Player* player);
// can be extended in in BG subclass // can be extended in in BG subclass
void HandleTriggerBuff(GameObject* gameObject); void HandleTriggerBuff(GameObject* gameObject);
@@ -663,7 +611,9 @@ protected:
bool m_IsRandom; bool m_IsRandom;
BGHonorMode m_HonorMode; BGHonorMode m_HonorMode;
int32 m_TeamScores[BG_TEAMS_COUNT]; int32 m_TeamScores[PVP_TEAMS_COUNT];
ArenaTeamScore _arenaTeamScores[PVP_TEAMS_COUNT];
// pussywizard: // pussywizard:
uint32 m_UpdateTimer; uint32 m_UpdateTimer;
@@ -685,12 +635,12 @@ private:
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
bool m_IsArena; bool m_IsArena;
TeamId m_WinnerId; PvPTeamId m_WinnerId;
int32 m_StartDelayTime; int32 m_StartDelayTime;
bool m_IsRated; // is this battle rated? bool m_IsRated; // is this battle rated?
bool m_PrematureCountDown; bool m_PrematureCountDown;
uint32 m_PrematureCountDownTimer; uint32 m_PrematureCountDownTimer;
char const* m_Name; std::string m_Name{};
/* Pre- and post-update hooks */ /* Pre- and post-update hooks */
@@ -729,22 +679,20 @@ private:
// Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction // Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction
// Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG // Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG
// Invited players counters // Invited players counters
uint32 m_BgInvitedPlayers[BG_TEAMS_COUNT]; uint32 m_BgInvitedPlayers[PVP_TEAMS_COUNT];
// Raid Group // Raid Group
Group* m_BgRaids[BG_TEAMS_COUNT]; // 0 - alliance, 1 - horde Group* m_BgRaids[PVP_TEAMS_COUNT]; // 0 - alliance, 1 - horde
SpectatorList m_Spectators; SpectatorList m_Spectators;
ToBeTeleportedMap m_ToBeTeleported; ToBeTeleportedMap m_ToBeTeleported;
// Players count by team // Players count by team
uint32 m_PlayersCount[BG_TEAMS_COUNT]; uint32 m_PlayersCount[PVP_TEAMS_COUNT];
// Arena team ids by team // Arena team ids by team
uint32 m_ArenaTeamIds[BG_TEAMS_COUNT]; uint32 m_ArenaTeamIds[PVP_TEAMS_COUNT];
uint32 m_ArenaTeamMMR[PVP_TEAMS_COUNT];
int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT];
uint32 m_ArenaTeamMMR[BG_TEAMS_COUNT];
// Limits // Limits
uint32 m_LevelMin; uint32 m_LevelMin;
@@ -755,11 +703,8 @@ private:
// Start location // Start location
uint32 m_MapId; uint32 m_MapId;
BattlegroundMap* m_Map; BattlegroundMap* m_Map;
float m_TeamStartLocX[BG_TEAMS_COUNT];
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];
float m_TeamStartLocO[BG_TEAMS_COUNT];
float m_StartMaxDist; float m_StartMaxDist;
std::array<Position, PVP_TEAMS_COUNT> _startPosition;
uint32 ScriptId; uint32 ScriptId;
}; };
#endif #endif
+20 -253
View File
@@ -204,179 +204,6 @@ void BattlegroundMgr::BuildBattlegroundStatusPacket(WorldPacket* data, Battlegro
} }
} }
void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg)
{
uint8 type = (bg->isArena() ? 1 : 0);
data->Initialize(MSG_PVP_LOG_DATA, (1 + 1 + 4 + 40 * bg->GetPlayerScoresSize()));
*data << uint8(type); // type (battleground=0/arena=1)
if (type) // arena
{
// it seems this must be according to BG_WINNER_A/H and _NOT_ TEAM_A/H
for (TeamId iTeamId = TEAM_ALLIANCE; iTeamId <= TEAM_HORDE; iTeamId = TeamId(iTeamId + 1))
{
// Xinef: oryginally this was looping in reverse order, loop order was changed so we have to change checked teamId
int32 rating_change = bg->GetArenaTeamRatingChangeForTeam(Battleground::GetOtherTeamId(iTeamId));
uint32 pointsLost = rating_change < 0 ? -rating_change : 0;
uint32 pointsGained = rating_change > 0 ? rating_change : 0;
uint32 MatchmakerRating = bg->GetArenaMatchmakerRating(Battleground::GetOtherTeamId(iTeamId));
*data << uint32(pointsLost); // Rating Lost
*data << uint32(pointsGained); // Rating gained
*data << uint32(MatchmakerRating); // Matchmaking Value
}
for (TeamId iTeamId = TEAM_ALLIANCE; iTeamId <= TEAM_HORDE; iTeamId = TeamId(iTeamId + 1))
{
if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(bg->GetArenaTeamIdForTeam(Battleground::GetOtherTeamId(iTeamId))))
* data << at->GetName();
else
*data << uint8(0);
}
}
if (bg->GetStatus() != STATUS_WAIT_LEAVE)
*data << uint8(0); // bg not ended
else
{
*data << uint8(1); // bg ended
*data << uint8(GetPvPTeamId(bg->GetWinner())); // who win
}
size_t wpos = data->wpos();
uint32 scoreCount = 0;
*data << uint32(scoreCount); // placeholder
Battleground::BattlegroundScoreMap::const_iterator itr2 = bg->GetPlayerScoresBegin();
for (Battleground::BattlegroundScoreMap::const_iterator itr = itr2; itr != bg->GetPlayerScoresEnd();)
{
itr2 = itr++;
if (!bg->IsPlayerInBattleground(itr2->first))
{
LOG_ERROR("bg.battleground", "Player {} has scoreboard entry for battleground {} but is not in battleground!", itr->first.ToString(), bg->GetBgTypeID());
continue;
}
*data << itr2->first;
*data << uint32(itr2->second->KillingBlows);
if (type == 0)
{
*data << uint32(itr2->second->HonorableKills);
*data << uint32(itr2->second->Deaths);
*data << uint32(itr2->second->BonusHonor);
}
else
{
*data << uint8(itr2->second->player->GetBgTeamId() == TEAM_ALLIANCE ? 1 : 0); // green or yellow
}
*data << uint32(itr2->second->DamageDone); // damage done
*data << uint32(itr2->second->HealingDone); // healing done
BattlegroundTypeId bgTypeId = bg->GetBgTypeID();
switch (bgTypeId) // battleground specific things
{
case BATTLEGROUND_RB:
switch (bg->GetMapId())
{
case 489:
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundWGScore*)itr2->second)->FlagCaptures); // flag captures
*data << uint32(((BattlegroundWGScore*)itr2->second)->FlagReturns); // flag returns
break;
case 566:
*data << uint32(0x00000001); // count of next fields
*data << uint32(((BattlegroundEYScore*)itr2->second)->FlagCaptures); // flag captures
break;
case 529:
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundABScore*)itr2->second)->BasesAssaulted); // bases asssulted
*data << uint32(((BattlegroundABScore*)itr2->second)->BasesDefended); // bases defended
break;
case 30:
*data << uint32(0x00000005); // count of next fields
*data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsAssaulted); // GraveyardsAssaulted
*data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsDefended); // GraveyardsDefended
*data << uint32(((BattlegroundAVScore*)itr2->second)->TowersAssaulted); // TowersAssaulted
*data << uint32(((BattlegroundAVScore*)itr2->second)->TowersDefended); // TowersDefended
*data << uint32(((BattlegroundAVScore*)itr2->second)->MinesCaptured); // MinesCaptured
break;
case 607:
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundSAScore*)itr2->second)->demolishers_destroyed);
*data << uint32(((BattlegroundSAScore*)itr2->second)->gates_destroyed);
break;
case 628: // IC
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundICScore*)itr2->second)->BasesAssaulted); // bases asssulted
*data << uint32(((BattlegroundICScore*)itr2->second)->BasesDefended); // bases defended
[[fallthrough]]; // TODO: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
default:
if (BattlegroundMgr::getBgFromMap.find(bg->GetMapId()) != BattlegroundMgr::getBgFromMap.end())
BattlegroundMgr::getBgFromMap[bg->GetMapId()](data, itr2);
else
*data << uint32(0);
break;
}
break;
case BATTLEGROUND_AV:
*data << uint32(0x00000005); // count of next fields
*data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsAssaulted); // GraveyardsAssaulted
*data << uint32(((BattlegroundAVScore*)itr2->second)->GraveyardsDefended); // GraveyardsDefended
*data << uint32(((BattlegroundAVScore*)itr2->second)->TowersAssaulted); // TowersAssaulted
*data << uint32(((BattlegroundAVScore*)itr2->second)->TowersDefended); // TowersDefended
*data << uint32(((BattlegroundAVScore*)itr2->second)->MinesCaptured); // MinesCaptured
break;
case BATTLEGROUND_WS:
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundWGScore*)itr2->second)->FlagCaptures); // flag captures
*data << uint32(((BattlegroundWGScore*)itr2->second)->FlagReturns); // flag returns
break;
case BATTLEGROUND_AB:
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundABScore*)itr2->second)->BasesAssaulted); // bases asssulted
*data << uint32(((BattlegroundABScore*)itr2->second)->BasesDefended); // bases defended
break;
case BATTLEGROUND_EY:
*data << uint32(0x00000001); // count of next fields
*data << uint32(((BattlegroundEYScore*)itr2->second)->FlagCaptures); // flag captures
break;
case BATTLEGROUND_SA:
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundSAScore*)itr2->second)->demolishers_destroyed);
*data << uint32(((BattlegroundSAScore*)itr2->second)->gates_destroyed);
break;
case BATTLEGROUND_IC:
*data << uint32(0x00000002); // count of next fields
*data << uint32(((BattlegroundICScore*)itr2->second)->BasesAssaulted); // bases assaulted
*data << uint32(((BattlegroundICScore*)itr2->second)->BasesDefended); // bases defended
break;
case BATTLEGROUND_NA:
case BATTLEGROUND_BE:
case BATTLEGROUND_AA:
case BATTLEGROUND_RL:
case BATTLEGROUND_DS:
case BATTLEGROUND_RV:
*data << uint32(0);
break;
default:
if (BattlegroundMgr::getBgFromTypeID.find(bgTypeId) != BattlegroundMgr::getBgFromTypeID.end())
BattlegroundMgr::getBgFromTypeID[bgTypeId](data, itr2, bg);
else
*data << uint32(0);
break;
}
// should never happen
if (++scoreCount >= bg->GetMaxPlayersPerTeam() * 2 && itr != bg->GetPlayerScoresEnd())
{
LOG_INFO("misc", "Battleground {} scoreboard has more entries ({}) than allowed players in this bg ({})", bgTypeId, bg->GetPlayerScoresSize(), bg->GetMaxPlayersPerTeam() * 2);
break;
}
}
data->put(wpos, scoreCount);
}
void BattlegroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result) void BattlegroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result)
{ {
data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
@@ -495,8 +322,8 @@ bool BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data)
bg->SetMinPlayersPerTeam(data.MinPlayersPerTeam); bg->SetMinPlayersPerTeam(data.MinPlayersPerTeam);
bg->SetMaxPlayersPerTeam(data.MaxPlayersPerTeam); bg->SetMaxPlayersPerTeam(data.MaxPlayersPerTeam);
bg->SetName(data.BattlegroundName); bg->SetName(data.BattlegroundName);
bg->SetTeamStartLoc(TEAM_ALLIANCE, data.Team1StartLocX, data.Team1StartLocY, data.Team1StartLocZ, data.Team1StartLocO); bg->SetTeamStartPosition(TEAM_ALLIANCE, data.StartLocation[TEAM_ALLIANCE]);
bg->SetTeamStartLoc(TEAM_HORDE, data.Team2StartLocX, data.Team2StartLocY, data.Team2StartLocZ, data.Team2StartLocO); bg->SetTeamStartPosition(TEAM_HORDE, data.StartLocation[TEAM_HORDE]);
bg->SetStartMaxDist(data.StartMaxDist); bg->SetStartMaxDist(data.StartMaxDist);
bg->SetLevelRange(data.LevelMin, data.LevelMax); bg->SetLevelRange(data.LevelMin, data.LevelMax);
bg->SetScriptId(data.scriptId); bg->SetScriptId(data.scriptId);
@@ -570,44 +397,27 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
continue; continue;
} }
if (data.bgTypeId == BATTLEGROUND_AA || data.bgTypeId == BATTLEGROUND_RB) if (data.bgTypeId != BATTLEGROUND_AA && data.bgTypeId != BATTLEGROUND_RB)
{
data.Team1StartLocX = 0;
data.Team1StartLocY = 0;
data.Team1StartLocZ = 0;
data.Team1StartLocO = fields[6].Get<float>();
data.Team2StartLocX = 0;
data.Team2StartLocY = 0;
data.Team2StartLocZ = 0;
data.Team2StartLocO = fields[8].Get<float>();
}
else
{ {
uint32 startId = fields[5].Get<uint32>(); uint32 startId = fields[5].Get<uint32>();
if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId)) if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId))
{ {
data.Team1StartLocX = start->x; data.StartLocation[TEAM_ALLIANCE].Relocate(start->x, start->y, start->z, fields[6].Get<float>());
data.Team1StartLocY = start->y;
data.Team1StartLocZ = start->z;
data.Team1StartLocO = fields[6].Get<float>();
} }
else else
{ {
LOG_ERROR("bg.battleground", "Table `battleground_template` for id {} have non-existed `game_graveyard` table id {} in field `AllianceStartLoc`. BG not created.", data.bgTypeId, startId); LOG_ERROR("sql.sql", "Table `battleground_template` for id %u contains a non-existing WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.", data.bgTypeId, startId);
continue; continue;
} }
startId = fields[7].Get<uint32>(); startId = fields[7].Get<uint32>();
if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId)) if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId))
{ {
data.Team2StartLocX = start->x; data.StartLocation[TEAM_HORDE].Relocate(start->x, start->y, start->z, fields[8].Get<float>());
data.Team2StartLocY = start->y;
data.Team2StartLocZ = start->z;
data.Team2StartLocO = fields[8].Get<float>();
} }
else else
{ {
LOG_ERROR("bg.battleground", "Table `battleground_template` for id {} have non-existed `game_graveyard` table id {} in field `HordeStartLoc`. BG not created.", data.bgTypeId, startId); LOG_ERROR("sql.sql", "Table `battleground_template` for id %u contains a non-existing WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.", data.bgTypeId, startId);
continue; continue;
} }
} }
@@ -708,13 +518,19 @@ void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid
} }
} }
void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId /*bgTypeId*/) void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId)
{ {
if (Battleground* bg = GetBattleground(instanceId)) if (Battleground* bg = GetBattleground(instanceId))
{ {
float x, y, z, o; uint32 mapid = bg->GetMapId();
bg->GetTeamStartLoc(player->GetBgTeamId(), x, y, z, o); Position const* pos = bg->GetTeamStartPosition(player->GetBgTeamId());
player->TeleportTo(bg->GetMapId(), x, y, z, o);
LOG_DEBUG("bg.battleground", "BattlegroundMgr::SendToBattleground: Sending {} to map {}, {} (bgType {})", player->GetName(), mapid, pos->ToString(), bgTypeId);
player->TeleportTo(mapid, pos->GetPositionX(), pos->GetPositionY(), pos->GetPositionZ(), pos->GetOrientation());
}
else
{
LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Instance {} (bgType {}) not found while trying to teleport player {}", instanceId, bgTypeId, player->GetName());
} }
} }
@@ -999,60 +815,11 @@ void BattlegroundMgr::RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 ins
m_Battlegrounds.erase(instanceId); m_Battlegrounds.erase(instanceId);
} }
void BattlegroundMgr::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId) void BattlegroundMgr::DoForAllBattlegrounds(std::function<void(Battleground*)> const& worker)
{ {
if (ginfo->IsInvitedToBGInstanceGUID) for (auto const& [_, bg] : m_Battlegrounds)
return;
// set side if needed
if (teamId != TEAM_NEUTRAL)
ginfo->teamId = teamId;
// set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(ginfo->BgTypeId, ginfo->ArenaType);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
// set ArenaTeamId for rated matches
if (bg->isArena() && bg->isRated())
bg->SetArenaTeamIdForTeam(ginfo->teamId, ginfo->ArenaTeamId);
ginfo->RemoveInviteTime = GameTime::GetGameTimeMS().count() + INVITE_ACCEPT_WAIT_TIME;
// loop through the players
for (auto& itr : ginfo->Players)
{ {
// get the player worker(bg);
Player* player = ObjectAccessor::FindConnectedPlayer(itr);
if (!player)
continue;
// update average wait time
bgQueue.PlayerInvitedToBGUpdateAverageWaitTime(ginfo);
// increase invited counter for each invited player
bg->IncreaseInvitedCount(ginfo->teamId);
// create remind invite events
BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, ginfo->BgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime);
bgQueue.AddEvent(inviteEvent, INVITATION_REMIND_TIME);
// create automatic remove events
BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgQueueTypeId, ginfo->RemoveInviteTime);
bgQueue.AddEvent(removeEvent, INVITE_ACCEPT_WAIT_TIME);
// Check queueSlot
uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
ASSERT(queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES);
// send status packet
WorldPacket data;
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0, ginfo->ArenaType, TEAM_NEUTRAL, bg->isRated(), ginfo->BgTypeId);
player->GetSession()->SendPacket(&data);
// pussywizard:
if (bg->isArena() && bg->isRated())
bg->ArenaLogEntries[player->GetGUID()].Fill(player->GetName().c_str(), player->GetGUID().GetCounter(), player->GetSession()->GetAccountId(), ginfo->ArenaTeamId, player->GetSession()->GetRemoteAddress());
} }
} }
@@ -24,6 +24,7 @@
#include "CreatureAIImpl.h" #include "CreatureAIImpl.h"
#include "DBCEnums.h" #include "DBCEnums.h"
#include <unordered_map> #include <unordered_map>
#include <functional>
typedef std::map<uint32, Battleground*> BattlegroundContainer; typedef std::map<uint32, Battleground*> BattlegroundContainer;
typedef std::unordered_map<uint32, BattlegroundTypeId> BattleMastersMap; typedef std::unordered_map<uint32, BattlegroundTypeId> BattleMastersMap;
@@ -42,15 +43,8 @@ struct CreateBattlegroundData
uint32 LevelMax; uint32 LevelMax;
char const* BattlegroundName; char const* BattlegroundName;
uint32 MapID; uint32 MapID;
float Team1StartLocX;
float Team1StartLocY;
float Team1StartLocZ;
float Team1StartLocO;
float Team2StartLocX;
float Team2StartLocY;
float Team2StartLocZ;
float Team2StartLocO;
float StartMaxDist; float StartMaxDist;
std::array<Position, PVP_TEAMS_COUNT> StartLocation;
uint32 scriptId; uint32 scriptId;
uint8 Weight; uint8 Weight;
}; };
@@ -73,7 +67,6 @@ public:
void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, ObjectGuid guid); void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, ObjectGuid guid);
void BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere); void BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere);
void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result); void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result);
void BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg);
void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType, TeamId teamId, bool isRated = false, BattlegroundTypeId forceBgTypeId = BATTLEGROUND_TYPE_NONE); void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType, TeamId teamId, bool isRated = false, BattlegroundTypeId forceBgTypeId = BATTLEGROUND_TYPE_NONE);
void BuildPlaySoundPacket(WorldPacket* data, uint32 soundid); void BuildPlaySoundPacket(WorldPacket* data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid); void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid);
@@ -96,8 +89,6 @@ public:
void ScheduleArenaQueueUpdate(uint32 arenaRatedTeamId, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id); void ScheduleArenaQueueUpdate(uint32 arenaRatedTeamId, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id);
uint32 GetPrematureFinishTime() const; uint32 GetPrematureFinishTime() const;
static void InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId);
void ToggleArenaTesting(); void ToggleArenaTesting();
void ToggleTesting(); void ToggleTesting();
@@ -138,6 +129,8 @@ public:
static std::unordered_map<uint32, BattlegroundQueueTypeId> ArenaTypeToQueue; // ArenaType -> BattlegroundQueueTypeId static std::unordered_map<uint32, BattlegroundQueueTypeId> ArenaTypeToQueue; // ArenaType -> BattlegroundQueueTypeId
static std::unordered_map<uint32, ArenaType> QueueToArenaType; // BattlegroundQueueTypeId -> ArenaType static std::unordered_map<uint32, ArenaType> QueueToArenaType; // BattlegroundQueueTypeId -> ArenaType
void DoForAllBattlegrounds(std::function<void(Battleground*)> const& worker);
private: private:
bool CreateBattleground(CreateBattlegroundData& data); bool CreateBattleground(CreateBattlegroundData& data);
uint32 GetNextClientVisibleInstanceId(); uint32 GetNextClientVisibleInstanceId();
@@ -37,7 +37,7 @@
BattlegroundQueue::BattlegroundQueue() : m_bgTypeId(BATTLEGROUND_TYPE_NONE), m_arenaType(ArenaType(0)) BattlegroundQueue::BattlegroundQueue() : m_bgTypeId(BATTLEGROUND_TYPE_NONE), m_arenaType(ArenaType(0))
{ {
for (uint32 i = 0; i < BG_TEAMS_COUNT; ++i) for (uint32 i = 0; i < PVP_TEAMS_COUNT; ++i)
{ {
for (uint32 j = 0; j < MAX_BATTLEGROUND_BRACKETS; ++j) for (uint32 j = 0; j < MAX_BATTLEGROUND_BRACKETS; ++j)
{ {
@@ -87,7 +87,7 @@ bool BattlegroundQueue::SelectionPool::KickGroup(const uint32 size)
// find last group with proper size or largest // find last group with proper size or largest
bool foundProper = false; bool foundProper = false;
auto groupToKick = SelectedGroups.begin(); auto groupToKick = SelectedGroups.begin();
for (auto itr = groupToKick; itr != SelectedGroups.end(); ++itr) for (auto& itr = groupToKick; itr != SelectedGroups.end(); ++itr)
{ {
// if proper size - overwrite to kick last one // if proper size - overwrite to kick last one
if (std::abs(int32((*itr)->Players.size()) - (int32)size) <= 1) if (std::abs(int32((*itr)->Players.size()) - (int32)size) <= 1)
@@ -154,7 +154,7 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, PvPDiffi
uint32 index = 0; uint32 index = 0;
if (!isRated && !isPremade) if (!isRated && !isPremade)
index += BG_TEAMS_COUNT; index += PVP_TEAMS_COUNT;
if (ginfo->teamId == TEAM_HORDE) if (ginfo->teamId == TEAM_HORDE)
index++; index++;
@@ -453,88 +453,6 @@ void BattlegroundQueue::FillPlayersToBG(Battleground* bg, const int32 aliFree, c
} }
} }
void BattlegroundQueue::FillPlayersToBGWithSpecific(Battleground* bg, const int32 aliFree, const int32 hordeFree, BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId)
{
if (!sScriptMgr->CanFillPlayersToBGWithSpecific(this, bg, aliFree, hordeFree, thisBracketId, specificQueue, specificBracketId))
return;
// clear selection pools
m_SelectionPools[TEAM_ALLIANCE].Init();
m_SelectionPools[TEAM_HORDE].Init();
// quick check if nothing we can do:
if (!sBattlegroundMgr->isTesting())
if ((m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_ALLIANCE].empty() && specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_ALLIANCE].empty()) ||
(m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_HORDE].empty() && specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_HORDE].empty()))
return;
// copy groups from both queues to new joined container
GroupsQueueType m_QueuedBoth[BG_TEAMS_COUNT];
m_QueuedBoth[TEAM_ALLIANCE].insert(m_QueuedBoth[TEAM_ALLIANCE].end(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_ALLIANCE].begin(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_ALLIANCE].end());
m_QueuedBoth[TEAM_ALLIANCE].insert(m_QueuedBoth[TEAM_ALLIANCE].end(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_ALLIANCE].begin(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_ALLIANCE].end());
m_QueuedBoth[TEAM_HORDE].insert(m_QueuedBoth[TEAM_HORDE].end(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_HORDE].begin(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_HORDE].end());
m_QueuedBoth[TEAM_HORDE].insert(m_QueuedBoth[TEAM_HORDE].end(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_HORDE].begin(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_HORDE].end());
// ally: at first fill as much as possible
auto Ali_itr = m_QueuedBoth[TEAM_ALLIANCE].begin();
for (; Ali_itr != m_QueuedBoth[TEAM_ALLIANCE].end() && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); ++Ali_itr);
// horde: at first fill as much as possible
auto Horde_itr = m_QueuedBoth[TEAM_HORDE].begin();
for (; Horde_itr != m_QueuedBoth[TEAM_HORDE].end() && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); ++Horde_itr);
// calculate free space after adding
int32 aliDiff = aliFree - int32(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
int32 hordeDiff = hordeFree - int32(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
int32 invType = sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE);
int32 invDiff = 0;
// check balance configuration and set the max difference between teams
switch (invType)
{
case BG_QUEUE_INVITATION_TYPE_NO_BALANCE:
return;
case BG_QUEUE_INVITATION_TYPE_BALANCED:
invDiff = 1;
break;
case BG_QUEUE_INVITATION_TYPE_EVEN:
break;
default:
return;
}
// if free space differs too much, ballance
while (std::abs(aliDiff - hordeDiff) > invDiff && (m_SelectionPools[TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() > 0))
{
// if results in more alliance players than horde:
if (aliDiff < hordeDiff)
{
// no more alliance in pool, invite whatever we can from horde
if (!m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
break;
// kick alliance, returns true if kicked more than needed, so then try to fill up
if (m_SelectionPools[TEAM_ALLIANCE].KickGroup(hordeDiff - aliDiff))
for (; Ali_itr != m_QueuedBoth[TEAM_ALLIANCE].end() && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree >= hordeDiff ? aliFree - hordeDiff : 0); ++Ali_itr);
}
else // if results in more horde players than alliance:
{
// no more horde in pool, invite whatever we can from alliance
if (!m_SelectionPools[TEAM_HORDE].GetPlayerCount())
break;
// kick horde, returns true if kicked more than needed, so then try to fill up
if (m_SelectionPools[TEAM_HORDE].KickGroup(aliDiff - hordeDiff))
for (; Horde_itr != m_QueuedBoth[TEAM_HORDE].end() && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree >= aliDiff ? hordeFree - aliDiff : 0); ++Horde_itr);
}
// recalculate free space after adding
aliDiff = aliFree - static_cast<int32>(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
hordeDiff = hordeFree - static_cast<int32>(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
}
}
// this method checks if premade versus premade battleground is possible // this method checks if premade versus premade battleground is possible
// then after 30 mins (default) in queue it moves premade group to normal queue // then after 30 mins (default) in queue it moves premade group to normal queue
bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam) bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam)
@@ -573,7 +491,7 @@ bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint
uint32 premade_time = sWorld->getIntConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH); uint32 premade_time = sWorld->getIntConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
uint32 time_before = GameTime::GetGameTimeMS().count() >= premade_time ? GameTime::GetGameTimeMS().count() - premade_time : 0; uint32 time_before = GameTime::GetGameTimeMS().count() >= premade_time ? GameTime::GetGameTimeMS().count() - premade_time : 0;
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty()) if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty())
for (auto itr = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].end(); ) for (auto itr = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].end(); )
{ {
@@ -624,7 +542,7 @@ bool BattlegroundQueue::CheckNormalMatch(Battleground* bgTemplate, BattlegroundB
// this method will check if we can invite players to same faction skirmish match // this method will check if we can invite players to same faction skirmish match
bool BattlegroundQueue::CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam) bool BattlegroundQueue::CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam)
{ {
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
if (!m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].empty()) if (!m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].empty())
{ {
// clear selection pools // clear selection pools
@@ -633,7 +551,7 @@ bool BattlegroundQueue::CheckSkirmishForSameFaction(BattlegroundBracketId bracke
// fill one queue to both selection pools // fill one queue to both selection pools
for (auto itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr) for (auto itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr)
for (uint32 j = 0; j < BG_TEAMS_COUNT; j++) // try to add this group to both pools for (uint32 j = 0; j < PVP_TEAMS_COUNT; j++) // try to add this group to both pools
if (m_SelectionPools[TEAM_ALLIANCE + j].GetPlayerCount() < minPlayersPerTeam) // if this pool is not full if (m_SelectionPools[TEAM_ALLIANCE + j].GetPlayerCount() < minPlayersPerTeam) // if this pool is not full
if (m_SelectionPools[TEAM_ALLIANCE + j].AddGroup((*itr), minPlayersPerTeam)) // successfully added if (m_SelectionPools[TEAM_ALLIANCE + j].AddGroup((*itr), minPlayersPerTeam)) // successfully added
{ {
@@ -676,9 +594,6 @@ void BattlegroundQueue::UpdateEvents(uint32 diff)
m_events.Update(diff); m_events.Update(diff);
} }
struct BgEmptinessComp { bool operator()(Battleground* const& bg1, Battleground* const& bg2) const { return ((float)bg1->GetMaxFreeSlots() / (float)bg1->GetMaxPlayersPerTeam()) > ((float)bg2->GetMaxFreeSlots() / (float)bg2->GetMaxPlayersPerTeam()); } };
typedef std::set<Battleground*, BgEmptinessComp> BattlegroundNeedSet;
void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId) void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId)
{ {
// if no players in queue - do nothing // if no players in queue - do nothing
@@ -696,28 +611,35 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
// battlegrounds with free slots should be populated first using players in queue // battlegrounds with free slots should be populated first using players in queue
if (!BattlegroundMgr::IsArenaType(m_bgTypeId)) if (!BattlegroundMgr::IsArenaType(m_bgTypeId))
{ {
const BattlegroundContainer& bgList = sBattlegroundMgr->GetBattlegroundList(); std::vector<Battleground*> bgsToCheck;
BattlegroundNeedSet bgsToCheck;
// sort from most needing (most empty) to least needing using a std::set with functor // sort from most needing (most empty) to least needing using a std::set with functor
for (auto itr : bgList) sBattlegroundMgr->DoForAllBattlegrounds([&](Battleground* bg)
{ {
Battleground* bg = itr.second; if (!BattlegroundMgr::IsArenaType(bg->GetBgTypeID()) &&
if (!BattlegroundMgr::IsArenaType(bg->GetBgTypeID()) && (bg->GetBgTypeID(true) == m_bgTypeId || m_bgTypeId == BATTLEGROUND_RB) && (bg->GetBgTypeID(true) == m_bgTypeId || m_bgTypeId == BATTLEGROUND_RB) &&
bg->HasFreeSlots() && bg->GetMinLevel() <= bracketEntry->minLevel && bg->GetMaxLevel() >= bracketEntry->maxLevel) bg->HasFreeSlots() && bg->GetMinLevel() <= bracketEntry->minLevel &&
bgsToCheck.insert(bg); bg->GetMaxLevel() >= bracketEntry->maxLevel)
{
bgsToCheck.emplace_back(bg);
} }
});
std::sort(bgsToCheck.begin(), bgsToCheck.end(), [](Battleground* const& bg1, Battleground* const& bg2)
{
return ((float)bg1->GetMaxFreeSlots() / (float)bg1->GetMaxPlayersPerTeam()) > ((float)bg2->GetMaxFreeSlots() / (float)bg2->GetMaxPlayersPerTeam());
});
// now iterate needing battlegrounds // now iterate needing battlegrounds
for (auto bg : bgsToCheck) for (auto const& bg : bgsToCheck)
{ {
// call a function that fills whatever we can from normal queues // call a function that fills whatever we can from normal queues
FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id); FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id);
// invite players // invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto itr : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups) for (auto itr : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(itr, bg, itr->RealTeamID); InviteGroupToBG(itr, bg, itr->RealTeamID);
} }
// prevent new BGs to be created if there are some non-empty BGs running // prevent new BGs to be created if there are some non-empty BGs running
@@ -751,9 +673,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
return; return;
// invite players // invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups) for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
bg->StartBattleground(); bg->StartBattleground();
@@ -764,9 +686,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id); FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id);
// invite players // invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups) for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
} }
} }
@@ -786,9 +708,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
return; return;
// invite players // invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++) for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups) for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
bg->StartBattleground(); bg->StartBattleground();
} }
@@ -804,7 +726,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
const uint32 maxCountedMMR = 2500; const uint32 maxCountedMMR = 2500;
// we need to find 2 teams which will play next game // we need to find 2 teams which will play next game
GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT]; GroupsQueueType::iterator itr_teams[PVP_TEAMS_COUNT];
bool increaseItr = true; bool increaseItr = true;
bool reverse1 = urand(0, 1) != 0; bool reverse1 = urand(0, 1) != 0;
@@ -937,8 +859,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
arena->SetArenaMatchmakerRating(TEAM_ALLIANCE, aTeam->ArenaMatchmakerRating); arena->SetArenaMatchmakerRating(TEAM_ALLIANCE, aTeam->ArenaMatchmakerRating);
arena->SetArenaMatchmakerRating(TEAM_HORDE, hTeam->ArenaMatchmakerRating); arena->SetArenaMatchmakerRating(TEAM_HORDE, hTeam->ArenaMatchmakerRating);
BattlegroundMgr::InviteGroupToBG(aTeam, arena, TEAM_ALLIANCE); InviteGroupToBG(aTeam, arena, TEAM_ALLIANCE);
BattlegroundMgr::InviteGroupToBG(hTeam, arena, TEAM_HORDE); InviteGroupToBG(hTeam, arena, TEAM_HORDE);
arena->StartBattleground(); arena->StartBattleground();
} }
@@ -980,12 +902,12 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
{ {
_queueAnnouncementTimer[bracket_id] = -1; _queueAnnouncementTimer[bracket_id] = -1;
char const* bgName = bg_template->GetName(); auto bgName = bg_template->GetName();
uint32 MaxPlayers = bg_template->GetMinPlayersPerTeam() * 2; uint32 MaxPlayers = bg_template->GetMinPlayersPerTeam() * 2;
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32) 80); uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32) 80);
uint32 q_max_level = std::min(bracketEntry->maxLevel, (uint32) 80); uint32 q_max_level = std::min(bracketEntry->maxLevel, (uint32) 80);
sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName, q_min_level, q_max_level, qPlayers, MaxPlayers); sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName.c_str(), q_min_level, q_max_level, qPlayers, MaxPlayers);
} }
else else
{ {
@@ -1031,7 +953,7 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
} }
BattlegroundBracketId bracketId = bracketEntry->GetBracketId(); BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
char const* bgName = bg->GetName(); auto bgName = bg->GetName();
uint32 MinPlayers = bg->GetMinPlayersPerTeam(); uint32 MinPlayers = bg->GetMinPlayersPerTeam();
uint32 MaxPlayers = MinPlayers * 2; uint32 MaxPlayers = MinPlayers * 2;
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32)80); uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32)80);
@@ -1046,12 +968,9 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
// Show queue status to player only (when joining battleground queue or Arena and arena world announcer is disabled) // Show queue status to player only (when joining battleground queue or Arena and arena world announcer is disabled)
if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
{ {
ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName, q_min_level, q_max_level, ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName.c_str(), q_min_level, q_max_level,
qAlliance, qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0,
(MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
qHorde,
(MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0
);
} }
else // Show queue status to server (when joining battleground queue) else // Show queue status to server (when joining battleground queue)
{ {
@@ -1069,7 +988,7 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
return; return;
} }
sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName, q_min_level, q_max_level, qAlliance + qHorde, MaxPlayers); sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName.c_str(), q_min_level, q_max_level, qAlliance + qHorde, MaxPlayers);
} }
} }
} }
@@ -1120,7 +1039,7 @@ void BattlegroundQueue::SendJoinMessageArenaQueue(Player* leader, GroupQueueInfo
return; return;
} }
sWorld->SendWorldTextOptional(LANG_ARENA_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_ARENA_QUEUE, bgName, arenatype.c_str(), q_min_level, q_max_level, qPlayers, playersNeed); sWorld->SendWorldTextOptional(LANG_ARENA_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_ARENA_QUEUE, bgName.c_str(), arenatype.c_str(), q_min_level, q_max_level, qPlayers, playersNeed);
} }
} }
else else
@@ -1175,6 +1094,63 @@ int32 BattlegroundQueue::GetQueueAnnouncementTimer(uint32 bracketId) const
return _queueAnnouncementTimer[bracketId]; return _queueAnnouncementTimer[bracketId];
} }
void BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId)
{
if (ginfo->IsInvitedToBGInstanceGUID)
return;
// set side if needed
if (teamId != TEAM_NEUTRAL)
ginfo->teamId = teamId;
// set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(ginfo->BgTypeId, ginfo->ArenaType);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
// set ArenaTeamId for rated matches
if (bg->isArena() && bg->isRated())
bg->SetArenaTeamIdForTeam(ginfo->teamId, ginfo->ArenaTeamId);
ginfo->RemoveInviteTime = GameTime::GetGameTimeMS().count() + INVITE_ACCEPT_WAIT_TIME;
// loop through the players
for (auto const& itr : ginfo->Players)
{
// get the player
Player* player = ObjectAccessor::FindConnectedPlayer(itr);
if (!player)
continue;
// update average wait time
bgQueue.PlayerInvitedToBGUpdateAverageWaitTime(ginfo);
// increase invited counter for each invited player
bg->IncreaseInvitedCount(ginfo->teamId);
// create remind invite events
BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, ginfo->BgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime);
bgQueue.AddEvent(inviteEvent, INVITATION_REMIND_TIME);
// create automatic remove events
BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgQueueTypeId, ginfo->RemoveInviteTime);
bgQueue.AddEvent(removeEvent, INVITE_ACCEPT_WAIT_TIME);
// Check queueSlot
uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
ASSERT(queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES);
// send status packet
WorldPacket data;
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0, ginfo->ArenaType, TEAM_NEUTRAL, bg->isRated(), ginfo->BgTypeId);
player->GetSession()->SendPacket(&data);
// pussywizard:
if (bg->isArena() && bg->isRated())
bg->ArenaLogEntries[player->GetGUID()].Fill(player->GetName().c_str(), player->GetGUID().GetCounter(), player->GetSession()->GetAccountId(), ginfo->ArenaTeamId, player->GetSession()->GetRemoteAddress());
}
}
/*********************************************************/ /*********************************************************/
/*** BATTLEGROUND QUEUE EVENTS ***/ /*** BATTLEGROUND QUEUE EVENTS ***/
/*********************************************************/ /*********************************************************/
@@ -72,7 +72,6 @@ public:
void UpdateEvents(uint32 diff); void UpdateEvents(uint32 diff);
void FillPlayersToBG(Battleground* bg, int32 aliFree, int32 hordeFree, BattlegroundBracketId bracket_id); void FillPlayersToBG(Battleground* bg, int32 aliFree, int32 hordeFree, BattlegroundBracketId bracket_id);
void FillPlayersToBGWithSpecific(Battleground* bg, int32 aliFree, int32 hordeFree, BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId);
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam); bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
bool CheckNormalMatch(Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers); bool CheckNormalMatch(Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam); bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam);
@@ -83,6 +82,7 @@ public:
bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo* ginfo); bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo* ginfo);
void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo); void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo);
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo) const; uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo) const;
void InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId);
[[nodiscard]] uint32 GetPlayersCountInGroupsQueue(BattlegroundBracketId bracketId, BattlegroundQueueGroupTypes bgqueue); [[nodiscard]] uint32 GetPlayersCountInGroupsQueue(BattlegroundBracketId bracketId, BattlegroundQueueGroupTypes bgqueue);
[[nodiscard]] bool IsAllQueuesEmpty(BattlegroundBracketId bracket_id); [[nodiscard]] bool IsAllQueuesEmpty(BattlegroundBracketId bracket_id);
void SendMessageBGQueue(Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry); void SendMessageBGQueue(Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry);
@@ -125,7 +125,7 @@ public:
}; };
//one selection pool for horde, other one for alliance //one selection pool for horde, other one for alliance
SelectionPool m_SelectionPools[BG_TEAMS_COUNT]; SelectionPool m_SelectionPools[PVP_TEAMS_COUNT];
ArenaType GetArenaType() { return m_arenaType; } ArenaType GetArenaType() { return m_arenaType; }
BattlegroundTypeId GetBGTypeID() { return m_bgTypeId; } BattlegroundTypeId GetBGTypeID() { return m_bgTypeId; }
@@ -136,8 +136,8 @@ public:
private: private:
BattlegroundTypeId m_bgTypeId; BattlegroundTypeId m_bgTypeId;
ArenaType m_arenaType; ArenaType m_arenaType;
uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; uint32 m_WaitTimes[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
uint32 m_WaitTimeLastIndex[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]; uint32 m_WaitTimeLastIndex[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS];
// Event handler // Event handler
EventProcessor m_events; EventProcessor m_events;
@@ -0,0 +1,125 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _BATTLEGROUND_SCORE_H
#define _BATTLEGROUND_SCORE_H
#include "Errors.h"
#include "ObjectGuid.h"
#include "SharedDefines.h"
class WorldPacket;
enum ScoreType
{
SCORE_KILLING_BLOWS = 1,
SCORE_DEATHS,
SCORE_HONORABLE_KILLS,
SCORE_BONUS_HONOR,
SCORE_DAMAGE_DONE,
SCORE_HEALING_DONE,
// WS and EY
SCORE_FLAG_CAPTURES,
SCORE_FLAG_RETURNS,
// AB and IC
SCORE_BASES_ASSAULTED,
SCORE_BASES_DEFENDED,
// AV
SCORE_GRAVEYARDS_ASSAULTED,
SCORE_GRAVEYARDS_DEFENDED,
SCORE_TOWERS_ASSAULTED,
SCORE_TOWERS_DEFENDED,
SCORE_MINES_CAPTURED,
//SCORE_LEADERS_KILLED,
//SCORE_SECONDARY_OBJECTIVES,
// SOTA
SCORE_DESTROYED_DEMOLISHER,
SCORE_DESTROYED_WALL
};
struct AC_GAME_API BattlegroundScore
{
friend class Arena;
friend class Battleground;
protected:
BattlegroundScore(ObjectGuid playerGuid) : PlayerGuid(playerGuid) { }
virtual ~BattlegroundScore() = default;
virtual void UpdateScore(uint32 type, uint32 value)
{
switch (type)
{
case SCORE_KILLING_BLOWS: // Killing blows
KillingBlows += value;
break;
case SCORE_DEATHS: // Deaths
Deaths += value;
break;
case SCORE_HONORABLE_KILLS: // Honorable kills
HonorableKills += value;
break;
case SCORE_BONUS_HONOR: // Honor bonus
BonusHonor += value;
break;
case SCORE_DAMAGE_DONE: // Damage Done
DamageDone += value;
break;
case SCORE_HEALING_DONE: // Healing Done
HealingDone += value;
break;
default:
ABORT("Not implemented Battleground score type!");
break;
}
}
virtual void AppendToPacket(WorldPacket& data);
virtual void BuildObjectivesBlock(WorldPacket& /*data*/) = 0;
// For Logging purpose
virtual std::string ToString() const { return ""; }
[[nodiscard]] uint32 GetKillingBlows() const { return KillingBlows; }
[[nodiscard]] uint32 GetDeaths() const { return Deaths; }
[[nodiscard]] uint32 GetHonorableKills() const { return HonorableKills; }
[[nodiscard]] uint32 GetBonusHonor() const { return BonusHonor; }
[[nodiscard]] uint32 GetDamageDone() const { return DamageDone; }
[[nodiscard]] uint32 GetHealingDone() const { return HealingDone; }
[[nodiscard]] virtual uint32 GetAttr1() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr2() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr3() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr4() const { return 0; }
[[nodiscard]] virtual uint32 GetAttr5() const { return 0; }
ObjectGuid PlayerGuid;
// Default score, present in every type
uint32 KillingBlows = 0;
uint32 Deaths = 0;
uint32 HonorableKills = 0;
uint32 BonusHonor = 0;
uint32 DamageDone = 0;
uint32 HealingDone = 0;
};
#endif // TRINITY_BATTLEGROUND_SCORE_H
@@ -25,6 +25,13 @@
#include "WorldPacket.h" #include "WorldPacket.h"
#include "WorldSession.h" #include "WorldSession.h"
void BattlegroundABScore::BuildObjectivesBlock(WorldPacket& data)
{
data << uint32(2);
data << uint32(BasesAssaulted);
data << uint32(BasesDefended);
}
BattlegroundAB::BattlegroundAB() BattlegroundAB::BattlegroundAB()
{ {
m_BuffChange = true; m_BuffChange = true;
@@ -37,11 +44,6 @@ BattlegroundAB::BattlegroundAB()
_teamScores500Disadvantage[TEAM_HORDE] = false; _teamScores500Disadvantage[TEAM_HORDE] = false;
_honorTics = 0; _honorTics = 0;
_reputationTics = 0; _reputationTics = 0;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN;
} }
BattlegroundAB::~BattlegroundAB() = default; BattlegroundAB::~BattlegroundAB() = default;
@@ -78,8 +80,17 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff)
NodeOccupied(node); NodeOccupied(node);
SendNodeUpdate(node); SendNodeUpdate(node);
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN, teamId == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, nullptr, teamId == TEAM_ALLIANCE ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE, LANG_BG_AB_NODE_STABLES + node); if (teamId == TEAM_ALLIANCE)
PlaySoundToAll(teamId == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_CAPTURED_ALLIANCE : BG_AB_SOUND_NODE_CAPTURED_HORDE); {
SendBroadcastText(ABNodes[node].TextAllianceTaken, CHAT_MSG_BG_SYSTEM_ALLIANCE);
PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE);
}
else
{
SendBroadcastText(ABNodes[node].TextHordeTaken, CHAT_MSG_BG_SYSTEM_HORDE);
PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
}
break; break;
} }
case BG_AB_EVENT_ALLIANCE_TICK: case BG_AB_EVENT_ALLIANCE_TICK:
@@ -108,12 +119,12 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff)
{ {
if (teamId == TEAM_ALLIANCE) if (teamId == TEAM_ALLIANCE)
{ {
SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendBroadcastText(BG_AB_TEXT_ALLIANCE_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY_ALLIANCE); PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY_ALLIANCE);
} }
else else
{ {
SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendBroadcastText(BG_AB_TEXT_HORDE_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY_HORDE); PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY_HORDE);
} }
} }
@@ -165,7 +176,7 @@ void BattlegroundAB::StartingEventOpenDoors()
void BattlegroundAB::AddPlayer(Player* player) void BattlegroundAB::AddPlayer(Player* player)
{ {
Battleground::AddPlayer(player); Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundABScore(player); PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundABScore(player->GetGUID()));
} }
void BattlegroundAB::RemovePlayer(Player* player) void BattlegroundAB::RemovePlayer(Player* player)
@@ -309,8 +320,8 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
uint32 sound = 0; uint32 sound = 0;
uint32 message = 0; TeamId teamid = player->GetTeamId();
uint32 message2 = 0;
DeleteBanner(node); DeleteBanner(node);
CreateBanner(node, true); CreateBanner(node, true);
@@ -322,8 +333,15 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL; _capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME); _bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
sound = BG_AB_SOUND_NODE_CLAIMED; sound = BG_AB_SOUND_NODE_CLAIMED;
message = LANG_BG_AB_NODE_CLAIMED;
message2 = player->GetTeamId() == TEAM_ALLIANCE ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE; if (teamid == TEAM_ALLIANCE)
{
SendBroadcastText(ABNodes[node].TextAllianceClaims, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
SendBroadcastText(ABNodes[node].TextHordeClaims, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
} }
else if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED || _capturePointInfo[node]._state == BG_AB_NODE_STATE_HORDE_CONTESTED) else if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED || _capturePointInfo[node]._state == BG_AB_NODE_STATE_HORDE_CONTESTED)
{ {
@@ -334,7 +352,15 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
_capturePointInfo[node]._state = static_cast<uint8>(BG_AB_NODE_STATE_ALLY_CONTESTED) + player->GetTeamId(); _capturePointInfo[node]._state = static_cast<uint8>(BG_AB_NODE_STATE_ALLY_CONTESTED) + player->GetTeamId();
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL; _capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME); _bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
message = LANG_BG_AB_NODE_ASSAULTED;
if (teamid == TEAM_ALLIANCE)
{
SendBroadcastText(ABNodes[node].TextAllianceAssaulted, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
SendBroadcastText(ABNodes[node].TextHordeAssaulted, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
} }
else else
{ {
@@ -343,8 +369,17 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
_capturePointInfo[node]._ownerTeamId = player->GetTeamId(); _capturePointInfo[node]._ownerTeamId = player->GetTeamId();
_bgEvents.CancelEvent(BG_AB_EVENT_CAPTURE_STABLE + node); _bgEvents.CancelEvent(BG_AB_EVENT_CAPTURE_STABLE + node);
NodeOccupied(node); // after setting team owner NodeOccupied(node); // after setting team owner
message = LANG_BG_AB_NODE_DEFENDED;
if (teamid == TEAM_ALLIANCE)
{
SendBroadcastText(ABNodes[node].TextAllianceDefended, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
} }
else
{
SendBroadcastText(ABNodes[node].TextHordeDefended, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
}
sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
} }
else else
@@ -357,13 +392,20 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
ApplyPhaseMask(); ApplyPhaseMask();
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME); _bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
message = LANG_BG_AB_NODE_ASSAULTED;
sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
if (teamid == TEAM_ALLIANCE)
{
SendBroadcastText(ABNodes[node].TextAllianceAssaulted, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
SendBroadcastText(ABNodes[node].TextHordeAssaulted, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
} }
SendNodeUpdate(node); SendNodeUpdate(node);
PlaySoundToAll(sound); PlaySoundToAll(sound);
SendMessage2ToAll(message, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, player, LANG_BG_AB_NODE_STABLES + node, message2);
} }
TeamId BattlegroundAB::GetPrematureWinner() TeamId BattlegroundAB::GetPrematureWinner()
@@ -473,26 +515,24 @@ GraveyardStruct const* BattlegroundAB::GetClosestGraveyard(Player* player)
return nearestEntry; return nearestEntry;
} }
void BattlegroundAB::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) bool BattlegroundAB::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{ {
auto itr = PlayerScores.find(player->GetGUID()); if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
if (itr == PlayerScores.end()) return false;
return;
switch (type) switch (type)
{ {
case SCORE_BASES_ASSAULTED: case SCORE_BASES_ASSAULTED:
((BattlegroundABScore*)itr->second)->BasesAssaulted += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_ASSAULT_BASE); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_ASSAULT_BASE);
break; break;
case SCORE_BASES_DEFENDED: case SCORE_BASES_DEFENDED:
((BattlegroundABScore*)itr->second)->BasesDefended += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_DEFEND_BASE); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_DEFEND_BASE);
break; break;
default: default:
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break; break;
} }
return true;
} }
bool BattlegroundAB::AllNodesConrolledByTeam(TeamId teamId) const bool BattlegroundAB::AllNodesConrolledByTeam(TeamId teamId) const
@@ -508,7 +548,8 @@ void BattlegroundAB::ApplyPhaseMask()
phaseMask |= 1 << (i * 2 + 1 + _capturePointInfo[i]._ownerTeamId); phaseMask |= 1 << (i * 2 + 1 + _capturePointInfo[i]._ownerTeamId);
const BattlegroundPlayerMap& bgPlayerMap = GetPlayers(); const BattlegroundPlayerMap& bgPlayerMap = GetPlayers();
for (auto itr : bgPlayerMap)
for (auto const& itr : bgPlayerMap)
{ {
itr.second->SetPhaseMask(phaseMask, false); itr.second->SetPhaseMask(phaseMask, false);
itr.second->UpdateObjectVisibility(true, false); itr.second->UpdateObjectVisibility(true, false);
@@ -19,6 +19,7 @@
#define __BATTLEGROUNDAB_H #define __BATTLEGROUNDAB_H
#include "Battleground.h" #include "Battleground.h"
#include "BattlegroundScore.h"
#include "EventMap.h" #include "EventMap.h"
enum BG_AB_Events enum BG_AB_Events
@@ -147,6 +148,34 @@ enum BG_AB_BattlegroundNodes
BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static) BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static)
}; };
enum BG_AB_BroadcastTexts
{
BG_AB_TEXT_ALLIANCE_NEAR_VICTORY = 10598,
BG_AB_TEXT_HORDE_NEAR_VICTORY = 10599,
};
struct ABNodeInfo
{
uint32 NodeId;
uint32 TextAllianceAssaulted;
uint32 TextHordeAssaulted;
uint32 TextAllianceTaken;
uint32 TextHordeTaken;
uint32 TextAllianceDefended;
uint32 TextHordeDefended;
uint32 TextAllianceClaims;
uint32 TextHordeClaims;
};
ABNodeInfo const ABNodes[BG_AB_DYNAMIC_NODES_COUNT] =
{
{ BG_AB_NODE_STABLES, 10199, 10200, 10203, 10204, 10201, 10202, 10286, 10287 },
{ BG_AB_NODE_BLACKSMITH, 10211, 10212, 10213, 10214, 10215, 10216, 10290, 10291 },
{ BG_AB_NODE_FARM, 10217, 10218, 10219, 10220, 10221, 10222, 10288, 10289 },
{ BG_AB_NODE_LUMBER_MILL, 10224, 10225, 10226, 10227, 10228, 10229, 10284, 10285 },
{ BG_AB_NODE_GOLD_MINE, 10230, 10231, 10232, 10233, 10234, 10235, 10282, 10283 }
};
enum BG_AB_NodeStatus enum BG_AB_NodeStatus
{ {
BG_AB_NODE_STATE_NEUTRAL = 0, BG_AB_NODE_STATE_NEUTRAL = 0,
@@ -225,18 +254,40 @@ const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] =
{714.61f, 646.15f, -10.87f, 4.34f} // horde starting base {714.61f, 646.15f, -10.87f, 4.34f} // horde starting base
}; };
struct BattlegroundABScore : public BattlegroundScore struct BattlegroundABScore final : public BattlegroundScore
{ {
explicit BattlegroundABScore(Player* player) : BattlegroundScore(player), BasesAssaulted(0), BasesDefended(0) { } friend class BattlegroundAB;
~BattlegroundABScore() override = default;
uint32 BasesAssaulted;
uint32 BasesDefended;
uint32 GetAttr1() const final { return BasesAssaulted; } protected:
uint32 GetAttr2() const final { return BasesDefended; }
explicit BattlegroundABScore(ObjectGuid playerGuid) : BattlegroundScore(playerGuid) { }
void UpdateScore(uint32 type, uint32 value) override
{
switch (type)
{
case SCORE_BASES_ASSAULTED:
BasesAssaulted += value;
break;
case SCORE_BASES_DEFENDED:
BasesDefended += value;
break;
default:
BattlegroundScore::UpdateScore(type, value);
break;
}
}
void BuildObjectivesBlock(WorldPacket& data) final override;
uint32 GetAttr1() const final override { return BasesAssaulted; }
uint32 GetAttr2() const final override { return BasesDefended; }
uint32 BasesAssaulted = 0;
uint32 BasesDefended = 0;
}; };
class BattlegroundAB : public Battleground class AC_GAME_API BattlegroundAB : public Battleground
{ {
public: public:
BattlegroundAB(); BattlegroundAB();
@@ -252,7 +303,7 @@ public:
void EndBattleground(TeamId winnerTeamId) override; void EndBattleground(TeamId winnerTeamId) override;
GraveyardStruct const* GetClosestGraveyard(Player* player) override; GraveyardStruct const* GetClosestGraveyard(Player* player) override;
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override; void FillInitialWorldStates(WorldPacket& data) override;
void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override; void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override;
@@ -288,7 +339,7 @@ private:
EventMap _bgEvents; EventMap _bgEvents;
uint32 _honorTics; uint32 _honorTics;
uint32 _reputationTics; uint32 _reputationTics;
uint8 _controlledPoints[BG_TEAMS_COUNT] {}; uint8 _controlledPoints[PVP_TEAMS_COUNT] {};
bool _teamScores500Disadvantage[BG_TEAMS_COUNT] {}; bool _teamScores500Disadvantage[PVP_TEAMS_COUNT] {};
}; };
#endif #endif
@@ -27,6 +27,16 @@
#include "WorldPacket.h" #include "WorldPacket.h"
#include "WorldSession.h" #include "WorldSession.h"
void BattlegroundAVScore::BuildObjectivesBlock(WorldPacket& data)
{
data << uint32(5); // Objectives Count
data << uint32(GraveyardsAssaulted);
data << uint32(GraveyardsDefended);
data << uint32(TowersAssaulted);
data << uint32(TowersDefended);
data << uint32(MinesCaptured);
}
BattlegroundAV::BattlegroundAV() BattlegroundAV::BattlegroundAV()
{ {
BgObjects.resize(BG_AV_OBJECT_MAX); BgObjects.resize(BG_AV_OBJECT_MAX);
@@ -49,14 +59,9 @@ BattlegroundAV::BattlegroundAV()
for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
InitNode(i, TEAM_NEUTRAL, false); InitNode(i, TEAM_NEUTRAL, false);
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES; StartMessageIds[BG_STARTING_EVENT_SECOND] = BG_AV_TEXT_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE; StartMessageIds[BG_STARTING_EVENT_THIRD] = BG_AV_TEXT_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE; StartMessageIds[BG_STARTING_EVENT_FOURTH] = BG_AV_TEXT_BATTLE_HAS_BEGUN;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN;
}
BattlegroundAV::~BattlegroundAV()
{
} }
void BattlegroundAV::HandleKillPlayer(Player* player, Player* killer) void BattlegroundAV::HandleKillPlayer(Player* player, Player* killer)
@@ -268,7 +273,15 @@ void BattlegroundAV::UpdateScore(TeamId teamId, int16 points)
} }
else if (!m_IsInformedNearVictory[teamId] && m_Team_Scores[teamId] < SEND_MSG_NEAR_LOSE) else if (!m_IsInformedNearVictory[teamId] && m_Team_Scores[teamId] < SEND_MSG_NEAR_LOSE)
{ {
SendMessageToAll(teamId == TEAM_HORDE ? LANG_BG_AV_H_NEAR_LOSE : LANG_BG_AV_A_NEAR_LOSE, teamId == TEAM_HORDE ? CHAT_MSG_BG_SYSTEM_HORDE : CHAT_MSG_BG_SYSTEM_ALLIANCE); if (teamId == TEAM_ALLIANCE)
{
SendBroadcastText(BG_AV_TEXT_ALLIANCE_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_ALLIANCE);
}
else
{
SendBroadcastText(BG_AV_TEXT_HORDE_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_HORDE);
}
PlaySoundToAll(AV_SOUND_NEAR_VICTORY); PlaySoundToAll(AV_SOUND_NEAR_VICTORY);
m_IsInformedNearVictory[teamId] = true; m_IsInformedNearVictory[teamId] = true;
} }
@@ -456,8 +469,7 @@ void BattlegroundAV::StartingEventOpenDoors()
void BattlegroundAV::AddPlayer(Player* player) void BattlegroundAV::AddPlayer(Player* player)
{ {
Battleground::AddPlayer(player); Battleground::AddPlayer(player);
//create score and add it to map, default values are set in constructor PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundAVScore(player->GetGUID()));
PlayerScores[player->GetGUID()] = new BattlegroundAVScore(player);
} }
void BattlegroundAV::EndBattleground(TeamId winnerTeamId) void BattlegroundAV::EndBattleground(TeamId winnerTeamId)
@@ -542,43 +554,33 @@ void BattlegroundAV::HandleAreaTrigger(Player* player, uint32 trigger)
} }
} }
void BattlegroundAV::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) bool BattlegroundAV::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{ {
auto itr = PlayerScores.find(player->GetGUID()); if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
if (itr == PlayerScores.end()) return false;
return;
switch (type) switch (type)
{ {
case SCORE_GRAVEYARDS_ASSAULTED: case SCORE_GRAVEYARDS_ASSAULTED:
((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD);
break; break;
case SCORE_GRAVEYARDS_DEFENDED: case SCORE_GRAVEYARDS_DEFENDED:
((BattlegroundAVScore*)itr->second)->GraveyardsDefended += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD);
break; break;
case SCORE_TOWERS_ASSAULTED: case SCORE_TOWERS_ASSAULTED:
((BattlegroundAVScore*)itr->second)->TowersAssaulted += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER);
break; break;
case SCORE_TOWERS_DEFENDED: case SCORE_TOWERS_DEFENDED:
((BattlegroundAVScore*)itr->second)->TowersDefended += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER);
break; break;
case SCORE_MINES_CAPTURED: case SCORE_MINES_CAPTURED:
((BattlegroundAVScore*)itr->second)->MinesCaptured += value;
break;
case SCORE_LEADERS_KILLED:
((BattlegroundAVScore*)itr->second)->LeadersKilled += value;
break;
case SCORE_SECONDARY_OBJECTIVES:
((BattlegroundAVScore*)itr->second)->SecondaryObjectives += value;
break; break;
default: default:
Battleground::UpdatePlayerScore(player, type, value, doAddHonor); Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break; break;
} }
return true;
} }
void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node) void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node)
@@ -19,6 +19,7 @@
#define __BATTLEGROUNDAV_H #define __BATTLEGROUNDAV_H
#include "Battleground.h" #include "Battleground.h"
#include "BattlegroundScore.h"
#define LANG_BG_AV_A_CAPTAIN_BUFF "Begone. Uncouth scum! The Alliance shall prevail in Alterac Valley!" #define LANG_BG_AV_A_CAPTAIN_BUFF "Begone. Uncouth scum! The Alliance shall prevail in Alterac Valley!"
#define LANG_BG_AV_H_CAPTAIN_BUFF "Now is the time to attack! For the Horde!" #define LANG_BG_AV_H_CAPTAIN_BUFF "Now is the time to attack! For the Horde!"
@@ -51,6 +52,16 @@
#define AV_EVENT_START_BATTLE 9166 // Achievement: The Alterac Blitz #define AV_EVENT_START_BATTLE 9166 // Achievement: The Alterac Blitz
enum BG_AV_BroadcastTexts
{
BG_AV_TEXT_START_ONE_MINUTE = 10638,
BG_AV_TEXT_START_HALF_MINUTE = 10639,
BG_AV_TEXT_BATTLE_HAS_BEGUN = 10640,
BG_AV_TEXT_ALLIANCE_NEAR_LOSE = 23210,
BG_AV_TEXT_HORDE_NEAR_LOSE = 23211
};
enum BG_AV_Sounds enum BG_AV_Sounds
{ {
//TODO: get out if there comes a sound when neutral team captures mine //TODO: get out if there comes a sound when neutral team captures mine
@@ -1341,6 +1352,7 @@ enum BG_AV_BUFF
AV_BUFF_A_CAPTAIN = 23693, //the buff which the alliance captain does AV_BUFF_A_CAPTAIN = 23693, //the buff which the alliance captain does
AV_BUFF_H_CAPTAIN = 22751 //the buff which the horde captain does AV_BUFF_H_CAPTAIN = 22751 //the buff which the horde captain does
}; };
enum BG_AV_States enum BG_AV_States
{ {
POINT_NEUTRAL = 0, POINT_NEUTRAL = 0,
@@ -1551,17 +1563,47 @@ struct BG_AV_NodeInfo
inline BG_AV_Nodes& operator++(BG_AV_Nodes& i) { return i = BG_AV_Nodes(i + 1); } inline BG_AV_Nodes& operator++(BG_AV_Nodes& i) { return i = BG_AV_Nodes(i + 1); }
struct BattlegroundAVScore : public BattlegroundScore struct BattlegroundAVScore final : public BattlegroundScore
{ {
explicit BattlegroundAVScore(Player* player) : BattlegroundScore(player), GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0), LeadersKilled(0), SecondaryObjectives(0) { } friend class BattlegroundAV;
~BattlegroundAVScore() override { }
uint32 GraveyardsAssaulted; protected:
uint32 GraveyardsDefended; explicit BattlegroundAVScore(ObjectGuid playerGuid) : BattlegroundScore(playerGuid) { }
uint32 TowersAssaulted;
uint32 TowersDefended; void UpdateScore(uint32 type, uint32 value) override
uint32 MinesCaptured; {
uint32 LeadersKilled; switch (type)
uint32 SecondaryObjectives; {
case SCORE_GRAVEYARDS_ASSAULTED:
GraveyardsAssaulted += value;
break;
case SCORE_GRAVEYARDS_DEFENDED:
GraveyardsDefended += value;
break;
case SCORE_TOWERS_ASSAULTED:
TowersAssaulted += value;
break;
case SCORE_TOWERS_DEFENDED:
TowersDefended += value;
break;
case SCORE_MINES_CAPTURED:
MinesCaptured += value;
break;
default:
BattlegroundScore::UpdateScore(type, value);
break;
}
}
void BuildObjectivesBlock(WorldPacket& data) final override;
uint32 GraveyardsAssaulted = 0;
uint32 GraveyardsDefended = 0;
uint32 TowersAssaulted = 0;
uint32 TowersDefended = 0;
uint32 MinesCaptured = 0;
//uint32 LeadersKilled;
//uint32 SecondaryObjectives;
uint32 GetAttr1() const final { return GraveyardsAssaulted; } uint32 GetAttr1() const final { return GraveyardsAssaulted; }
uint32 GetAttr2() const final { return GraveyardsDefended; } uint32 GetAttr2() const final { return GraveyardsDefended; }
@@ -1570,11 +1612,11 @@ struct BattlegroundAVScore : public BattlegroundScore
uint32 GetAttr5() const final { return MinesCaptured; } uint32 GetAttr5() const final { return MinesCaptured; }
}; };
class BattlegroundAV : public Battleground class AC_GAME_API BattlegroundAV : public Battleground
{ {
public: public:
BattlegroundAV(); BattlegroundAV();
~BattlegroundAV() override; ~BattlegroundAV() override = default;
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
void AddPlayer(Player* player) override; void AddPlayer(Player* player) override;
@@ -1588,7 +1630,7 @@ public:
/*general stuff*/ /*general stuff*/
void UpdateScore(TeamId teamId, int16 points); void UpdateScore(TeamId teamId, int16 points);
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
/*handlestuff*/ //these are functions which get called from extern /*handlestuff*/ //these are functions which get called from extern
void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override; void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override;
@@ -16,7 +16,6 @@
*/ */
#include "BattlegroundBE.h" #include "BattlegroundBE.h"
#include "Language.h"
#include "Log.h" #include "Log.h"
#include "Player.h" #include "Player.h"
#include "WorldPacket.h" #include "WorldPacket.h"
@@ -24,20 +23,6 @@
BattlegroundBE::BattlegroundBE() BattlegroundBE::BattlegroundBE()
{ {
BgObjects.resize(BG_BE_OBJECT_MAX); BgObjects.resize(BG_BE_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundBE::~BattlegroundBE()
{
} }
void BattlegroundBE::StartingEventCloseDoors() void BattlegroundBE::StartingEventCloseDoors()
@@ -58,39 +43,6 @@ void BattlegroundBE::StartingEventOpenDoors()
SpawnBGObject(i, 60); SpawnBGObject(i, 60);
} }
void BattlegroundBE::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundBE::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundBE::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
LOG_ERROR("bg.battleground", "Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundBE::HandlePlayerUnderMap(Player* player) bool BattlegroundBE::HandlePlayerUnderMap(Player* player)
{ {
player->NearTeleportTo(6238.930176f, 262.963470f, 0.889519f, player->GetOrientation()); player->NearTeleportTo(6238.930176f, 262.963470f, 0.889519f, player->GetOrientation());
@@ -138,13 +90,7 @@ void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger)
void BattlegroundBE::FillInitialWorldStates(WorldPacket& data) void BattlegroundBE::FillInitialWorldStates(WorldPacket& data)
{ {
data << uint32(0x9f3) << uint32(1); // 9 data << uint32(0x9f3) << uint32(1); // 9
Battleground::UpdateArenaWorldState(); Arena::FillInitialWorldStates(data);
}
void BattlegroundBE::Init()
{
//call parent's class reset
Battleground::Init();
} }
bool BattlegroundBE::SetupBattleground() bool BattlegroundBE::SetupBattleground()
@@ -167,8 +113,3 @@ bool BattlegroundBE::SetupBattleground()
return true; return true;
} }
void BattlegroundBE::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
}
@@ -18,7 +18,7 @@
#ifndef __BATTLEGROUNDBE_H #ifndef __BATTLEGROUNDBE_H
#define __BATTLEGROUNDBE_H #define __BATTLEGROUNDBE_H
#include "Battleground.h" #include "Arena.h"
enum BattlegroundBEObjectTypes enum BattlegroundBEObjectTypes
{ {
@@ -33,7 +33,7 @@ enum BattlegroundBEObjectTypes
BG_BE_OBJECT_MAX = 8 BG_BE_OBJECT_MAX = 8
}; };
enum BattlegroundBEObjects enum BattlegroundBEGameObjects
{ {
BG_BE_OBJECT_TYPE_DOOR_1 = 183971, BG_BE_OBJECT_TYPE_DOOR_1 = 183971,
BG_BE_OBJECT_TYPE_DOOR_2 = 183973, BG_BE_OBJECT_TYPE_DOOR_2 = 183973,
@@ -43,26 +43,19 @@ enum BattlegroundBEObjects
BG_BE_OBJECT_TYPE_BUFF_2 = 184664 BG_BE_OBJECT_TYPE_BUFF_2 = 184664
}; };
class BattlegroundBE : public Battleground class AC_GAME_API BattlegroundBE : public Arena
{ {
public: public:
BattlegroundBE(); BattlegroundBE();
~BattlegroundBE() override;
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
void AddPlayer(Player* player) override;
void StartingEventCloseDoors() override; void StartingEventCloseDoors() override;
void StartingEventOpenDoors() override; void StartingEventOpenDoors() override;
void RemovePlayer(Player* player) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override; void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override; bool SetupBattleground() override;
void Init() override;
void FillInitialWorldStates(WorldPacket& d) override; void FillInitialWorldStates(WorldPacket& d) override;
void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* player) override; bool HandlePlayerUnderMap(Player* player) override;
/* Scorekeeping */
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
}; };
#endif #endif
@@ -16,6 +16,7 @@
*/ */
#include "BattlegroundDS.h" #include "BattlegroundDS.h"
#include "ArenaScore.h"
#include "Creature.h" #include "Creature.h"
#include "GameObject.h" #include "GameObject.h"
#include "Language.h" #include "Language.h"
@@ -30,25 +31,8 @@ BattlegroundDS::BattlegroundDS()
BgObjects.resize(BG_DS_OBJECT_MAX); BgObjects.resize(BG_DS_OBJECT_MAX);
BgCreatures.resize(BG_DS_NPC_MAX); BgCreatures.resize(BG_DS_NPC_MAX);
_waterfallTimer = 0;
_waterfallStatus = 0;
_waterfallKnockbackTimer = 0;
_pipeKnockBackTimer = 0; _pipeKnockBackTimer = 0;
_pipeKnockBackCount = 0; _pipeKnockBackCount = 0;
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundDS::~BattlegroundDS()
{
} }
void BattlegroundDS::PostUpdateImpl(uint32 diff) void BattlegroundDS::PostUpdateImpl(uint32 diff)
@@ -56,64 +40,58 @@ void BattlegroundDS::PostUpdateImpl(uint32 diff)
if (GetStatus() != STATUS_IN_PROGRESS) if (GetStatus() != STATUS_IN_PROGRESS)
return; return;
if (getPipeKnockBackCount() < BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT) _events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{ {
if (getPipeKnockBackTimer() < diff) switch (eventId)
{
case BG_DS_EVENT_WATERFALL_WARNING:
// Add the water
DoorClose(BG_DS_OBJECT_WATER_2);
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_ON, BG_DS_WATERFALL_WARNING_DURATION);
break;
case BG_DS_EVENT_WATERFALL_ON:
// Active collision and start knockback timer
DoorClose(BG_DS_OBJECT_WATER_1);
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_OFF, BG_DS_WATERFALL_DURATION);
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_KNOCKBACK, BG_DS_WATERFALL_KNOCKBACK_TIMER);
break;
case BG_DS_EVENT_WATERFALL_OFF:
// Remove collision and water
DoorOpen(BG_DS_OBJECT_WATER_1);
DoorOpen(BG_DS_OBJECT_WATER_2);
_events.CancelEvent(BG_DS_EVENT_WATERFALL_KNOCKBACK);
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_WARNING, BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX);
break;
case BG_DS_EVENT_WATERFALL_KNOCKBACK:
// Repeat knockback while the waterfall still active
if (Creature* waterSpout = GetBGCreature(BG_DS_NPC_WATERFALL_KNOCKBACK))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_WATER_SPOUT, true);
_events.ScheduleEvent(eventId, BG_DS_WATERFALL_KNOCKBACK_TIMER);
break;
case BG_DS_EVENT_PIPE_KNOCKBACK:
for (uint32 i = BG_DS_NPC_PIPE_KNOCKBACK_1; i <= BG_DS_NPC_PIPE_KNOCKBACK_2; ++i)
if (Creature* waterSpout = GetBGCreature(i))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true);
break;
}
}
if (_pipeKnockBackCount < BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
{
if (_pipeKnockBackTimer < diff)
{ {
for (uint32 i = BG_DS_NPC_PIPE_KNOCKBACK_1; i <= BG_DS_NPC_PIPE_KNOCKBACK_2; ++i) for (uint32 i = BG_DS_NPC_PIPE_KNOCKBACK_1; i <= BG_DS_NPC_PIPE_KNOCKBACK_2; ++i)
if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[i])) if (Creature* waterSpout = GetBGCreature(i))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true); waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true);
setPipeKnockBackCount(getPipeKnockBackCount() + 1); ++_pipeKnockBackCount;
setPipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_DELAY); _pipeKnockBackTimer = BG_DS_PIPE_KNOCKBACK_DELAY;
} }
else else
setPipeKnockBackTimer(getPipeKnockBackTimer() - diff); _pipeKnockBackTimer -= diff;
} }
if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_ON) // Repeat knockback while the waterfall still active
{
if (getWaterFallKnockbackTimer() < diff)
{
if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[BG_DS_NPC_WATERFALL_KNOCKBACK]))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_WATER_SPOUT, true);
setWaterFallKnockbackTimer(BG_DS_WATERFALL_KNOCKBACK_TIMER);
}
else
setWaterFallKnockbackTimer(getWaterFallKnockbackTimer() - diff);
}
if (getWaterFallTimer() < diff)
{
if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_OFF) // Add the water
{
DoorClose(BG_DS_OBJECT_WATER_2);
setWaterFallTimer(BG_DS_WATERFALL_WARNING_DURATION);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_WARNING);
}
else if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_WARNING) // Active collision and perform knockback
{
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_READY);
setWaterFallTimer(BG_DS_WATERFALL_DURATION);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_ON);
setWaterFallKnockbackTimer(BG_DS_WATERFALL_KNOCKBACK_TIMER);
}
else //if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_ON) // Remove collision and water
{
// turn off collision
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_ACTIVE);
DoorOpen(BG_DS_OBJECT_WATER_2);
setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX));
setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF);
}
}
else
setWaterFallTimer(getWaterFallTimer() - diff);
} }
void BattlegroundDS::StartingEventCloseDoors() void BattlegroundDS::StartingEventCloseDoors()
@@ -130,11 +108,12 @@ void BattlegroundDS::StartingEventOpenDoors()
for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i) for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60); SpawnBGObject(i, 60);
setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); _events.ScheduleEvent(BG_DS_EVENT_WATERFALL_WARNING, BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF); //for (uint8 i = 0; i < BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT; ++i)
// _events.ScheduleEvent(BG_DS_EVENT_PIPE_KNOCKBACK, BG_DS_PIPE_KNOCKBACK_FIRST_DELAY + i * BG_DS_PIPE_KNOCKBACK_DELAY);
setPipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_FIRST_DELAY); _pipeKnockBackCount = 0;
setPipeKnockBackCount(0); _pipeKnockBackTimer = BG_DS_PIPE_KNOCKBACK_FIRST_DELAY;
SpawnBGObject(BG_DS_OBJECT_WATER_2, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_DS_OBJECT_WATER_2, RESPAWN_IMMEDIATELY);
DoorOpen(BG_DS_OBJECT_WATER_2); DoorOpen(BG_DS_OBJECT_WATER_2);
@@ -149,39 +128,6 @@ void BattlegroundDS::StartingEventOpenDoors()
itr->second->RemoveAurasDueToSpell(48018); itr->second->RemoveAurasDueToSpell(48018);
} }
void BattlegroundDS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundDS::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundDS::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
LOG_ERROR("bg.battleground", "BattlegroundDS: Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger) void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger)
{ {
if (GetStatus() != STATUS_IN_PROGRESS) if (GetStatus() != STATUS_IN_PROGRESS)
@@ -192,13 +138,13 @@ void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger)
case 5347: case 5347:
case 5348: case 5348:
// Remove effects of Demonic Circle Summon // Remove effects of Demonic Circle Summon
if (player->HasAura(48018)) if (player->HasAura(SPELL_WARL_DEMONIC_CIRCLE))
player->RemoveAurasDueToSpell(48018); player->RemoveAurasDueToSpell(SPELL_WARL_DEMONIC_CIRCLE);
// Someone has get back into the pipes and the knockback has already been performed, // Someone has get back into the pipes and the knockback has already been performed,
// so we reset the knockback count for kicking the player again into the arena. // so we reset the knockback count for kicking the player again into the arena.
if (getPipeKnockBackCount() >= BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT) if (_pipeKnockBackCount >= BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
setPipeKnockBackCount(0); _pipeKnockBackCount = 0;
break; break;
// OUTSIDE OF ARENA, TELEPORT! // OUTSIDE OF ARENA, TELEPORT!
case 5328: case 5328:
@@ -218,6 +164,9 @@ void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger)
case 5344: // -60 case 5344: // -60
player->NearTeleportTo(1330.0f, 800.0f, 3.16f, player->GetOrientation()); player->NearTeleportTo(1330.0f, 800.0f, 3.16f, player->GetOrientation());
break; break;
/*default:
Battleground::HandleAreaTrigger(player, trigger);
break;*/
} }
} }
@@ -230,13 +179,7 @@ bool BattlegroundDS::HandlePlayerUnderMap(Player* player)
void BattlegroundDS::FillInitialWorldStates(WorldPacket& data) void BattlegroundDS::FillInitialWorldStates(WorldPacket& data)
{ {
data << uint32(3610) << uint32(1); // 9 show data << uint32(3610) << uint32(1); // 9 show
Battleground::UpdateArenaWorldState(); Arena::FillInitialWorldStates(data);
}
void BattlegroundDS::Init()
{
//call parent's class reset
Battleground::Init();
} }
bool BattlegroundDS::SetupBattleground() bool BattlegroundDS::SetupBattleground()
@@ -18,7 +18,9 @@
#ifndef __BATTLEGROUNDDS_H #ifndef __BATTLEGROUNDDS_H
#define __BATTLEGROUNDDS_H #define __BATTLEGROUNDDS_H
#include "Battleground.h" #include "Arena.h"
#include "Duration.h"
#include "EventMap.h"
enum BattlegroundDSObjectTypes enum BattlegroundDSObjectTypes
{ {
@@ -33,7 +35,7 @@ enum BattlegroundDSObjectTypes
BG_DS_OBJECT_MAX = 8 BG_DS_OBJECT_MAX = 8
}; };
enum BattlegroundDSObjects enum BattlegroundDSGameObjects
{ {
BG_DS_OBJECT_TYPE_DOOR_1 = 192642, BG_DS_OBJECT_TYPE_DOOR_1 = 192642,
BG_DS_OBJECT_TYPE_DOOR_2 = 192643, BG_DS_OBJECT_TYPE_DOOR_2 = 192643,
@@ -61,62 +63,54 @@ enum BattlegroundDSSpells
BG_DS_SPELL_FLUSH = 57405, // Visual and target selector for the starting knockback from the pipe BG_DS_SPELL_FLUSH = 57405, // Visual and target selector for the starting knockback from the pipe
BG_DS_SPELL_FLUSH_KNOCKBACK = 61698, // Knockback effect for previous spell (triggered, not need to be casted) BG_DS_SPELL_FLUSH_KNOCKBACK = 61698, // Knockback effect for previous spell (triggered, not need to be casted)
BG_DS_SPELL_WATER_SPOUT = 58873, // Knockback effect of the central waterfall BG_DS_SPELL_WATER_SPOUT = 58873, // Knockback effect of the central waterfall
SPELL_WARL_DEMONIC_CIRCLE = 48018 // Demonic Circle Summon
}; };
enum BattlegroundDSData enum BattlegroundDSData
{ {
// These values are NOT blizzlike... need the correct data!
BG_DS_WATERFALL_TIMER_MIN = 30000,
BG_DS_WATERFALL_TIMER_MAX = 60000,
BG_DS_WATERFALL_WARNING_DURATION = 5000,
BG_DS_WATERFALL_DURATION = 30000,
BG_DS_WATERFALL_KNOCKBACK_TIMER = 1500,
BG_DS_PIPE_KNOCKBACK_FIRST_DELAY = 5000, BG_DS_PIPE_KNOCKBACK_FIRST_DELAY = 5000,
BG_DS_PIPE_KNOCKBACK_DELAY = 3000, BG_DS_PIPE_KNOCKBACK_DELAY = 3000,
BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT = 2, BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT = 2,
BG_DS_WATERFALL_STATUS_WARNING = 1, // Water starting to fall, but no LoS Blocking nor movement blocking
BG_DS_WATERFALL_STATUS_ON = 2, // LoS and Movement blocking active
BG_DS_WATERFALL_STATUS_OFF = 3,
}; };
class BattlegroundDS : public Battleground // These values are NOT blizzlike... need the correct data!
constexpr Seconds BG_DS_WATERFALL_TIMER_MIN = 30s;
constexpr Seconds BG_DS_WATERFALL_TIMER_MAX = 60s;
constexpr Seconds BG_DS_WATERFALL_WARNING_DURATION = 5s;
constexpr Seconds BG_DS_WATERFALL_DURATION = 30s;
constexpr Milliseconds BG_DS_WATERFALL_KNOCKBACK_TIMER = 1500ms;
enum BattlegroundDSEvents
{
BG_DS_EVENT_WATERFALL_WARNING = 1, // Water starting to fall, but no LoS Blocking nor movement blocking
BG_DS_EVENT_WATERFALL_ON = 2, // LoS and Movement blocking active
BG_DS_EVENT_WATERFALL_OFF = 3,
BG_DS_EVENT_WATERFALL_KNOCKBACK = 4,
BG_DS_EVENT_PIPE_KNOCKBACK = 5
};
class AC_GAME_API BattlegroundDS : public Arena
{ {
public: public:
BattlegroundDS(); BattlegroundDS();
~BattlegroundDS() override;
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
void AddPlayer(Player* player) override;
void StartingEventCloseDoors() override; void StartingEventCloseDoors() override;
void StartingEventOpenDoors() override; void StartingEventOpenDoors() override;
void RemovePlayer(Player* player) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override; void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override; bool SetupBattleground() override;
void Init() override;
void FillInitialWorldStates(WorldPacket& d) override; void FillInitialWorldStates(WorldPacket& d) override;
void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* player) override; bool HandlePlayerUnderMap(Player* player) override;
private: private:
uint32 _waterfallTimer; void PostUpdateImpl(uint32 diff) override;
uint8 _waterfallStatus;
uint32 _waterfallKnockbackTimer;
uint32 _pipeKnockBackTimer; uint32 _pipeKnockBackTimer;
uint8 _pipeKnockBackCount; uint8 _pipeKnockBackCount;
void PostUpdateImpl(uint32 diff) override; EventMap _events;
protected:
uint32 getWaterFallStatus() { return _waterfallStatus; };
void setWaterFallStatus(uint8 status) { _waterfallStatus = status; };
uint32 getWaterFallTimer() { return _waterfallTimer; };
void setWaterFallTimer(uint32 timer) { _waterfallTimer = timer; };
uint32 getWaterFallKnockbackTimer() { return _waterfallKnockbackTimer; };
void setWaterFallKnockbackTimer(uint32 timer) { _waterfallKnockbackTimer = timer; };
uint8 getPipeKnockBackCount() { return _pipeKnockBackCount; };
void setPipeKnockBackCount(uint8 count) { _pipeKnockBackCount = count; };
uint32 getPipeKnockBackTimer() { return _pipeKnockBackTimer; };
void setPipeKnockBackTimer(uint32 timer) { _pipeKnockBackTimer = timer; };
}; };
#endif #endif
@@ -28,6 +28,12 @@
#include "WorldPacket.h" #include "WorldPacket.h"
#include "WorldSession.h" #include "WorldSession.h"
void BattlegroundEYScore::BuildObjectivesBlock(WorldPacket& data)
{
data << uint32(1); // Objectives Count
data << uint32(FlagCaptures);
}
BattlegroundEY::BattlegroundEY() BattlegroundEY::BattlegroundEY()
{ {
m_BuffChange = true; m_BuffChange = true;
@@ -43,11 +49,6 @@ BattlegroundEY::BattlegroundEY()
_ownedPointsCount[TEAM_HORDE] = 0; _ownedPointsCount[TEAM_HORDE] = 0;
_flagState = BG_EY_FLAG_STATE_ON_BASE; _flagState = BG_EY_FLAG_STATE_ON_BASE;
_flagCapturedObject = 0; _flagCapturedObject = 0;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
} }
BattlegroundEY::~BattlegroundEY() BattlegroundEY::~BattlegroundEY()
@@ -144,6 +145,7 @@ void BattlegroundEY::UpdatePointsState()
itr->second->SendUpdateWorldState(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY); itr->second->SendUpdateWorldState(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY);
itr->second->SendUpdateWorldState(PROGRESS_BAR_STATUS, _capturePointInfo[point]._barStatus); itr->second->SendUpdateWorldState(PROGRESS_BAR_STATUS, _capturePointInfo[point]._barStatus);
++_capturePointInfo[point]._playersCount[itr->second->GetTeamId()]; ++_capturePointInfo[point]._playersCount[itr->second->GetTeamId()];
_capturePointInfo[point].player = itr->second;
// Xinef: ugly hax... area trigger is no longer called by client... // Xinef: ugly hax... area trigger is no longer called by client...
if (pointObject->GetEntry() == BG_OBJECT_FR_TOWER_CAP_EY_ENTRY && itr->second->GetDistance2d(2043.96f, 1729.68f) < 3.0f) if (pointObject->GetEntry() == BG_OBJECT_FR_TOWER_CAP_EY_ENTRY && itr->second->GetDistance2d(2043.96f, 1729.68f) < 3.0f)
@@ -165,10 +167,10 @@ void BattlegroundEY::UpdatePointsState()
if (pointOwnerTeamId != _capturePointInfo[point]._ownerTeamId) if (pointOwnerTeamId != _capturePointInfo[point]._ownerTeamId)
{ {
if (_capturePointInfo[point].IsUncontrolled()) if (_capturePointInfo[point].IsUncontrolled())
EventTeamCapturedPoint(pointOwnerTeamId, point); EventTeamCapturedPoint(_capturePointInfo[point].player, pointOwnerTeamId, point);
if (pointOwnerTeamId == TEAM_NEUTRAL && _capturePointInfo[point].IsUnderControl()) if (pointOwnerTeamId == TEAM_NEUTRAL && _capturePointInfo[point].IsUnderControl())
EventTeamLostPoint(pointOwnerTeamId, point); EventTeamLostPoint(_capturePointInfo[point].player, point);
} }
} }
} }
@@ -206,7 +208,7 @@ void BattlegroundEY::UpdatePointsIcons(uint32 point)
void BattlegroundEY::AddPlayer(Player* player) void BattlegroundEY::AddPlayer(Player* player)
{ {
Battleground::AddPlayer(player); Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundEYScore(player); PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundEYScore(player->GetGUID()));
} }
void BattlegroundEY::RemovePlayer(Player* player) void BattlegroundEY::RemovePlayer(Player* player)
@@ -371,7 +373,7 @@ void BattlegroundEY::RespawnFlag()
_flagCapturedObject = 0; _flagCapturedObject = 0;
SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY);
SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendBroadcastText(BG_EY_TEXT_FLAG_RESET, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); PlaySoundToAll(BG_EY_SOUND_FLAG_RESET);
UpdateWorldState(NETHERSTORM_FLAG, 1); UpdateWorldState(NETHERSTORM_FLAG, 1);
} }
@@ -413,7 +415,10 @@ void BattlegroundEY::EventPlayerDroppedFlag(Player* player)
player->CastSpell(player, SPELL_RECENTLY_DROPPED_FLAG, true); player->CastSpell(player, SPELL_RECENTLY_DROPPED_FLAG, true);
player->CastSpell(player, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true); player->CastSpell(player, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true);
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE); if (player->GetTeamId() == TEAM_ALLIANCE)
SendBroadcastText(BG_EY_TEXT_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_ALLIANCE);
else
SendBroadcastText(BG_EY_TEXT_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_HORDE);
} }
void BattlegroundEY::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject) void BattlegroundEY::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject)
@@ -429,12 +434,16 @@ void BattlegroundEY::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
player->CastSpell(player, BG_EY_NETHERSTORM_FLAG_SPELL, true); player->CastSpell(player, BG_EY_NETHERSTORM_FLAG_SPELL, true);
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, nullptr, player->GetName().c_str());
PlaySoundToAll(player->GetTeamId() == TEAM_ALLIANCE ? BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE : BG_EY_SOUND_FLAG_PICKED_UP_HORDE); PlaySoundToAll(player->GetTeamId() == TEAM_ALLIANCE ? BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE : BG_EY_SOUND_FLAG_PICKED_UP_HORDE);
UpdateWorldState(NETHERSTORM_FLAG, 0); UpdateWorldState(NETHERSTORM_FLAG, 0);
if (player->GetTeamId() == TEAM_ALLIANCE)
SendBroadcastText(BG_EY_TEXT_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
else
SendBroadcastText(BG_EY_TEXT_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, player);
} }
void BattlegroundEY::EventTeamLostPoint(TeamId /*teamId*/, uint32 point) void BattlegroundEY::EventTeamLostPoint(Player* player, uint32 point)
{ {
TeamId oldTeamId = _capturePointInfo[point]._ownerTeamId; TeamId oldTeamId = _capturePointInfo[point]._ownerTeamId;
if (oldTeamId == TEAM_ALLIANCE) if (oldTeamId == TEAM_ALLIANCE)
@@ -443,7 +452,7 @@ void BattlegroundEY::EventTeamLostPoint(TeamId /*teamId*/, uint32 point)
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY); SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY); SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY); SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY);
SendMessageToAll(m_LosingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE); SendBroadcastText(m_LosingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
} }
else else
{ {
@@ -451,7 +460,7 @@ void BattlegroundEY::EventTeamLostPoint(TeamId /*teamId*/, uint32 point)
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY); SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY); SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY);
SendMessageToAll(m_LosingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE); SendBroadcastText(m_LosingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE, player);
} }
SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY); SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY);
@@ -465,7 +474,7 @@ void BattlegroundEY::EventTeamLostPoint(TeamId /*teamId*/, uint32 point)
DelCreature(BG_EY_TRIGGER_FEL_REAVER + point); DelCreature(BG_EY_TRIGGER_FEL_REAVER + point);
} }
void BattlegroundEY::EventTeamCapturedPoint(TeamId teamId, uint32 point) void BattlegroundEY::EventTeamCapturedPoint(Player* player, TeamId teamId, uint32 point)
{ {
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType, RESPAWN_ONE_DAY); SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType, RESPAWN_ONE_DAY);
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY); SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY);
@@ -477,7 +486,7 @@ void BattlegroundEY::EventTeamCapturedPoint(TeamId teamId, uint32 point)
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY);
SendMessageToAll(m_CapturingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE); SendBroadcastText(m_CapturingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
} }
else else
{ {
@@ -485,7 +494,7 @@ void BattlegroundEY::EventTeamCapturedPoint(TeamId teamId, uint32 point)
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY);
SendMessageToAll(m_CapturingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE); SendBroadcastText(m_CapturingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE, player);
} }
_capturePointInfo[point]._ownerTeamId = teamId; _capturePointInfo[point]._ownerTeamId = teamId;
@@ -524,12 +533,12 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType
if (player->GetTeamId() == TEAM_ALLIANCE) if (player->GetTeamId() == TEAM_ALLIANCE)
{ {
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE); PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE);
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); SendBroadcastText(BG_EY_TEXT_ALLIANCE_CAPTURED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
} }
else else
{ {
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE); PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE);
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, player); SendBroadcastText(BG_EY_TEXT_HORDE_CAPTURED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, player);
} }
UpdatePlayerScore(player, SCORE_FLAG_CAPTURES, 1); UpdatePlayerScore(player, SCORE_FLAG_CAPTURES, 1);
@@ -537,18 +546,21 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType
AddPoints(player->GetTeamId(), BG_EY_FlagPoints[_ownedPointsCount[player->GetTeamId()] - 1]); AddPoints(player->GetTeamId(), BG_EY_FlagPoints[_ownedPointsCount[player->GetTeamId()] - 1]);
} }
void BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) bool BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{ {
if (type == SCORE_FLAG_CAPTURES) if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
return false;
switch (type)
{ {
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID()); case SCORE_FLAG_CAPTURES:
if (itr != PlayerScores.end())
((BattlegroundEYScore*)itr->second)->FlagCaptures += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_EY_OBJECTIVE_CAPTURE_FLAG); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_EY_OBJECTIVE_CAPTURE_FLAG);
return; break;
default:
break;
} }
Battleground::UpdatePlayerScore(player, type, value, doAddHonor); return true;
} }
void BattlegroundEY::FillInitialWorldStates(WorldPacket& data) void BattlegroundEY::FillInitialWorldStates(WorldPacket& data)
@@ -19,8 +19,9 @@
#define __BATTLEGROUNDEY_H #define __BATTLEGROUNDEY_H
#include "Battleground.h" #include "Battleground.h"
#include "EventMap.h" #include "BattlegroundScore.h"
#include "Language.h" #include "Language.h"
#include "EventMap.h"
enum BG_EY_Events enum BG_EY_Events
{ {
@@ -242,6 +243,35 @@ enum BG_EY_FlagState
BG_EY_FLAG_STATE_ON_GROUND = 3 BG_EY_FLAG_STATE_ON_GROUND = 3
}; };
enum BG_EY_BroadcastTexts
{
BG_EY_TEXT_ALLIANCE_TAKEN_FEL_REAVER_RUINS = 17828,
BG_EY_TEXT_HORDE_TAKEN_FEL_REAVER_RUINS = 17829,
BG_EY_TEXT_ALLIANCE_LOST_FEL_REAVER_RUINS = 17835,
BG_EY_TEXT_HORDE_LOST_FEL_REAVER_RUINS = 17836,
BG_EY_TEXT_ALLIANCE_TAKEN_BLOOD_ELF_TOWER = 17819,
BG_EY_TEXT_HORDE_TAKEN_BLOOD_ELF_TOWER = 17823,
BG_EY_TEXT_ALLIANCE_LOST_BLOOD_ELF_TOWER = 17831,
BG_EY_TEXT_HORDE_LOST_BLOOD_ELF_TOWER = 17832,
BG_EY_TEXT_ALLIANCE_TAKEN_DRAENEI_RUINS = 17827,
BG_EY_TEXT_HORDE_TAKEN_DRAENEI_RUINS = 17826,
BG_EY_TEXT_ALLIANCE_LOST_DRAENEI_RUINS = 17833,
BG_EY_TEXT_HORDE_LOST_DRAENEI_RUINS = 17834,
BG_EY_TEXT_ALLIANCE_TAKEN_MAGE_TOWER = 17824,
BG_EY_TEXT_HORDE_TAKEN_MAGE_TOWER = 17825,
BG_EY_TEXT_ALLIANCE_LOST_MAGE_TOWER = 17837,
BG_EY_TEXT_HORDE_LOST_MAGE_TOWER = 17838,
BG_EY_TEXT_TAKEN_FLAG = 18359,
BG_EY_TEXT_FLAG_DROPPED = 18361,
BG_EY_TEXT_FLAG_RESET = 18364,
BG_EY_TEXT_ALLIANCE_CAPTURED_FLAG = 18375,
BG_EY_TEXT_HORDE_CAPTURED_FLAG = 18384,
};
struct BattlegroundEYPointIconsStruct struct BattlegroundEYPointIconsStruct
{ {
BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex) BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex)
@@ -305,30 +335,48 @@ const BattlegroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] =
const BattlegroundEYLosingPointStruct m_LosingPointTypes[EY_POINTS_MAX] = const BattlegroundEYLosingPointStruct m_LosingPointTypes[EY_POINTS_MAX] =
{ {
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_LOST_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_LOST_H_F_RUINS), BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, BG_EY_TEXT_ALLIANCE_LOST_FEL_REAVER_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, BG_EY_TEXT_HORDE_LOST_FEL_REAVER_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_H_B_TOWER), BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_EY_TEXT_ALLIANCE_LOST_BLOOD_ELF_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_EY_TEXT_HORDE_LOST_BLOOD_ELF_TOWER),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_H_D_RUINS), BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_EY_TEXT_ALLIANCE_LOST_DRAENEI_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_EY_TEXT_HORDE_LOST_DRAENEI_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_H_M_TOWER) BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_EY_TEXT_ALLIANCE_LOST_MAGE_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_EY_TEXT_HORDE_LOST_MAGE_TOWER)
}; };
const BattlegroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] = const BattlegroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] =
{ {
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_TAKEN_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, BG_EY_GRAVEYARD_FEL_REAVER), BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, BG_EY_TEXT_ALLIANCE_TAKEN_FEL_REAVER_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, BG_EY_TEXT_HORDE_TAKEN_FEL_REAVER_RUINS, BG_EY_GRAVEYARD_FEL_REAVER),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, BG_EY_GRAVEYARD_BLOOD_ELF), BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_EY_TEXT_ALLIANCE_TAKEN_BLOOD_ELF_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_EY_TEXT_HORDE_TAKEN_BLOOD_ELF_TOWER, BG_EY_GRAVEYARD_BLOOD_ELF),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, BG_EY_GRAVEYARD_DRAENEI_RUINS), BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_EY_TEXT_ALLIANCE_TAKEN_DRAENEI_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_EY_TEXT_HORDE_TAKEN_DRAENEI_RUINS, BG_EY_GRAVEYARD_DRAENEI_RUINS),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, BG_EY_GRAVEYARD_MAGE_TOWER) BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_EY_TEXT_ALLIANCE_TAKEN_MAGE_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_EY_TEXT_HORDE_TAKEN_MAGE_TOWER, BG_EY_GRAVEYARD_MAGE_TOWER)
}; };
struct BattlegroundEYScore : public BattlegroundScore struct BattlegroundEYScore final : public BattlegroundScore
{ {
BattlegroundEYScore(Player* player) : BattlegroundScore(player), FlagCaptures(0) { } friend class BattlegroundEY;
~BattlegroundEYScore() override { }
uint32 FlagCaptures;
uint32 GetAttr1() const final { return FlagCaptures; } protected:
BattlegroundEYScore(ObjectGuid playerGuid) : BattlegroundScore(playerGuid) { }
void UpdateScore(uint32 type, uint32 value) override
{
switch (type)
{
case SCORE_FLAG_CAPTURES: // Flags captured
FlagCaptures += value;
break;
default:
BattlegroundScore::UpdateScore(type, value);
break;
}
}
void BuildObjectivesBlock(WorldPacket& data) final override;
uint32 GetAttr1() const final override { return FlagCaptures; }
uint32 FlagCaptures = 0;
}; };
class BattlegroundEY : public Battleground class AC_GAME_API BattlegroundEY : public Battleground
{ {
public: public:
BattlegroundEY(); BattlegroundEY();
@@ -354,7 +402,7 @@ public:
bool SetupBattleground() override; bool SetupBattleground() override;
void Init() override; void Init() override;
void EndBattleground(TeamId winnerTeamId) override; void EndBattleground(TeamId winnerTeamId) override;
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override; void FillInitialWorldStates(WorldPacket& data) override;
void SetDroppedFlagGUID(ObjectGuid guid, TeamId /*teamId*/ = TEAM_NEUTRAL) override { _droppedFlagGUID = guid; } void SetDroppedFlagGUID(ObjectGuid guid, TeamId /*teamId*/ = TEAM_NEUTRAL) override { _droppedFlagGUID = guid; }
ObjectGuid GetDroppedFlagGUID() const { return _droppedFlagGUID; } ObjectGuid GetDroppedFlagGUID() const { return _droppedFlagGUID; }
@@ -371,8 +419,8 @@ private:
void PostUpdateImpl(uint32 diff) override; void PostUpdateImpl(uint32 diff) override;
void EventPlayerCapturedFlag(Player* Source, uint32 BgObjectType); void EventPlayerCapturedFlag(Player* Source, uint32 BgObjectType);
void EventTeamLostPoint(TeamId teamId, uint32 point); void EventTeamLostPoint(Player* player, uint32 point);
void EventTeamCapturedPoint(TeamId teamId, uint32 point); void EventTeamCapturedPoint(Player* player, TeamId teamId, uint32 point);
void UpdatePointsCount(); void UpdatePointsCount();
void UpdatePointsIcons(uint32 point); void UpdatePointsIcons(uint32 point);
@@ -393,7 +441,8 @@ private:
TeamId _ownerTeamId; TeamId _ownerTeamId;
int8 _barStatus; int8 _barStatus;
uint32 _areaTrigger; uint32 _areaTrigger;
int8 _playersCount[BG_TEAMS_COUNT]; int8 _playersCount[PVP_TEAMS_COUNT];
Player* player = nullptr;
bool IsUnderControl(TeamId teamId) const { return _ownerTeamId == teamId; } bool IsUnderControl(TeamId teamId) const { return _ownerTeamId == teamId; }
bool IsUnderControl() const { return _ownerTeamId != TEAM_NEUTRAL; } bool IsUnderControl() const { return _ownerTeamId != TEAM_NEUTRAL; }
@@ -403,7 +452,7 @@ private:
CapturePointInfo _capturePointInfo[EY_POINTS_MAX]; CapturePointInfo _capturePointInfo[EY_POINTS_MAX];
EventMap _bgEvents; EventMap _bgEvents;
uint32 _honorTics; uint32 _honorTics;
uint8 _ownedPointsCount[BG_TEAMS_COUNT]; uint8 _ownedPointsCount[PVP_TEAMS_COUNT];
ObjectGuid _flagKeeperGUID; ObjectGuid _flagKeeperGUID;
ObjectGuid _droppedFlagGUID; ObjectGuid _droppedFlagGUID;
uint8 _flagState; uint8 _flagState;
@@ -29,16 +29,18 @@
#include "WorldPacket.h" #include "WorldPacket.h"
#include "WorldSession.h" #include "WorldSession.h"
void BattlegroundICScore::BuildObjectivesBlock(WorldPacket& data)
{
data << uint32(2); // Objectives Count
data << uint32(BasesAssaulted);
data << uint32(BasesDefended);
}
BattlegroundIC::BattlegroundIC() BattlegroundIC::BattlegroundIC()
{ {
BgObjects.resize(MAX_NORMAL_GAMEOBJECTS_SPAWNS + MAX_AIRSHIPS_SPAWNS + MAX_HANGAR_TELEPORTERS_SPAWNS + MAX_FORTRESS_TELEPORTERS_SPAWNS + MAX_HANGAR_TELEPORTER_EFFECTS_SPAWNS + MAX_FORTRESS_TELEPORTER_EFFECTS_SPAWNS); BgObjects.resize(MAX_NORMAL_GAMEOBJECTS_SPAWNS + MAX_AIRSHIPS_SPAWNS + MAX_HANGAR_TELEPORTERS_SPAWNS + MAX_FORTRESS_TELEPORTERS_SPAWNS + MAX_HANGAR_TELEPORTER_EFFECTS_SPAWNS + MAX_FORTRESS_TELEPORTER_EFFECTS_SPAWNS);
BgCreatures.resize(MAX_NORMAL_NPCS_SPAWNS + MAX_WORKSHOP_SPAWNS + MAX_DOCKS_SPAWNS + MAX_SPIRIT_GUIDES_SPAWNS + MAX_HANGAR_NPCS_SPAWNS); BgCreatures.resize(MAX_NORMAL_NPCS_SPAWNS + MAX_WORKSHOP_SPAWNS + MAX_DOCKS_SPAWNS + MAX_SPIRIT_GUIDES_SPAWNS + MAX_HANGAR_NPCS_SPAWNS);
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_IC_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_IC_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_IC_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_IC_HAS_BEGUN;
for (uint8 i = 0; i < 2; ++i) for (uint8 i = 0; i < 2; ++i)
factionReinforcements[i] = MAX_REINFORCEMENTS; factionReinforcements[i] = MAX_REINFORCEMENTS;
@@ -60,10 +62,6 @@ BattlegroundIC::BattlegroundIC()
respawnMap.clear(); respawnMap.clear();
} }
BattlegroundIC::~BattlegroundIC()
{
}
void BattlegroundIC::DoAction(uint32 action, ObjectGuid guid) void BattlegroundIC::DoAction(uint32 action, ObjectGuid guid)
{ {
if (action != ACTION_TELEPORT_PLAYER_TO_TRANSPORT) if (action != ACTION_TELEPORT_PLAYER_TO_TRANSPORT)
@@ -246,7 +244,14 @@ void BattlegroundIC::PostUpdateImpl(uint32 diff)
UpdateNodeWorldState(&nodePoint[i]); UpdateNodeWorldState(&nodePoint[i]);
HandleCapturedNodes(&nodePoint[i], false); HandleCapturedNodes(&nodePoint[i], false);
SendMessage2ToAll(LANG_BG_IC_TEAM_HAS_TAKEN_NODE, CHAT_MSG_BG_SYSTEM_NEUTRAL, nullptr, (nodePoint[i].faction == TEAM_ALLIANCE ? LANG_BG_IC_ALLIANCE : LANG_BG_IC_HORDE), nodePoint[i].string); if (nodePoint[i].faction == TEAM_ALLIANCE)
{
SendBroadcastText(ICNodes[i].TextAllianceTaken, CHAT_MSG_BG_SYSTEM_ALLIANCE);
}
else
{
SendBroadcastText(ICNodes[i].TextHordeTaken, CHAT_MSG_BG_SYSTEM_HORDE);
}
nodePoint[i].needChange = false; nodePoint[i].needChange = false;
nodePoint[i].timer = BANNER_STATE_CHANGE_TIME; nodePoint[i].timer = BANNER_STATE_CHANGE_TIME;
@@ -272,10 +277,6 @@ void BattlegroundIC::PostUpdateImpl(uint32 diff)
else resourceTimer -= diff; else resourceTimer -= diff;
} }
void BattlegroundIC::StartingEventCloseDoors()
{
}
void BattlegroundIC::StartingEventOpenDoors() void BattlegroundIC::StartingEventOpenDoors()
{ {
//after 20 seconds they should be despawned //after 20 seconds they should be despawned
@@ -320,7 +321,7 @@ bool BattlegroundIC::IsResourceGlutAllowed(TeamId teamId) const
void BattlegroundIC::AddPlayer(Player* player) void BattlegroundIC::AddPlayer(Player* player)
{ {
Battleground::AddPlayer(player); Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundICScore(player); PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundICScore(player->GetGUID()));
if (nodePoint[NODE_TYPE_QUARRY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) if (nodePoint[NODE_TYPE_QUARRY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H))
player->CastSpell(player, SPELL_QUARRY, true); player->CastSpell(player, SPELL_QUARRY, true);
@@ -364,26 +365,22 @@ void BattlegroundIC::HandleAreaTrigger(Player* player, uint32 trigger)
} }
} }
void BattlegroundIC::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) bool BattlegroundIC::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{ {
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID()); if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
if (itr == PlayerScores.end()) return false;
return;
switch (type) switch (type)
{ {
case SCORE_BASES_ASSAULTED: case SCORE_BASES_ASSAULTED:
((BattlegroundICScore*)itr->second)->BasesAssaulted += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, IC_OBJECTIVE_ASSAULT_BASE); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, IC_OBJECTIVE_ASSAULT_BASE);
break; break;
case SCORE_BASES_DEFENDED: case SCORE_BASES_DEFENDED:
((BattlegroundICScore*)itr->second)->BasesDefended += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, IC_OBJECTIVE_DEFEND_BASE); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, IC_OBJECTIVE_DEFEND_BASE);
break; break;
default:
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break;
} }
return true;
} }
void BattlegroundIC::FillInitialWorldStates(WorldPacket& data) void BattlegroundIC::FillInitialWorldStates(WorldPacket& data)
@@ -553,12 +550,6 @@ void BattlegroundIC::HandleKillPlayer(Player* player, Player* killer)
EndBattleground(killer->GetTeamId()); EndBattleground(killer->GetTeamId());
} }
void BattlegroundIC::EndBattleground(TeamId winnerTeamId)
{
SendMessage2ToAll(LANG_BG_IC_TEAM_WINS, CHAT_MSG_BG_SYSTEM_NEUTRAL, nullptr, (winnerTeamId == TEAM_ALLIANCE ? LANG_BG_IC_ALLIANCE : LANG_BG_IC_HORDE));
Battleground::EndBattleground(winnerTeamId);
}
void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject) void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject)
{ {
if (GetStatus() != STATUS_IN_PROGRESS) if (GetStatus() != STATUS_IN_PROGRESS)
@@ -621,8 +612,15 @@ void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1);
SendMessage2ToAll(LANG_BG_IC_TEAM_ASSAULTED_NODE_1, CHAT_MSG_BG_SYSTEM_NEUTRAL, player, point.string); if (nodePoint[i].faction == TEAM_ALLIANCE)
SendMessage2ToAll(LANG_BG_IC_TEAM_ASSAULTED_NODE_2, CHAT_MSG_BG_SYSTEM_NEUTRAL, player, point.string, (player->GetTeamId() == TEAM_ALLIANCE ? LANG_BG_IC_ALLIANCE : LANG_BG_IC_HORDE)); {
SendBroadcastText(ICNodes[i].TextAssaulted, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
SendBroadcastText(ICNodes[i].TextAssaulted, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
HandleContestedNodes(&point); HandleContestedNodes(&point);
} }
else if (nextBanner == point.banners[BANNER_A_CONTROLLED] || nextBanner == point.banners[BANNER_H_CONTROLLED]) else if (nextBanner == point.banners[BANNER_A_CONTROLLED] || nextBanner == point.banners[BANNER_H_CONTROLLED])
@@ -630,7 +628,16 @@ void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
{ {
point.timer = BANNER_STATE_CHANGE_TIME; point.timer = BANNER_STATE_CHANGE_TIME;
point.needChange = false; point.needChange = false;
SendMessage2ToAll(LANG_BG_IC_TEAM_DEFENDED_NODE, CHAT_MSG_BG_SYSTEM_NEUTRAL, player, point.string);
if (nodePoint[i].faction == TEAM_ALLIANCE)
{
SendBroadcastText(ICNodes[i].TextDefended, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
SendBroadcastText(ICNodes[i].TextDefended, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
HandleCapturedNodes(&point, true); HandleCapturedNodes(&point, true);
UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1);
} }
@@ -926,33 +933,41 @@ void BattlegroundIC::DestroyGate(Player* /*player*/, GameObject* go)
UpdateWorldState(uws_open, 1); UpdateWorldState(uws_open, 1);
} }
uint32 textId;
ChatMsg msgType;
TeamId teamId = TEAM_ALLIANCE; TeamId teamId = TEAM_ALLIANCE;
uint32 lang_entry = 0;
switch (go->GetEntry()) switch (go->GetEntry())
{ {
case GO_HORDE_GATE_1: case GO_HORDE_GATE_1:
lang_entry = LANG_BG_IC_NORTH_GATE_DESTROYED; textId = BG_IC_TEXT_FRONT_GATE_HORDE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE;
break; break;
case GO_HORDE_GATE_2: case GO_HORDE_GATE_2:
lang_entry = LANG_BG_IC_EAST_GATE_DESTROYED; textId = BG_IC_TEXT_WEST_GATE_HORDE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE;
break; break;
case GO_HORDE_GATE_3: case GO_HORDE_GATE_3:
lang_entry = LANG_BG_IC_WEST_GATE_DESTROYED; textId = BG_IC_TEXT_EAST_GATE_HORDE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE;
break; break;
case GO_ALLIANCE_GATE_1: case GO_ALLIANCE_GATE_1:
textId = BG_IC_TEXT_WEST_GATE_ALLIANCE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_HORDE;
teamId = TEAM_HORDE; teamId = TEAM_HORDE;
lang_entry = LANG_BG_IC_WEST_GATE_DESTROYED;
break; break;
case GO_ALLIANCE_GATE_2: case GO_ALLIANCE_GATE_2:
textId = BG_IC_TEXT_EAST_GATE_ALLIANCE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_HORDE;
teamId = TEAM_HORDE; teamId = TEAM_HORDE;
lang_entry = LANG_BG_IC_EAST_GATE_DESTROYED;
break; break;
case GO_ALLIANCE_GATE_3: case GO_ALLIANCE_GATE_3:
textId = BG_IC_TEXT_FRONT_GATE_ALLIANCE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_HORDE;
teamId = TEAM_HORDE; teamId = TEAM_HORDE;
lang_entry = LANG_BG_IC_SOUTH_GATE_DESTROYED;
break; break;
default: default:
break; return;
} }
if (teamId == TEAM_ALLIANCE) if (teamId == TEAM_ALLIANCE)
@@ -967,11 +982,7 @@ void BattlegroundIC::DestroyGate(Player* /*player*/, GameObject* go)
} }
TurnBosses(true); TurnBosses(true);
SendMessage2ToAll(lang_entry, CHAT_MSG_BG_SYSTEM_NEUTRAL, nullptr, (teamId == TEAM_ALLIANCE ? LANG_BG_IC_HORDE_KEEP : LANG_BG_IC_ALLIANCE_KEEP)); SendBroadcastText(textId, msgType);
}
void BattlegroundIC::EventPlayerDamagedGO(Player* /*player*/, GameObject* /*go*/, uint32 /*eventType*/)
{
} }
GraveyardStruct const* BattlegroundIC::GetClosestGraveyard(Player* player) GraveyardStruct const* BattlegroundIC::GetClosestGraveyard(Player* player)
@@ -19,10 +19,10 @@
#define __BATTLEGROUNDIC_H #define __BATTLEGROUNDIC_H
#include "Battleground.h" #include "Battleground.h"
#include "Language.h" #include "BattlegroundScore.h"
#include "Object.h" #include "Object.h"
const uint32 BG_IC_Factions[BG_TEAMS_COUNT] = const uint32 BG_IC_Factions[PVP_TEAMS_COUNT] =
{ {
1732, // Alliance 1732, // Alliance
1735 // Horde 1735 // Horde
@@ -854,6 +854,36 @@ const float BG_IC_SpiritGuidePos[MAX_NODE_TYPES + 2][4] =
{1148.65f, -1250.98f, 16.60f, 1.74f}, // last resort horde {1148.65f, -1250.98f, 16.60f, 1.74f}, // last resort horde
}; };
enum ICBroadcastTexts
{
BG_IC_TEXT_FRONT_GATE_HORDE_DESTROYED = 35409,
BG_IC_TEXT_FRONT_GATE_ALLIANCE_DESTROYED = 35410,
BG_IC_TEXT_WEST_GATE_HORDE_DESTROYED = 35411,
BG_IC_TEXT_WEST_GATE_ALLIANCE_DESTROYED = 35412,
BG_IC_TEXT_EAST_GATE_HORDE_DESTROYED = 35413,
BG_IC_TEXT_EAST_GATE_ALLIANCE_DESTROYED = 35414
};
struct ICNodeInfo
{
uint32 NodeId;
uint32 TextAssaulted;
uint32 TextDefended;
uint32 TextAllianceTaken;
uint32 TextHordeTaken;
};
ICNodeInfo const ICNodes[MAX_NODE_TYPES] =
{
{ NODE_TYPE_REFINERY, 35377, 35378, 35379, 35380 },
{ NODE_TYPE_QUARRY, 35373, 35374, 35375, 35376 },
{ NODE_TYPE_DOCKS, 35365, 35366, 35367, 35368 },
{ NODE_TYPE_HANGAR, 35369, 35370, 35371, 35372 },
{ NODE_TYPE_WORKSHOP, 35278, 35286, 35279, 35280 },
{ NODE_TYPE_GRAVEYARD_A, 35461, 35459, 35463, 35466 },
{ NODE_TYPE_GRAVEYARD_H, 35462, 35460, 35464, 35465 }
};
// I.E: Hangar, Quarry, Graveyards .. etc // I.E: Hangar, Quarry, Graveyards .. etc
struct ICNodePoint struct ICNodePoint
{ {
@@ -867,18 +897,17 @@ struct ICNodePoint
uint32 last_entry; // the last gameobject_entry uint32 last_entry; // the last gameobject_entry
uint32 worldStates[5]; // the worldstates that represent the node in the map uint32 worldStates[5]; // the worldstates that represent the node in the map
ICNodeState nodeState; ICNodeState nodeState;
uint32 string;
}; };
const ICNodePoint nodePointInitial[7] = const ICNodePoint nodePointInitial[MAX_NODE_TYPES] =
{ {
{BG_IC_GO_REFINERY_BANNER, GO_REFINERY_BANNER, TEAM_NEUTRAL, NODE_TYPE_REFINERY, {GO_ALLIANCE_BANNER_REFINERY, GO_ALLIANCE_BANNER_REFINERY_CONT, GO_HORDE_BANNER_REFINERY, GO_HORDE_BANNER_REFINERY_CONT}, false, 0, 0, {BG_IC_REFINERY_UNCONTROLLED, BG_IC_REFINERY_CONFLICT_A, BG_IC_REFINERY_CONFLICT_H, BG_IC_REFINERY_CONTROLLED_A, BG_IC_REFINERY_CONTROLLED_H}, NODE_STATE_UNCONTROLLED, LANG_BG_IC_REFINERY}, {BG_IC_GO_REFINERY_BANNER, GO_REFINERY_BANNER, TEAM_NEUTRAL, NODE_TYPE_REFINERY, {GO_ALLIANCE_BANNER_REFINERY, GO_ALLIANCE_BANNER_REFINERY_CONT, GO_HORDE_BANNER_REFINERY, GO_HORDE_BANNER_REFINERY_CONT}, false, 0, 0, {BG_IC_REFINERY_UNCONTROLLED, BG_IC_REFINERY_CONFLICT_A, BG_IC_REFINERY_CONFLICT_H, BG_IC_REFINERY_CONTROLLED_A, BG_IC_REFINERY_CONTROLLED_H}, NODE_STATE_UNCONTROLLED},
{BG_IC_GO_QUARRY_BANNER, GO_QUARRY_BANNER, TEAM_NEUTRAL, NODE_TYPE_QUARRY, {GO_ALLIANCE_BANNER_QUARRY, GO_ALLIANCE_BANNER_QUARRY_CONT, GO_HORDE_BANNER_QUARRY, GO_HORDE_BANNER_QUARRY_CONT}, false, 0, 0, {BG_IC_QUARRY_UNCONTROLLED, BG_IC_QUARRY_CONFLICT_A, BG_IC_QUARRY_CONFLICT_H, BG_IC_QUARRY_CONTROLLED_A, BG_IC_QUARRY_CONTROLLED_H}, NODE_STATE_UNCONTROLLED, LANG_BG_IC_QUARRY}, {BG_IC_GO_QUARRY_BANNER, GO_QUARRY_BANNER, TEAM_NEUTRAL, NODE_TYPE_QUARRY, {GO_ALLIANCE_BANNER_QUARRY, GO_ALLIANCE_BANNER_QUARRY_CONT, GO_HORDE_BANNER_QUARRY, GO_HORDE_BANNER_QUARRY_CONT}, false, 0, 0, {BG_IC_QUARRY_UNCONTROLLED, BG_IC_QUARRY_CONFLICT_A, BG_IC_QUARRY_CONFLICT_H, BG_IC_QUARRY_CONTROLLED_A, BG_IC_QUARRY_CONTROLLED_H}, NODE_STATE_UNCONTROLLED},
{BG_IC_GO_DOCKS_BANNER, GO_DOCKS_BANNER, TEAM_NEUTRAL, NODE_TYPE_DOCKS, {GO_ALLIANCE_BANNER_DOCK, GO_ALLIANCE_BANNER_DOCK_CONT, GO_HORDE_BANNER_DOCK, GO_HORDE_BANNER_DOCK_CONT}, false, 0, 0, {BG_IC_DOCKS_UNCONTROLLED, BG_IC_DOCKS_CONFLICT_A, BG_IC_DOCKS_CONFLICT_H, BG_IC_DOCKS_CONTROLLED_A, BG_IC_DOCKS_CONTROLLED_H}, NODE_STATE_UNCONTROLLED, LANG_BG_IC_DOCKS}, {BG_IC_GO_DOCKS_BANNER, GO_DOCKS_BANNER, TEAM_NEUTRAL, NODE_TYPE_DOCKS, {GO_ALLIANCE_BANNER_DOCK, GO_ALLIANCE_BANNER_DOCK_CONT, GO_HORDE_BANNER_DOCK, GO_HORDE_BANNER_DOCK_CONT}, false, 0, 0, {BG_IC_DOCKS_UNCONTROLLED, BG_IC_DOCKS_CONFLICT_A, BG_IC_DOCKS_CONFLICT_H, BG_IC_DOCKS_CONTROLLED_A, BG_IC_DOCKS_CONTROLLED_H}, NODE_STATE_UNCONTROLLED},
{BG_IC_GO_HANGAR_BANNER, GO_HANGAR_BANNER, TEAM_NEUTRAL, NODE_TYPE_HANGAR, {GO_ALLIANCE_BANNER_HANGAR, GO_ALLIANCE_BANNER_HANGAR_CONT, GO_HORDE_BANNER_HANGAR, GO_HORDE_BANNER_HANGAR_CONT}, false, 0, 0, {BG_IC_HANGAR_UNCONTROLLED, BG_IC_HANGAR_CONFLICT_A, BG_IC_HANGAR_CONFLICT_H, BG_IC_HANGAR_CONTROLLED_A, BG_IC_HANGAR_CONTROLLED_H}, NODE_STATE_UNCONTROLLED, LANG_BG_IC_HANGAR}, {BG_IC_GO_HANGAR_BANNER, GO_HANGAR_BANNER, TEAM_NEUTRAL, NODE_TYPE_HANGAR, {GO_ALLIANCE_BANNER_HANGAR, GO_ALLIANCE_BANNER_HANGAR_CONT, GO_HORDE_BANNER_HANGAR, GO_HORDE_BANNER_HANGAR_CONT}, false, 0, 0, {BG_IC_HANGAR_UNCONTROLLED, BG_IC_HANGAR_CONFLICT_A, BG_IC_HANGAR_CONFLICT_H, BG_IC_HANGAR_CONTROLLED_A, BG_IC_HANGAR_CONTROLLED_H}, NODE_STATE_UNCONTROLLED},
{BG_IC_GO_WORKSHOP_BANNER, GO_WORKSHOP_BANNER, TEAM_NEUTRAL, NODE_TYPE_WORKSHOP, {GO_ALLIANCE_BANNER_WORKSHOP, GO_ALLIANCE_BANNER_WORKSHOP_CONT, GO_HORDE_BANNER_WORKSHOP, GO_HORDE_BANNER_WORKSHOP_CONT}, false, 0, 0, {BG_IC_WORKSHOP_UNCONTROLLED, BG_IC_WORKSHOP_CONFLICT_A, BG_IC_WORKSHOP_CONFLICT_H, BG_IC_WORKSHOP_CONTROLLED_A, BG_IC_WORKSHOP_CONTROLLED_H}, NODE_STATE_UNCONTROLLED, LANG_BG_IC_WORKSHOP}, {BG_IC_GO_WORKSHOP_BANNER, GO_WORKSHOP_BANNER, TEAM_NEUTRAL, NODE_TYPE_WORKSHOP, {GO_ALLIANCE_BANNER_WORKSHOP, GO_ALLIANCE_BANNER_WORKSHOP_CONT, GO_HORDE_BANNER_WORKSHOP, GO_HORDE_BANNER_WORKSHOP_CONT}, false, 0, 0, {BG_IC_WORKSHOP_UNCONTROLLED, BG_IC_WORKSHOP_CONFLICT_A, BG_IC_WORKSHOP_CONFLICT_H, BG_IC_WORKSHOP_CONTROLLED_A, BG_IC_WORKSHOP_CONTROLLED_H}, NODE_STATE_UNCONTROLLED},
{BG_IC_GO_ALLIANCE_BANNER, GO_ALLIANCE_BANNER, TEAM_ALLIANCE, NODE_TYPE_GRAVEYARD_A, {GO_ALLIANCE_BANNER_GRAVEYARD_A, GO_ALLIANCE_BANNER_GRAVEYARD_A_CONT, GO_HORDE_BANNER_GRAVEYARD_A, GO_HORDE_BANNER_GRAVEYARD_A_CONT}, false, 0, 0, {BG_IC_ALLIANCE_KEEP_UNCONTROLLED, BG_IC_ALLIANCE_KEEP_CONFLICT_A, BG_IC_ALLIANCE_KEEP_CONFLICT_H, BG_IC_ALLIANCE_KEEP_CONTROLLED_A, BG_IC_ALLIANCE_KEEP_CONTROLLED_H}, NODE_STATE_CONTROLLED_A, LANG_BG_IC_ALLIANCE_KEEP}, {BG_IC_GO_ALLIANCE_BANNER, GO_ALLIANCE_BANNER, TEAM_ALLIANCE, NODE_TYPE_GRAVEYARD_A, {GO_ALLIANCE_BANNER_GRAVEYARD_A, GO_ALLIANCE_BANNER_GRAVEYARD_A_CONT, GO_HORDE_BANNER_GRAVEYARD_A, GO_HORDE_BANNER_GRAVEYARD_A_CONT}, false, 0, 0, {BG_IC_ALLIANCE_KEEP_UNCONTROLLED, BG_IC_ALLIANCE_KEEP_CONFLICT_A, BG_IC_ALLIANCE_KEEP_CONFLICT_H, BG_IC_ALLIANCE_KEEP_CONTROLLED_A, BG_IC_ALLIANCE_KEEP_CONTROLLED_H}, NODE_STATE_CONTROLLED_A},
{BG_IC_GO_HORDE_BANNER, GO_HORDE_BANNER, TEAM_HORDE, NODE_TYPE_GRAVEYARD_H, {GO_ALLIANCE_BANNER_GRAVEYARD_H, GO_ALLIANCE_BANNER_GRAVEYARD_H_CONT, GO_HORDE_BANNER_GRAVEYARD_H, GO_HORDE_BANNER_GRAVEYARD_H_CONT}, false, 0, 0, {BG_IC_HORDE_KEEP_UNCONTROLLED, BG_IC_HORDE_KEEP_CONFLICT_A, BG_IC_HORDE_KEEP_CONFLICT_H, BG_IC_HORDE_KEEP_CONTROLLED_A, BG_IC_HORDE_KEEP_CONTROLLED_H}, NODE_STATE_CONTROLLED_H, LANG_BG_IC_HORDE_KEEP} {BG_IC_GO_HORDE_BANNER, GO_HORDE_BANNER, TEAM_HORDE, NODE_TYPE_GRAVEYARD_H, {GO_ALLIANCE_BANNER_GRAVEYARD_H, GO_ALLIANCE_BANNER_GRAVEYARD_H_CONT, GO_HORDE_BANNER_GRAVEYARD_H, GO_HORDE_BANNER_GRAVEYARD_H_CONT}, false, 0, 0, {BG_IC_HORDE_KEEP_UNCONTROLLED, BG_IC_HORDE_KEEP_CONFLICT_A, BG_IC_HORDE_KEEP_CONFLICT_H, BG_IC_HORDE_KEEP_CONTROLLED_A, BG_IC_HORDE_KEEP_CONTROLLED_H}, NODE_STATE_CONTROLLED_H}
}; };
enum HonorRewards enum HonorRewards
@@ -887,45 +916,63 @@ enum HonorRewards
WINNER_HONOR_AMOUNT = 500 WINNER_HONOR_AMOUNT = 500
}; };
struct BattlegroundICScore : public BattlegroundScore struct BattlegroundICScore final : public BattlegroundScore
{ {
BattlegroundICScore(Player* player) : BattlegroundScore(player), BasesAssaulted(0), BasesDefended(0) { } friend class BattlegroundIC;
~BattlegroundICScore() override { }
uint32 BasesAssaulted;
uint32 BasesDefended;
uint32 GetAttr1() const final { return BasesAssaulted; } protected:
uint32 GetAttr2() const final { return BasesDefended; } BattlegroundICScore(ObjectGuid playerGuid) : BattlegroundScore(playerGuid) { }
void UpdateScore(uint32 type, uint32 value) override
{
switch (type)
{
case SCORE_BASES_ASSAULTED:
BasesAssaulted += value;
break;
case SCORE_BASES_DEFENDED:
BasesDefended += value;
break;
default:
BattlegroundScore::UpdateScore(type, value);
break;
}
}
void BuildObjectivesBlock(WorldPacket& data) final override;
uint32 GetAttr1() const final override { return BasesAssaulted; }
uint32 GetAttr2() const final override { return BasesDefended; }
uint32 BasesAssaulted = 0;
uint32 BasesDefended = 0;
}; };
class BattlegroundIC : public Battleground class AC_GAME_API BattlegroundIC : public Battleground
{ {
public: public:
BattlegroundIC(); BattlegroundIC();
~BattlegroundIC() override;
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
void AddPlayer(Player* player) override; void AddPlayer(Player* player) override;
void StartingEventCloseDoors() override; void StartingEventCloseDoors() override { }
void StartingEventOpenDoors() override; void StartingEventOpenDoors() override;
void PostUpdateImpl(uint32 diff) override; void PostUpdateImpl(uint32 diff) override;
void RemovePlayer(Player* player) override; void RemovePlayer(Player* player) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override; void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override; bool SetupBattleground() override;
void SpawnLeader(uint32 teamid);
void HandleKillUnit(Creature* unit, Player* killer) override; void HandleKillUnit(Creature* unit, Player* killer) override;
void HandleKillPlayer(Player* player, Player* killer) override; void HandleKillPlayer(Player* player, Player* killer) override;
void EndBattleground(TeamId winnerTeamId) override;
void EventPlayerClickedOnFlag(Player* source, GameObject* /*gameObject*/) override; void EventPlayerClickedOnFlag(Player* source, GameObject* /*gameObject*/) override;
void EventPlayerDamagedGO(Player* /*player*/, GameObject* go, uint32 eventType) override; void EventPlayerDamagedGO(Player* /*player*/, GameObject* /*go*/, uint32 /*eventType*/) override { }
void DestroyGate(Player* player, GameObject* go) override; void DestroyGate(Player* player, GameObject* go) override;
GraveyardStruct const* GetClosestGraveyard(Player* player) override; GraveyardStruct const* GetClosestGraveyard(Player* player) override;
/* Scorekeeping */ /* Scorekeeping */
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void FillInitialWorldStates(WorldPacket& data) override; void FillInitialWorldStates(WorldPacket& data) override;
@@ -16,28 +16,12 @@
*/ */
#include "BattlegroundNA.h" #include "BattlegroundNA.h"
#include "Language.h"
#include "ObjectMgr.h"
#include "Player.h" #include "Player.h"
#include "WorldPacket.h" #include "WorldPacket.h"
BattlegroundNA::BattlegroundNA() BattlegroundNA::BattlegroundNA()
{ {
BgObjects.resize(BG_NA_OBJECT_MAX); BgObjects.resize(BG_NA_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundNA::~BattlegroundNA()
{
} }
void BattlegroundNA::StartingEventCloseDoors() void BattlegroundNA::StartingEventCloseDoors()
@@ -55,39 +39,6 @@ void BattlegroundNA::StartingEventOpenDoors()
SpawnBGObject(i, 60); SpawnBGObject(i, 60);
} }
void BattlegroundNA::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundNA::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundNA::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
LOG_ERROR("bg.battleground", "BattlegroundNA: Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundNA::HandlePlayerUnderMap(Player* player) bool BattlegroundNA::HandlePlayerUnderMap(Player* player)
{ {
player->NearTeleportTo(4055.504395f, 2919.660645f, 13.611241f, player->GetOrientation()); player->NearTeleportTo(4055.504395f, 2919.660645f, 13.611241f, player->GetOrientation());
@@ -116,13 +67,7 @@ void BattlegroundNA::HandleAreaTrigger(Player* player, uint32 trigger)
void BattlegroundNA::FillInitialWorldStates(WorldPacket& data) void BattlegroundNA::FillInitialWorldStates(WorldPacket& data)
{ {
data << uint32(0xa11) << uint32(1); // 9 data << uint32(0xa11) << uint32(1); // 9
Battleground::UpdateArenaWorldState(); Arena::FillInitialWorldStates(data);
}
void BattlegroundNA::Init()
{
//call parent's class reset
Battleground::Init();
} }
bool BattlegroundNA::SetupBattleground() bool BattlegroundNA::SetupBattleground()
@@ -18,7 +18,7 @@
#ifndef __BATTLEGROUNDNA_H #ifndef __BATTLEGROUNDNA_H
#define __BATTLEGROUNDNA_H #define __BATTLEGROUNDNA_H
#include "Battleground.h" #include "Arena.h"
enum BattlegroundNAObjectTypes enum BattlegroundNAObjectTypes
{ {
@@ -33,7 +33,7 @@ enum BattlegroundNAObjectTypes
BG_NA_OBJECT_MAX = 8 BG_NA_OBJECT_MAX = 8
}; };
enum BattlegroundNAObjects enum BattlegroundNAGameObjects
{ {
BG_NA_OBJECT_TYPE_DOOR_1 = 183978, BG_NA_OBJECT_TYPE_DOOR_1 = 183978,
BG_NA_OBJECT_TYPE_DOOR_2 = 183980, BG_NA_OBJECT_TYPE_DOOR_2 = 183980,
@@ -43,23 +43,19 @@ enum BattlegroundNAObjects
BG_NA_OBJECT_TYPE_BUFF_2 = 184664 BG_NA_OBJECT_TYPE_BUFF_2 = 184664
}; };
class BattlegroundNA : public Battleground class AC_GAME_API BattlegroundNA : public Arena
{ {
public: public:
BattlegroundNA(); BattlegroundNA();
~BattlegroundNA() override;
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
void AddPlayer(Player* player) override;
void StartingEventCloseDoors() override; void StartingEventCloseDoors() override;
void StartingEventOpenDoors() override; void StartingEventOpenDoors() override;
void RemovePlayer(Player* player) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override; void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override; bool SetupBattleground() override;
void Init() override;
void FillInitialWorldStates(WorldPacket& d) override; void FillInitialWorldStates(WorldPacket& d) override;
void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* player) override; bool HandlePlayerUnderMap(Player* player) override;
}; };
#endif #endif
@@ -16,6 +16,7 @@
*/ */
#include "BattlegroundRL.h" #include "BattlegroundRL.h"
#include "ArenaScore.h"
#include "Language.h" #include "Language.h"
#include "Log.h" #include "Log.h"
#include "Player.h" #include "Player.h"
@@ -24,20 +25,6 @@
BattlegroundRL::BattlegroundRL() BattlegroundRL::BattlegroundRL()
{ {
BgObjects.resize(BG_RL_OBJECT_MAX); BgObjects.resize(BG_RL_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundRL::~BattlegroundRL()
{
} }
void BattlegroundRL::StartingEventCloseDoors() void BattlegroundRL::StartingEventCloseDoors()
@@ -55,39 +42,6 @@ void BattlegroundRL::StartingEventOpenDoors()
SpawnBGObject(i, 60); SpawnBGObject(i, 60);
} }
void BattlegroundRL::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundRL::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundRL::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
LOG_ERROR("bg.battleground", "Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundRL::HandlePlayerUnderMap(Player* player) bool BattlegroundRL::HandlePlayerUnderMap(Player* player)
{ {
player->NearTeleportTo(1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation()); player->NearTeleportTo(1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation());
@@ -142,13 +96,7 @@ void BattlegroundRL::HandleAreaTrigger(Player* player, uint32 trigger)
void BattlegroundRL::FillInitialWorldStates(WorldPacket& data) void BattlegroundRL::FillInitialWorldStates(WorldPacket& data)
{ {
data << uint32(0xbba) << uint32(1); // 9 data << uint32(0xbba) << uint32(1); // 9
Battleground::UpdateArenaWorldState(); Arena::FillInitialWorldStates(data);
}
void BattlegroundRL::Init()
{
//call parent's reset
Battleground::Init();
} }
bool BattlegroundRL::SetupBattleground() bool BattlegroundRL::SetupBattleground()
@@ -18,7 +18,7 @@
#ifndef __BATTLEGROUNDRL_H #ifndef __BATTLEGROUNDRL_H
#define __BATTLEGROUNDRL_H #define __BATTLEGROUNDRL_H
#include "Battleground.h" #include "Arena.h"
enum BattlegroundRLObjectTypes enum BattlegroundRLObjectTypes
{ {
@@ -39,23 +39,19 @@ enum BattlegroundRLObjects
BG_RL_OBJECT_TYPE_BUFF_2 = 184664 BG_RL_OBJECT_TYPE_BUFF_2 = 184664
}; };
class BattlegroundRL : public Battleground class AC_GAME_API BattlegroundRL : public Arena
{ {
public: public:
BattlegroundRL(); BattlegroundRL();
~BattlegroundRL() override;
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
void AddPlayer(Player* player) override;
void Init() override;
void FillInitialWorldStates(WorldPacket& d) override; void FillInitialWorldStates(WorldPacket& d) override;
void StartingEventCloseDoors() override; void StartingEventCloseDoors() override;
void StartingEventOpenDoors() override; void StartingEventOpenDoors() override;
void RemovePlayer(Player* player) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override; void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override; bool SetupBattleground() override;
void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* player) override; bool HandlePlayerUnderMap(Player* player) override;
}; };
#endif #endif
@@ -16,6 +16,7 @@
*/ */
#include "BattlegroundRV.h" #include "BattlegroundRV.h"
#include "ArenaScore.h"
#include "Battleground.h" #include "Battleground.h"
#include "GameObject.h" #include "GameObject.h"
#include "Language.h" #include "Language.h"
@@ -35,24 +36,16 @@ BattlegroundRV::BattlegroundRV()
{ {
BgObjects.resize(BG_RV_OBJECT_MAX); BgObjects.resize(BG_RV_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; _checkPlayersTimer = 0;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; _timer = 0s;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; _state = 0;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
CheckPlayersTimer = 0;
} }
BattlegroundRV::~BattlegroundRV() { }
void BattlegroundRV::TeleportUnitToNewZ(Unit* unit, float newZ, bool casting) void BattlegroundRV::TeleportUnitToNewZ(Unit* unit, float newZ, bool casting)
{ {
if (!unit->IsAlive()) if (!unit->IsAlive())
return; return;
unit->NearTeleportTo(unit->GetPositionX(), unit->GetPositionY(), newZ, unit->GetOrientation(), casting); unit->NearTeleportTo(unit->GetPositionX(), unit->GetPositionY(), newZ, unit->GetOrientation(), casting);
unit->m_positionZ = newZ; unit->m_positionZ = newZ;
} }
@@ -64,6 +57,7 @@ void BattlegroundRV::CheckPositionForUnit(Unit* unit)
{ {
float groundZ_vmap = unit->GetMap()->GetHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, true, 50.0f); float groundZ_vmap = unit->GetMap()->GetHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, true, 50.0f);
float groundZ_dyntree = unit->GetMap()->GetDynamicMapTree().getHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, 50.0f, unit->GetPhaseMask()); float groundZ_dyntree = unit->GetMap()->GetDynamicMapTree().getHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, 50.0f, unit->GetPhaseMask());
if ((groundZ_vmap > 28.0f && groundZ_vmap < 29.0f) || (groundZ_dyntree > 28.0f && groundZ_dyntree < 37.0f)) if ((groundZ_vmap > 28.0f && groundZ_vmap < 29.0f) || (groundZ_dyntree > 28.0f && groundZ_dyntree < 37.0f))
{ {
float groundZ = std::max<float>(groundZ_vmap, groundZ_dyntree); float groundZ = std::max<float>(groundZ_vmap, groundZ_dyntree);
@@ -78,19 +72,23 @@ void BattlegroundRV::PostUpdateImpl(uint32 diff)
if (GetStatus() != STATUS_IN_PROGRESS) if (GetStatus() != STATUS_IN_PROGRESS)
return; return;
if (GetTimer() < Milliseconds(diff)) if (_timer < Milliseconds(diff))
{ {
switch (getState()) switch (_state)
{ {
case BG_RV_STATE_OPEN_FENCES: case BG_RV_STATE_OPEN_FENCES:
{
for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i) for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i)
DoorOpen(i); DoorOpen(i);
SetTimer(BG_RV_CLOSE_FIRE_TIMER);
setState(BG_RV_STATE_CLOSE_FIRE);
for (auto itr = m_Players.begin(); itr != m_Players.end(); ++itr) _timer = BG_RV_CLOSE_FIRE_TIMER;
if (Player* player = itr->second) _state = BG_RV_STATE_CLOSE_FIRE;
for (auto const& [playerGuid, player] : m_Players)
{ {
if (!player)
continue;
// Demonic Circle Summon // Demonic Circle Summon
if (GameObject* gObj = player->GetGameObject(48018)) if (GameObject* gObj = player->GetGameObject(48018))
{ {
@@ -130,45 +128,43 @@ void BattlegroundRV::PostUpdateImpl(uint32 diff)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_TRANSPORT); go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_TRANSPORT);
} }
break; break;
}
case BG_RV_STATE_CLOSE_FIRE: case BG_RV_STATE_CLOSE_FIRE:
for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i) for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i)
DoorClose(i); DoorClose(i);
// Fire got closed after five seconds, leaves twenty seconds before toggling pillars // Fire got closed after five seconds, leaves twenty seconds before toggling pillars
SetTimer(BG_RV_FIRE_TO_PILLAR_TIMER); _timer = BG_RV_FIRE_TO_PILLAR_TIMER;
setState(BG_RV_STATE_SWITCH_PILLARS); _state = BG_RV_STATE_SWITCH_PILLARS;
break; break;
case BG_RV_STATE_SWITCH_PILLARS: case BG_RV_STATE_SWITCH_PILLARS:
UpdatePillars(); UpdatePillars();
SetTimer(BG_RV_PILLAR_SWITCH_TIMER); _timer = BG_RV_PILLAR_SWITCH_TIMER;
break; break;
} }
} }
else else
SetTimer(GetTimer() - Milliseconds(diff)); _timer -= Milliseconds(diff);
if (getState() == BG_RV_STATE_OPEN_FENCES) if (_state == BG_RV_STATE_OPEN_FENCES)
return; return;
if (CheckPlayersTimer <= diff) if (_checkPlayersTimer <= diff)
{ {
CheckPlayersTimer = 0; _checkPlayersTimer = 0;
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
CheckPositionForUnit(itr->second); for (auto const& itr : m_Players)
CheckPositionForUnit(itr.second);
// maybe for pets and m_Controlled also, but not really necessary // maybe for pets and m_Controlled also, but not really necessary
} }
else else
CheckPlayersTimer -= diff; _checkPlayersTimer -= diff;
}
void BattlegroundRV::StartingEventCloseDoors()
{
} }
void BattlegroundRV::StartingEventOpenDoors() void BattlegroundRV::StartingEventOpenDoors()
{ {
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) for (auto const& itr : m_Players)
itr->second->SetPhaseMask(1, true); itr.second->SetPhaseMask(1, true);
// Buff respawn // Buff respawn
SpawnBGObject(BG_RV_OBJECT_BUFF_1, 90); SpawnBGObject(BG_RV_OBJECT_BUFF_1, 90);
@@ -178,44 +174,8 @@ void BattlegroundRV::StartingEventOpenDoors()
DoorOpen(BG_RV_OBJECT_ELEVATOR_1); DoorOpen(BG_RV_OBJECT_ELEVATOR_1);
DoorOpen(BG_RV_OBJECT_ELEVATOR_2); DoorOpen(BG_RV_OBJECT_ELEVATOR_2);
setState(BG_RV_STATE_OPEN_FENCES); _state = BG_RV_STATE_OPEN_FENCES;
SetTimer(BG_RV_FIRST_TIMER); _timer = BG_RV_FIRST_TIMER;
}
void BattlegroundRV::AddPlayer(Player* player)
{
if (GetStatus() == STATUS_WAIT_JOIN && player->GetBgTeamId() == TEAM_HORDE)
player->SetPhaseMask(2, true);
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
BattlegroundRV::UpdateArenaWorldState();
}
void BattlegroundRV::RemovePlayer(Player* player)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
if (GetStatus() == STATUS_WAIT_JOIN)
player->SetPhaseMask(1, true);
BattlegroundRV::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundRV::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
return;
Battleground::HandleKillPlayer(player, killer);
BattlegroundRV::UpdateArenaWorldState();
CheckArenaWinConditions();
} }
bool BattlegroundRV::HandlePlayerUnderMap(Player* player) bool BattlegroundRV::HandlePlayerUnderMap(Player* player)
@@ -226,7 +186,7 @@ bool BattlegroundRV::HandlePlayerUnderMap(Player* player)
void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger) void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger)
{ {
if (GetStatus() != STATUS_IN_PROGRESS || getState() == BG_RV_STATE_OPEN_FENCES /*during elevator rising it's possible to jump and cause areatrigger*/) if (GetStatus() != STATUS_IN_PROGRESS || _state == BG_RV_STATE_OPEN_FENCES /*during elevator rising it's possible to jump and cause areatrigger*/)
return; return;
switch (trigger) switch (trigger)
@@ -251,13 +211,7 @@ void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger)
void BattlegroundRV::FillInitialWorldStates(WorldPacket& data) void BattlegroundRV::FillInitialWorldStates(WorldPacket& data)
{ {
data << uint32(BG_RV_WORLD_STATE) << uint32(1); data << uint32(BG_RV_WORLD_STATE) << uint32(1);
BattlegroundRV::UpdateArenaWorldState(); Arena::FillInitialWorldStates(data);
}
void BattlegroundRV::UpdateArenaWorldState()
{
UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(TEAM_HORDE));
} }
void BattlegroundRV::Init() void BattlegroundRV::Init()
@@ -352,5 +306,6 @@ GameObject* BattlegroundRV::GetPillarAtPosition(Position* p)
uint32 pillar = GetPillarIdForPos(p); uint32 pillar = GetPillarIdForPos(p);
if (!pillar) if (!pillar)
return nullptr; return nullptr;
return GetBgMap()->GetGameObject(BgObjects[pillar]); return GetBgMap()->GetGameObject(BgObjects[pillar]);
} }
@@ -18,7 +18,7 @@
#ifndef __BATTLEGROUNDRV_H #ifndef __BATTLEGROUNDRV_H
#define __BATTLEGROUNDRV_H #define __BATTLEGROUNDRV_H
#include "Battleground.h" #include "Arena.h"
enum BattlegroundRVObjectTypes enum BattlegroundRVObjectTypes
{ {
@@ -48,7 +48,7 @@ enum BattlegroundRVObjectTypes
BG_RV_OBJECT_MAX, BG_RV_OBJECT_MAX,
}; };
enum BattlegroundRVObjects enum BattlegroundRVGameObjects
{ {
BG_RV_OBJECT_TYPE_BUFF_1 = 184663, BG_RV_OBJECT_TYPE_BUFF_1 = 184663,
BG_RV_OBJECT_TYPE_BUFF_2 = 184664, BG_RV_OBJECT_TYPE_BUFF_2 = 184664,
@@ -82,43 +82,33 @@ enum BattlegroundRVData
BG_RV_WORLD_STATE = 0xe1a, BG_RV_WORLD_STATE = 0xe1a,
}; };
class BattlegroundRV : public Battleground class AC_GAME_API BattlegroundRV : public Arena
{ {
public: public:
BattlegroundRV(); BattlegroundRV();
~BattlegroundRV() override;
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
void AddPlayer(Player* player) override;
void RemovePlayer(Player* player) override;
void StartingEventCloseDoors() override;
void StartingEventOpenDoors() override; void StartingEventOpenDoors() override;
void Init() override; void Init() override;
void FillInitialWorldStates(WorldPacket& d) override; void FillInitialWorldStates(WorldPacket& d) override;
void UpdateArenaWorldState() override;
void HandleAreaTrigger(Player* player, uint32 trigger) override; void HandleAreaTrigger(Player* player, uint32 trigger) override;
bool SetupBattleground() override; bool SetupBattleground() override;
void HandleKillPlayer(Player* player, Player* killer) override;
bool HandlePlayerUnderMap(Player* player) override; bool HandlePlayerUnderMap(Player* player) override;
GameObject* GetPillarAtPosition(Position* p); GameObject* GetPillarAtPosition(Position* p);
private: private:
Milliseconds Timer; Milliseconds _timer;
uint32 State; uint32 _state;
uint16 CheckPlayersTimer; uint16 _checkPlayersTimer;
void PostUpdateImpl(uint32 diff) override; void PostUpdateImpl(uint32 diff) override;
protected: protected:
Milliseconds GetTimer() { return Timer; }
void SetTimer(Milliseconds timer) { Timer = timer; }
uint32 getState() { return State; };
void setState(uint32 state) { State = state; }
void TeleportUnitToNewZ(Unit* unit, float newZ, bool casting); void TeleportUnitToNewZ(Unit* unit, float newZ, bool casting);
void CheckPositionForUnit(Unit* unit); void CheckPositionForUnit(Unit* unit);
void UpdatePillars(); void UpdatePillars();
uint32 GetPillarIdForPos(Position* p); uint32 GetPillarIdForPos(Position* p);
}; };
#endif #endif
@@ -29,12 +29,16 @@ constexpr Milliseconds BG_SA_BOAT_START = 1min;
constexpr Milliseconds BG_SA_WARMUPLENGTH = 2min; constexpr Milliseconds BG_SA_WARMUPLENGTH = 2min;
constexpr Milliseconds BG_SA_ROUNDLENGTH = 10min; constexpr Milliseconds BG_SA_ROUNDLENGTH = 10min;
void BattlegroundSAScore::BuildObjectivesBlock(WorldPacket& data)
{
data << uint32(2); // Objectives Count
data << uint32(DemolishersDestroyed);
data << uint32(GatesDestroyed);
}
BattlegroundSA::BattlegroundSA() BattlegroundSA::BattlegroundSA()
{ {
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_SA_START_TWO_MINUTES; StartMessageIds[BG_STARTING_EVENT_FOURTH] = 0;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_SA_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_SA_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_SA_HAS_BEGUN;
BgObjects.resize(BG_SA_MAXOBJ); BgObjects.resize(BG_SA_MAXOBJ);
BgCreatures.resize(static_cast<uint16>(BG_SA_MAXNPC) + BG_SA_MAX_GY); BgCreatures.resize(static_cast<uint16>(BG_SA_MAXNPC) + BG_SA_MAX_GY);
TimerEnabled = false; TimerEnabled = false;
@@ -318,7 +322,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
{ {
SignaledRoundTwo = true; SignaledRoundTwo = true;
InitSecondRound = false; InitSecondRound = false;
SendMessageToAll(LANG_BG_SA_ROUND_TWO_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendBroadcastText(BG_SA_TEXT_ROUND_TWO_START_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
} }
} }
else else
@@ -370,7 +374,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
if (!SignaledRoundTwoHalfMin) if (!SignaledRoundTwoHalfMin)
{ {
SignaledRoundTwoHalfMin = true; SignaledRoundTwoHalfMin = true;
SendMessageToAll(LANG_BG_SA_ROUND_TWO_START_HALF_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendBroadcastText(BG_SA_TEXT_ROUND_TWO_START_HALF_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
} }
} }
StartShips(); StartShips();
@@ -496,11 +500,9 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
void BattlegroundSA::AddPlayer(Player* player) void BattlegroundSA::AddPlayer(Player* player)
{ {
Battleground::AddPlayer(player); Battleground::AddPlayer(player);
//create score and add it to map, default values are set in constructor PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundSAScore(player->GetGUID()));
BattlegroundSAScore* sc = new BattlegroundSAScore(player);
SendTransportInit(player); SendTransportInit(player);
PlayerScores[player->GetGUID()] = sc;
TeleportToEntrancePosition(player); TeleportToEntrancePosition(player);
} }
@@ -515,20 +517,6 @@ void BattlegroundSA::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/)
return; return;
} }
void BattlegroundSA::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
if (itr == PlayerScores.end())
return;
if (type == SCORE_DESTROYED_DEMOLISHER)
((BattlegroundSAScore*)itr->second)->demolishers_destroyed += value;
else if (type == SCORE_DESTROYED_WALL)
((BattlegroundSAScore*)itr->second)->gates_destroyed += value;
else
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
}
void BattlegroundSA::TeleportPlayers() void BattlegroundSA::TeleportPlayers()
{ {
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
@@ -19,17 +19,7 @@
#define __BATTLEGROUNDSA_H #define __BATTLEGROUNDSA_H
#include "Battleground.h" #include "Battleground.h"
#include "BattlegroundScore.h"
struct BattlegroundSAScore : public BattlegroundScore
{
BattlegroundSAScore(Player* player) : BattlegroundScore(player), demolishers_destroyed(0), gates_destroyed(0) { }
~BattlegroundSAScore() override { }
uint8 demolishers_destroyed;
uint8 gates_destroyed;
uint32 GetAttr1() const final { return demolishers_destroyed; }
uint32 GetAttr2() const final { return gates_destroyed; }
};
#define BG_SA_FLAG_AMOUNT 3 #define BG_SA_FLAG_AMOUNT 3
#define BG_SA_DEMOLISHER_AMOUNT 4 #define BG_SA_DEMOLISHER_AMOUNT 4
@@ -405,6 +395,15 @@ float const BG_SA_GYOrientation[BG_SA_MAX_GY] =
6.148f, // defender last GY 6.148f, // defender last GY
}; };
enum BG_SA_BroadcastTexts
{
BG_SA_TEXT_ALLIANCE_CAPTURED_TITAN_PORTAL = 28944,
BG_SA_TEXT_HORDE_CAPTURED_TITAN_PORTAL = 28945,
BG_SA_TEXT_ROUND_TWO_START_ONE_MINUTE = 29448,
BG_SA_TEXT_ROUND_TWO_START_HALF_MINUTE = 29449
};
struct BG_SA_RoundScore struct BG_SA_RoundScore
{ {
TeamId winner; TeamId winner;
@@ -420,8 +419,40 @@ const float SOTADefPortalDest[5][4] =
{ 1193.857f, 69.9f, 58.046f, 5.7245f }, { 1193.857f, 69.9f, 58.046f, 5.7245f },
}; };
struct BattlegroundSAScore final : public BattlegroundScore
{
friend class BattlegroundSA;
protected:
BattlegroundSAScore(ObjectGuid playerGuid) : BattlegroundScore(playerGuid) { }
void UpdateScore(uint32 type, uint32 value) override
{
switch (type)
{
case SCORE_DESTROYED_DEMOLISHER:
DemolishersDestroyed += value;
break;
case SCORE_DESTROYED_WALL:
GatesDestroyed += value;
break;
default:
BattlegroundScore::UpdateScore(type, value);
break;
}
}
void BuildObjectivesBlock(WorldPacket& data) final override;
uint32 GetAttr1() const final override { return DemolishersDestroyed; }
uint32 GetAttr2() const final override { return GatesDestroyed; }
uint32 DemolishersDestroyed = 0;
uint32 GatesDestroyed = 0;
};
/// Class for manage Strand of Ancient battleground /// Class for manage Strand of Ancient battleground
class BattlegroundSA : public Battleground class AC_GAME_API BattlegroundSA : public Battleground
{ {
public: public:
BattlegroundSA(); BattlegroundSA();
@@ -491,10 +522,6 @@ public:
void RemovePlayer(Player* player) override; void RemovePlayer(Player* player) override;
void HandleAreaTrigger(Player* player, uint32 trigger) override; void HandleAreaTrigger(Player* player, uint32 trigger) override;
/* Scorekeeping */
/// Update score board
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
// Teleporters // Teleporters
void DefendersPortalTeleport(GameObject* portal, Player* plr); void DefendersPortalTeleport(GameObject* portal, Player* plr);
@@ -620,6 +647,6 @@ private:
bool _relicClicked; bool _relicClicked;
// Achievement: Not Even a Scratch // Achievement: Not Even a Scratch
bool _notEvenAScratch[BG_TEAMS_COUNT]; bool _notEvenAScratch[PVP_TEAMS_COUNT];
}; };
#endif #endif
@@ -26,15 +26,21 @@
#include "World.h" #include "World.h"
#include "WorldPacket.h" #include "WorldPacket.h"
void BattlegroundWGScore::BuildObjectivesBlock(WorldPacket& data)
{
data << uint32(2); // Objectives Count
data << uint32(FlagCaptures);
data << uint32(FlagReturns);
}
BattlegroundWS::BattlegroundWS() BattlegroundWS::BattlegroundWS()
{ {
BgObjects.resize(BG_WS_OBJECT_MAX); BgObjects.resize(BG_WS_OBJECT_MAX);
BgCreatures.resize(BG_CREATURES_MAX_WS); BgCreatures.resize(BG_CREATURES_MAX_WS);
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; StartMessageIds[BG_STARTING_EVENT_SECOND] = BG_WS_TEXT_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; StartMessageIds[BG_STARTING_EVENT_THIRD] = BG_WS_TEXT_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; StartMessageIds[BG_STARTING_EVENT_FOURTH] = BG_WS_TEXT_BATTLE_HAS_BEGUN;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
_flagState[TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; _flagState[TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE;
_flagState[TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; _flagState[TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
@@ -68,7 +74,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff)
case BG_WS_EVENT_RESPAWN_BOTH_FLAGS: case BG_WS_EVENT_RESPAWN_BOTH_FLAGS:
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendBroadcastText(BG_WS_TEXT_FLAGS_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
break; break;
case BG_WS_EVENT_ALLIANCE_DROP_FLAG: case BG_WS_EVENT_ALLIANCE_DROP_FLAG:
@@ -134,7 +140,7 @@ void BattlegroundWS::StartingEventOpenDoors()
void BattlegroundWS::AddPlayer(Player* player) void BattlegroundWS::AddPlayer(Player* player)
{ {
Battleground::AddPlayer(player); Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundWGScore(player); PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundWGScore(player->GetGUID()));
} }
void BattlegroundWS::RespawnFlagAfterDrop(TeamId teamId) void BattlegroundWS::RespawnFlagAfterDrop(TeamId teamId)
@@ -144,7 +150,7 @@ void BattlegroundWS::RespawnFlagAfterDrop(TeamId teamId)
UpdateFlagState(teamId, BG_WS_FLAG_STATE_ON_BASE); UpdateFlagState(teamId, BG_WS_FLAG_STATE_ON_BASE);
SpawnBGObject(teamId == TEAM_ALLIANCE ? BG_WS_OBJECT_A_FLAG : BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); SpawnBGObject(teamId == TEAM_ALLIANCE ? BG_WS_OBJECT_A_FLAG : BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(teamId == TEAM_ALLIANCE ? LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED : LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendBroadcastText(BG_WS_TEXT_FLAGS_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
if (GameObject* flag = GetBgMap()->GetGameObject(GetDroppedFlagGUID(teamId))) if (GameObject* flag = GetBgMap()->GetGameObject(GetDroppedFlagGUID(teamId)))
@@ -187,18 +193,19 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* player)
AddPoints(player->GetTeamId(), 1); AddPoints(player->GetTeamId(), 1);
SetFlagPicker(ObjectGuid::Empty, GetOtherTeamId(player->GetTeamId())); SetFlagPicker(ObjectGuid::Empty, GetOtherTeamId(player->GetTeamId()));
UpdateFlagState(GetOtherTeamId(player->GetTeamId()), BG_WS_FLAG_STATE_ON_BASE); UpdateFlagState(GetOtherTeamId(player->GetTeamId()), BG_WS_FLAG_STATE_ON_BASE);
if (player->GetTeamId() == TEAM_ALLIANCE) if (player->GetTeamId() == TEAM_ALLIANCE)
{ {
player->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); player->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE);
SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); SendBroadcastText(BG_WS_TEXT_CAPTURED_HORDE_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
RewardReputationToTeam(890, _reputationCapture, TEAM_ALLIANCE); RewardReputationToTeam(890, _reputationCapture, TEAM_ALLIANCE);
} }
else else
{ {
player->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); player->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE); PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE);
SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, player); SendBroadcastText(BG_WS_TEXT_CAPTURED_ALLIANCE_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, player);
RewardReputationToTeam(889, _reputationCapture, TEAM_HORDE); RewardReputationToTeam(889, _reputationCapture, TEAM_HORDE);
} }
@@ -241,14 +248,14 @@ void BattlegroundWS::EventPlayerDroppedFlag(Player* player)
{ {
UpdateFlagState(TEAM_HORDE, BG_WS_FLAG_STATE_ON_GROUND); UpdateFlagState(TEAM_HORDE, BG_WS_FLAG_STATE_ON_GROUND);
player->CastSpell(player, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true); player->CastSpell(player, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true);
SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, player); SendBroadcastText(BG_WS_TEXT_HORDE_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_HORDE, player);
_bgEvents.RescheduleEvent(BG_WS_EVENT_HORDE_DROP_FLAG, BG_WS_FLAG_DROP_TIME); _bgEvents.RescheduleEvent(BG_WS_EVENT_HORDE_DROP_FLAG, BG_WS_FLAG_DROP_TIME);
} }
else else
{ {
UpdateFlagState(TEAM_ALLIANCE, BG_WS_FLAG_STATE_ON_GROUND); UpdateFlagState(TEAM_ALLIANCE, BG_WS_FLAG_STATE_ON_GROUND);
player->CastSpell(player, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true); player->CastSpell(player, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true);
SendMessageToAll(LANG_BG_WS_DROPPED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); SendBroadcastText(BG_WS_TEXT_ALLIANCE_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
_bgEvents.RescheduleEvent(BG_WS_EVENT_ALLIANCE_DROP_FLAG, BG_WS_FLAG_DROP_TIME); _bgEvents.RescheduleEvent(BG_WS_EVENT_ALLIANCE_DROP_FLAG, BG_WS_FLAG_DROP_TIME);
} }
} }
@@ -270,7 +277,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED); player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED);
PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_AF, CHAT_MSG_BG_SYSTEM_HORDE, player); SendBroadcastText(BG_WS_TEXT_ALLIANCE_FLAG_PICKED_UP, CHAT_MSG_BG_SYSTEM_HORDE, player);
if (GetFlagState(TEAM_HORDE) != BG_WS_FLAG_STATE_ON_BASE) if (GetFlagState(TEAM_HORDE) != BG_WS_FLAG_STATE_ON_BASE)
{ {
@@ -290,7 +297,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED); player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED);
PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); SendBroadcastText(BG_WS_TEXT_HORDE_FLAG_PICKED_UP, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
if (GetFlagState(TEAM_ALLIANCE) != BG_WS_FLAG_STATE_ON_BASE) if (GetFlagState(TEAM_ALLIANCE) != BG_WS_FLAG_STATE_ON_BASE)
{ {
@@ -315,7 +322,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1); UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED);
SendMessageToAll(LANG_BG_WS_RETURNED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); SendBroadcastText(BG_WS_TEXT_ALLIANCE_FLAG_RETURNED, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10); _bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15); _bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras(); RemoveAssaultAuras();
@@ -332,7 +339,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
player->CastSpell(player, assaultSpellId, true); player->CastSpell(player, assaultSpellId, true);
PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_AF, CHAT_MSG_BG_SYSTEM_HORDE, player); SendBroadcastText(BG_WS_TEXT_ALLIANCE_FLAG_PICKED_UP, CHAT_MSG_BG_SYSTEM_HORDE, player);
return; return;
} }
} }
@@ -348,7 +355,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1); UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED);
SendMessageToAll(LANG_BG_WS_RETURNED_HF, CHAT_MSG_BG_SYSTEM_HORDE, player); SendBroadcastText(BG_WS_TEXT_HORDE_FLAG_RETURNED, CHAT_MSG_BG_SYSTEM_HORDE, player);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10); _bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15); _bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras(); RemoveAssaultAuras();
@@ -365,7 +372,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
player->CastSpell(player, assaultSpellId, true); player->CastSpell(player, assaultSpellId, true);
PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP);
SendMessageToAll(LANG_BG_WS_PICKEDUP_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); SendBroadcastText(BG_WS_TEXT_HORDE_FLAG_PICKED_UP, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
return; return;
} }
} }
@@ -509,26 +516,22 @@ void BattlegroundWS::HandleKillPlayer(Player* player, Player* killer)
Battleground::HandleKillPlayer(player, killer); Battleground::HandleKillPlayer(player, killer);
} }
void BattlegroundWS::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) bool BattlegroundWS::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{ {
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID()); if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor))
if (itr == PlayerScores.end()) return false;
return;
switch (type) switch (type)
{ {
case SCORE_FLAG_CAPTURES: case SCORE_FLAG_CAPTURES:
((BattlegroundWGScore*)itr->second)->FlagCaptures += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG);
break; break;
case SCORE_FLAG_RETURNS: case SCORE_FLAG_RETURNS:
((BattlegroundWGScore*)itr->second)->FlagReturns += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG);
break; break;
default:
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break;
} }
return true;
} }
GraveyardStruct const* BattlegroundWS::GetClosestGraveyard(Player* player) GraveyardStruct const* BattlegroundWS::GetClosestGraveyard(Player* player)
@@ -19,6 +19,7 @@
#define __BATTLEGROUNDWS_H #define __BATTLEGROUNDWS_H
#include "Battleground.h" #include "Battleground.h"
#include "BattlegroundScore.h"
#include "EventMap.h" #include "EventMap.h"
enum BG_WS_Events enum BG_WS_Events
@@ -43,6 +44,23 @@ enum BG_WS_TimerOrScore
BG_WS_SPELL_BRUTAL_TIME = 15 * MINUTE * IN_MILLISECONDS BG_WS_SPELL_BRUTAL_TIME = 15 * MINUTE * IN_MILLISECONDS
}; };
enum BG_WS_BroadcastTexts
{
BG_WS_TEXT_START_ONE_MINUTE = 10015,
BG_WS_TEXT_START_HALF_MINUTE = 10016,
BG_WS_TEXT_BATTLE_HAS_BEGUN = 10014,
BG_WS_TEXT_CAPTURED_HORDE_FLAG = 9801,
BG_WS_TEXT_CAPTURED_ALLIANCE_FLAG = 9802,
BG_WS_TEXT_FLAGS_PLACED = 9803,
BG_WS_TEXT_ALLIANCE_FLAG_PICKED_UP = 9804,
BG_WS_TEXT_ALLIANCE_FLAG_DROPPED = 9805,
BG_WS_TEXT_HORDE_FLAG_PICKED_UP = 9807,
BG_WS_TEXT_HORDE_FLAG_DROPPED = 9806,
BG_WS_TEXT_ALLIANCE_FLAG_RETURNED = 9808,
BG_WS_TEXT_HORDE_FLAG_RETURNED = 9809,
};
enum BG_WS_Sound enum BG_WS_Sound
{ {
BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE = 8173,
@@ -164,18 +182,39 @@ enum BG_WS_Trigger
BG_WS_TRIGGER_HORDE_ELIXIR_BERSERK_SPAWN = 3709, BG_WS_TRIGGER_HORDE_ELIXIR_BERSERK_SPAWN = 3709,
}; };
struct BattlegroundWGScore : public BattlegroundScore struct BattlegroundWGScore final : public BattlegroundScore
{ {
BattlegroundWGScore(Player* player): BattlegroundScore(player), FlagCaptures(0), FlagReturns(0) { } friend class BattlegroundWS;
~BattlegroundWGScore() override { }
uint32 FlagCaptures;
uint32 FlagReturns;
uint32 GetAttr1() const final { return FlagCaptures; } protected:
uint32 GetAttr2() const final { return FlagReturns; } BattlegroundWGScore(ObjectGuid playerGuid) : BattlegroundScore(playerGuid) { }
void UpdateScore(uint32 type, uint32 value) override
{
switch (type)
{
case SCORE_FLAG_CAPTURES: // Flags captured
FlagCaptures += value;
break;
case SCORE_FLAG_RETURNS: // Flags returned
FlagReturns += value;
break;
default:
BattlegroundScore::UpdateScore(type, value);
break;
}
}
void BuildObjectivesBlock(WorldPacket& data) final override;
uint32 GetAttr1() const final override { return FlagCaptures; }
uint32 GetAttr2() const final override { return FlagReturns; }
uint32 FlagCaptures = 0;
uint32 FlagReturns = 0;
}; };
class BattlegroundWS : public Battleground class AC_GAME_API BattlegroundWS : public Battleground
{ {
public: public:
/* Construction */ /* Construction */
@@ -208,7 +247,7 @@ public:
GraveyardStruct const* GetClosestGraveyard(Player* player) override; GraveyardStruct const* GetClosestGraveyard(Player* player) override;
void UpdateFlagState(TeamId teamId, uint32 value); void UpdateFlagState(TeamId teamId, uint32 value);
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override;
void SetDroppedFlagGUID(ObjectGuid guid, TeamId teamId) override { _droppedFlagGUID[teamId] = guid; } void SetDroppedFlagGUID(ObjectGuid guid, TeamId teamId) override { _droppedFlagGUID[teamId] = guid; }
ObjectGuid GetDroppedFlagGUID(TeamId teamId) const { return _droppedFlagGUID[teamId];} ObjectGuid GetDroppedFlagGUID(TeamId teamId) const { return _droppedFlagGUID[teamId];}
void FillInitialWorldStates(WorldPacket& data) override; void FillInitialWorldStates(WorldPacket& data) override;
@@ -234,4 +273,5 @@ private:
void PostUpdateImpl(uint32 diff) override; void PostUpdateImpl(uint32 diff) override;
}; };
#endif #endif
@@ -340,7 +340,7 @@ void WorldSession::HandlePVPLogDataOpcode(WorldPacket& /*recvData*/)
return; return;
WorldPacket data; WorldPacket data;
sBattlegroundMgr->BuildPvpLogDataPacket(&data, bg); bg->BuildPvPLogDataPacket(data);
SendPacket(&data); SendPacket(&data);
LOG_DEBUG("network", "WORLD: Sent MSG_PVP_LOG_DATA Message"); LOG_DEBUG("network", "WORLD: Sent MSG_PVP_LOG_DATA Message");
@@ -94,7 +94,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
// TODO: find correct opcode // TODO: find correct opcode
if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{ {
SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
return; return;
} }
+6 -110
View File
@@ -645,79 +645,7 @@ enum AcoreStrings
// End Level 3 list, continued at 1100 // End Level 3 list, continued at 1100
// Battleground // 600-704 - free
LANG_BG_A_WINS = 600,
LANG_BG_H_WINS = 601,
LANG_BG_WS_START_TWO_MINUTES = 753,
LANG_BG_WS_START_ONE_MINUTE = 602,
LANG_BG_WS_START_HALF_MINUTE = 603,
LANG_BG_WS_HAS_BEGUN = 604,
LANG_BG_WS_CAPTURED_HF = 605,
LANG_BG_WS_CAPTURED_AF = 606,
LANG_BG_WS_DROPPED_HF = 607,
LANG_BG_WS_DROPPED_AF = 608,
LANG_BG_WS_RETURNED_AF = 609,
LANG_BG_WS_RETURNED_HF = 610,
LANG_BG_WS_PICKEDUP_HF = 611,
LANG_BG_WS_PICKEDUP_AF = 612,
LANG_BG_WS_F_PLACED = 613,
LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED = 614,
LANG_BG_WS_HORDE_FLAG_RESPAWNED = 615,
LANG_BG_EY_START_TWO_MINUTES = 755,
LANG_BG_EY_START_ONE_MINUTE = 636,
LANG_BG_EY_START_HALF_MINUTE = 637,
LANG_BG_EY_HAS_BEGUN = 638,
LANG_BG_AB_ALLY = 650,
LANG_BG_AB_HORDE = 651,
LANG_BG_AB_NODE_STABLES = 652,
LANG_BG_AB_NODE_BLACKSMITH = 653,
LANG_BG_AB_NODE_FARM = 654,
LANG_BG_AB_NODE_LUMBER_MILL = 655,
LANG_BG_AB_NODE_GOLD_MINE = 656,
LANG_BG_AB_NODE_TAKEN = 657,
LANG_BG_AB_NODE_DEFENDED = 658,
LANG_BG_AB_NODE_ASSAULTED = 659,
LANG_BG_AB_NODE_CLAIMED = 660,
LANG_BG_AB_START_TWO_MINUTES = 754,
LANG_BG_AB_START_ONE_MINUTE = 661,
LANG_BG_AB_START_HALF_MINUTE = 662,
LANG_BG_AB_HAS_BEGUN = 663,
LANG_BG_AB_A_NEAR_VICTORY = 664,
LANG_BG_AB_H_NEAR_VICTORY = 665,
LANG_BG_MARK_BY_MAIL = 666,
LANG_BG_EY_HAS_TAKEN_A_M_TOWER = 667,
LANG_BG_EY_HAS_TAKEN_H_M_TOWER = 668,
LANG_BG_EY_HAS_TAKEN_A_D_RUINS = 669,
LANG_BG_EY_HAS_TAKEN_H_D_RUINS = 670,
LANG_BG_EY_HAS_TAKEN_A_B_TOWER = 671,
LANG_BG_EY_HAS_TAKEN_H_B_TOWER = 672,
LANG_BG_EY_HAS_TAKEN_A_F_RUINS = 673,
LANG_BG_EY_HAS_TAKEN_H_F_RUINS = 674,
LANG_BG_EY_HAS_LOST_A_M_TOWER = 675,
LANG_BG_EY_HAS_LOST_H_M_TOWER = 676,
LANG_BG_EY_HAS_LOST_A_D_RUINS = 677,
LANG_BG_EY_HAS_LOST_H_D_RUINS = 678,
LANG_BG_EY_HAS_LOST_A_B_TOWER = 679,
LANG_BG_EY_HAS_LOST_H_B_TOWER = 680,
LANG_BG_EY_HAS_LOST_A_F_RUINS = 681,
LANG_BG_EY_HAS_LOST_H_F_RUINS = 682,
LANG_BG_EY_HAS_TAKEN_FLAG = 683,
LANG_BG_EY_CAPTURED_FLAG_A = 684,
LANG_BG_EY_CAPTURED_FLAG_H = 685,
LANG_BG_EY_DROPPED_FLAG = 686,
LANG_BG_EY_RESETED_FLAG = 687,
LANG_ARENA_ONE_TOOLOW = 700,
LANG_ARENA_ONE_MINUTE = 701,
LANG_ARENA_THIRTY_SECONDS = 702,
LANG_ARENA_FIFTEEN_SECONDS = 703,
LANG_ARENA_HAS_BEGUN = 704,
LANG_WAIT_BEFORE_SPEAKING = 705, LANG_WAIT_BEFORE_SPEAKING = 705,
LANG_NOT_EQUIPPED_ITEM = 706, LANG_NOT_EQUIPPED_ITEM = 706,
@@ -745,9 +673,7 @@ enum AcoreStrings
LANG_ARENA_GROUP_TOO_LARGE = 721, // "Your group is too large for this arena. Please regroup to join." LANG_ARENA_GROUP_TOO_LARGE = 721, // "Your group is too large for this arena. Please regroup to join."
LANG_ARENA_YOUR_TEAM_ONLY = 722, // "Your group has members not in your arena team. Please regroup to join." LANG_ARENA_YOUR_TEAM_ONLY = 722, // "Your group has members not in your arena team. Please regroup to join."
LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match." LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match."
LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!" // 724-726 - free
LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!"
// = 726, see LANG_ARENA_QUEUE_ANNOUNCE_WORLD
LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining." LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining."
LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group." LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group."
LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group." LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group."
@@ -775,9 +701,6 @@ enum AcoreStrings
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins."
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds."
// = 752, see LANG_PINFO_ACC_IP // = 752, see LANG_PINFO_ACC_IP
// LANG_BG_WS_START_TWO_MINUTES = 753, - defined above
// LANG_BG_AB_START_TWO_MINUTES = 754, - defined above
// LANG_BG_EY_START_TWO_MINUTES = 755, - defined above
// Room for BG/ARENA = 773-784, 788-799 not used // Room for BG/ARENA = 773-784, 788-799 not used
LANG_ARENA_TESTING = 785, LANG_ARENA_TESTING = 785,
@@ -1030,32 +953,9 @@ enum AcoreStrings
LANG_DEBUG_AREATRIGGER_OFF = 1203, LANG_DEBUG_AREATRIGGER_OFF = 1203,
LANG_DEBUG_AREATRIGGER_REACHED = 1204, LANG_DEBUG_AREATRIGGER_REACHED = 1204,
// Isle of Conquest // 1205-1299 - free
LANG_BG_IC_START_TWO_MINUTES = 1205,
LANG_BG_IC_START_ONE_MINUTE = 1206,
LANG_BG_IC_START_HALF_MINUTE = 1207,
LANG_BG_IC_HAS_BEGUN = 1208,
LANG_BG_IC_ALLIANCE_KEEP = 1209,
LANG_BG_IC_HORDE_KEEP = 1210,
LANG_BG_IC_TEAM_WINS = 1211,
LANG_BG_IC_WEST_GATE_DESTROYED = 1212,
LANG_BG_IC_EAST_GATE_DESTROYED = 1213,
LANG_BG_IC_SOUTH_GATE_DESTROYED = 1214,
LANG_BG_IC_NORTH_GATE_DESTROYED = 1215,
LANG_BG_IC_TEAM_ASSAULTED_NODE_1 = 1216,
LANG_BG_IC_TEAM_DEFENDED_NODE = 1217,
LANG_BG_IC_TEAM_ASSAULTED_NODE_2 = 1218,
LANG_BG_IC_TEAM_HAS_TAKEN_NODE = 1219,
LANG_BG_IC_WORKSHOP = 1220,
LANG_BG_IC_DOCKS = 1221,
LANG_BG_IC_REFINERY = 1222,
LANG_BG_IC_QUARRY = 1223,
LANG_BG_IC_HANGAR = 1224,
// 1225-1299
LANG_BG_IC_ALLIANCE = 1300,
LANG_BG_IC_HORDE = 1301,
// 1302-1325 // 1300-1333
// AV // AV
LANG_BG_AV_ALLY = 1300, LANG_BG_AV_ALLY = 1300,
LANG_BG_AV_HORDE = 1301, LANG_BG_AV_HORDE = 1301,
@@ -1086,14 +986,10 @@ enum AcoreStrings
LANG_BG_AV_NODE_TOWER_FROST_W = 1324, LANG_BG_AV_NODE_TOWER_FROST_W = 1324,
LANG_BG_AV_NODE_GRAVE_FROST_HUT = 1325, LANG_BG_AV_NODE_GRAVE_FROST_HUT = 1325,
LANG_BG_AV_START_ONE_MINUTE = 1326, // 1326-1330 - free
LANG_BG_AV_START_HALF_MINUTE = 1327,
LANG_BG_AV_HAS_BEGUN = 1328,
LANG_BG_AV_A_NEAR_LOSE = 1329,
LANG_BG_AV_H_NEAR_LOSE = 1330,
LANG_BG_AV_H_CAPTAIN_DEAD = 1331, LANG_BG_AV_H_CAPTAIN_DEAD = 1331,
LANG_BG_AV_A_CAPTAIN_DEAD = 1332, LANG_BG_AV_A_CAPTAIN_DEAD = 1332,
LANG_BG_AV_START_TWO_MINUTES = 1333,
//Player Ticket Strings //Player Ticket Strings
LANG_TICKET_CLOSED = 1334, LANG_TICKET_CLOSED = 1334,
+9 -2
View File
@@ -3407,13 +3407,20 @@ enum PvPTeamId
PVP_TEAM_NEUTRAL = 2 // Battleground: Neutral, Arena: None PVP_TEAM_NEUTRAL = 2 // Battleground: Neutral, Arena: None
}; };
uint8 constexpr PVP_TEAMS_COUNT = 2;
inline PvPTeamId GetPvPTeamId(TeamId teamId) inline PvPTeamId GetPvPTeamId(TeamId teamId)
{ {
return teamId == TEAM_ALLIANCE ? PVP_TEAM_ALLIANCE : PVP_TEAM_HORDE; return teamId == TEAM_ALLIANCE ? PVP_TEAM_ALLIANCE : PVP_TEAM_HORDE;
} }
inline TeamId GetTeamId(PvPTeamId teamId)
{
return teamId == PVP_TEAM_ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE;
}
// indexes of BattlemasterList.dbc // indexes of BattlemasterList.dbc
enum BattlegroundTypeId enum BattlegroundTypeId : uint8
{ {
BATTLEGROUND_TYPE_NONE = 0, // None BATTLEGROUND_TYPE_NONE = 0, // None
BATTLEGROUND_AV = 1, // Alterac Valley BATTLEGROUND_AV = 1, // Alterac Valley
@@ -3553,7 +3560,7 @@ enum DuelCompleteType
}; };
// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time // handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time
enum BattlegroundQueueTypeId enum BattlegroundQueueTypeId : uint8
{ {
BATTLEGROUND_QUEUE_NONE = 0, BATTLEGROUND_QUEUE_NONE = 0,
BATTLEGROUND_QUEUE_AV = 1, BATTLEGROUND_QUEUE_AV = 1,