diff --git a/data/sql/updates/pending_db_world/rev_1645123941917942700.sql b/data/sql/updates/pending_db_world/rev_1645123941917942700.sql new file mode 100644 index 000000000..3fdaaf52d --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1645123941917942700.sql @@ -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; diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 35c719643..cf937c257 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -442,7 +442,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un return false; } - TeamId winnerTeam = bg->GetWinner(); + TeamId winnerTeam = GetTeamId(bg->GetWinner()); if (winnerTeam == TEAM_NEUTRAL) { return false; diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index c16545cfa..bc2511cdc 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -231,7 +231,7 @@ void Battlefield::InvitePlayerToQueue(Player* player) 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]); for (GuidUnorderedSet::const_iterator itr = copy.begin(); itr != copy.end(); ++itr) @@ -252,7 +252,7 @@ void Battlefield::InvitePlayersInQueueToWar() 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) { 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() { // 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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (player->isAFK() && player->GetZoneId() == GetZoneId() && !player->IsGameMaster()) @@ -331,7 +331,7 @@ void Battlefield::StartBattle() if (m_isActive) return; - for (int team = 0; team < BG_TEAMS_COUNT; team++) + for (int team = 0; team < PVP_TEAMS_COUNT; team++) { m_PlayersInWar[team].clear(); m_Groups[team].clear(); @@ -378,7 +378,7 @@ void Battlefield::DoPlaySoundToAll(uint32 SoundID) data.Initialize(SMSG_PLAY_SOUND, 4); 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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->GetSession()->SendPacket(&data); @@ -449,7 +449,7 @@ void Battlefield::TeamCastSpell(TeamId team, int32 spellId) 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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->GetSession()->SendPacket(&data); @@ -457,7 +457,7 @@ void Battlefield::BroadcastPacketToZone(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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->GetSession()->SendPacket(&data); @@ -465,7 +465,7 @@ void Battlefield::BroadcastPacketToQueue(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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->GetSession()->SendPacket(&data); @@ -487,7 +487,7 @@ void Battlefield::SendWarningToPlayer(Player* player, uint32 entry) 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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) player->SendUpdateWorldState(field, value); diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index 9b5844e8c..f7846c745 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -57,7 +57,7 @@ enum BattlefieldSounds constexpr auto BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL = 1000; -const uint32 BattlefieldFactions[BG_TEAMS_COUNT] = +const uint32 BattlefieldFactions[PVP_TEAMS_COUNT] = { 1732, // Alliance 1735 // Horde @@ -372,11 +372,11 @@ protected: BfCapturePointVector m_capturePoints; // Players info maps - GuidUnorderedSet m_players[BG_TEAMS_COUNT]; // Players in zone - GuidUnorderedSet m_PlayersInQueue[BG_TEAMS_COUNT]; // Players in the queue - GuidUnorderedSet m_PlayersInWar[BG_TEAMS_COUNT]; // Players in WG combat - PlayerTimerMap m_InvitedPlayers[BG_TEAMS_COUNT]; - PlayerTimerMap m_PlayersWillBeKick[BG_TEAMS_COUNT]; + GuidUnorderedSet m_players[PVP_TEAMS_COUNT]; // Players in zone + GuidUnorderedSet m_PlayersInQueue[PVP_TEAMS_COUNT]; // Players in the queue + GuidUnorderedSet m_PlayersInWar[PVP_TEAMS_COUNT]; // Players in WG combat + PlayerTimerMap m_InvitedPlayers[PVP_TEAMS_COUNT]; + PlayerTimerMap m_PlayersWillBeKick[PVP_TEAMS_COUNT]; // Variables that must exist for each battlefield 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 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 m_Data64; std::vector m_Data32; diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 31462c286..bd7cee0db 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -315,7 +315,7 @@ void BattlefieldWG::UpdateCounterVehicle(bool init) // Update vehicle count WorldState to player 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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) { @@ -328,7 +328,7 @@ void BattlefieldWG::UpdateVehicleCountWG() 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) if (Player* player = ObjectAccessor::FindPlayer(*itr)) if (player->GetAreaId() == areaId) diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp new file mode 100644 index 000000000..fe6e7a439 --- /dev/null +++ b/src/server/game/Battlegrounds/Arena.cpp @@ -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 . + */ + +#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); +} diff --git a/src/server/game/Battlegrounds/Arena.h b/src/server/game/Battlegrounds/Arena.h new file mode 100644 index 000000000..0be78b705 --- /dev/null +++ b/src/server/game/Battlegrounds/Arena.h @@ -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 . + */ + +#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 diff --git a/src/server/game/Battlegrounds/ArenaScore.h b/src/server/game/Battlegrounds/ArenaScore.h new file mode 100644 index 000000000..3bb8b113a --- /dev/null +++ b/src/server/game/Battlegrounds/ArenaScore.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 . + */ + +#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 diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index ff086a276..42aa19629 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -26,7 +26,9 @@ #include "BattlegroundRL.h" #include "BattlegroundRV.h" #include "Chat.h" +#include "ChatTextBuilder.h" #include "Creature.h" +#include "CreatureTextMgr.h" #include "Formulas.h" #include "GameGraveyard.h" #include "GridNotifiersImpl.h" @@ -118,6 +120,20 @@ void Battleground::BroadcastWorker(Do& _do) _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() { m_RealTypeID = BATTLEGROUND_TYPE_NONE; @@ -129,7 +145,7 @@ Battleground::Battleground() m_LastResurrectTime = 0; m_ArenaType = 0; m_IsArena = false; - m_WinnerId = TEAM_NEUTRAL; + m_WinnerId = PVP_TEAM_NEUTRAL; m_StartTime = 0; m_ResetStatTimer = 0; m_ValidStartPositionTimer = 0; @@ -138,7 +154,6 @@ Battleground::Battleground() m_IsRated = false; m_BuffChange = false; m_IsRandom = false; - m_Name = ""; m_LevelMin = 0; m_LevelMax = 0; m_SetDeleteThis = false; @@ -151,24 +166,9 @@ Battleground::Battleground() m_StartMaxDist = 0.0f; 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_HORDE] = 0; - m_ArenaTeamRatingChanges[TEAM_ALLIANCE] = 0; - m_ArenaTeamRatingChanges[TEAM_HORDE] = 0; - m_ArenaTeamMMR[TEAM_ALLIANCE] = 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_THIRD] = BG_START_DELAY_30S; 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_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; + + StartMessageIds[BG_STARTING_EVENT_FIRST] = BG_TEXT_START_TWO_MINUTES; + StartMessageIds[BG_STARTING_EVENT_SECOND] = BG_TEXT_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = BG_TEXT_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = BG_TEXT_BATTLE_HAS_BEGUN; // pussywizard: m_UpdateTimer = 0; @@ -205,6 +205,8 @@ Battleground::Battleground() Battleground::~Battleground() { + LOG_DEBUG("bg.battleground", "> Remove Battleground {} {} {}", GetName(), GetBgTypeID(), GetInstanceID()); + _reviveEvents.KillAllEvents(false); // remove objects and creatures @@ -229,8 +231,8 @@ Battleground::~Battleground() m_Map = nullptr; } - for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr) - delete itr->second; + for (auto const& itr : PlayerScores) + delete itr.second; } 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 { - UpdateArenaWorldState(); - CheckArenaAfterTimerConditions(); + EndBattleground(PVP_TEAM_NEUTRAL); return; } } @@ -304,19 +305,20 @@ inline void Battleground::_CheckSafePositions(uint32 diff) return; m_ValidStartPositionTimer += diff; + if (m_ValidStartPositionTimer >= CHECK_PLAYER_POSITION_INVERVAL) { m_ValidStartPositionTimer = 0; - float x, y, z, o; - for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + for (auto const& [playerGuid, player] : GetPlayers()) { - Position pos = itr->second->GetPosition(); - GetTeamStartLoc(itr->second->GetBgTeamId(), x, y, z, o); - if (pos.GetExactDistSq(x, y, z) > maxDist) + Position pos = player->GetPosition(); + Position const* startPos = GetTeamStartPosition(player->GetBgTeamId()); + + if (pos.GetExactDistSq(startPos) > maxDist) { - LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending {} back to start location (map: {}) (possible exploit)", itr->second->GetName(), GetMapId()); - itr->second->TeleportTo(GetMapId(), x, y, z, o); + LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending {} back to start location (map: {}) (possible exploit)", player->GetName(), GetMapId()); + player->TeleportTo(GetMapId(), startPos->GetPositionX(), startPos->GetPositionY(), startPos->GetPositionZ(), startPos->GetOrientation()); } } } @@ -465,20 +467,26 @@ inline void Battleground::_ProcessJoin(uint32 diff) StartingEventCloseDoors(); SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FIRST]); + // 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 else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(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 else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(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()) switch (GetBgTypeID()) @@ -514,7 +522,9 @@ inline void Battleground::_ProcessJoin(uint32 diff) 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); 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) ArenaSpectator::HandleResetCommand(*itr); - CheckArenaWinConditions(); + CheckWinConditions(); // pussywizard: arena spectator stuff if (GetStatus() == STATUS_IN_PROGRESS) @@ -591,7 +601,7 @@ inline void Battleground::_ProcessJoin(uint32 diff) // Announce BG starting 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); } @@ -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; - m_TeamStartLocY[teamId] = Y; - m_TeamStartLocZ[teamId] = Z; - m_TeamStartLocO[teamId] = O; + ASSERT(teamId < TEAM_NEUTRAL); + _startPosition[teamId] = pos; +} + +Position const* Battleground::GetTeamStartPosition(TeamId teamId) const +{ + ASSERT(teamId < TEAM_NEUTRAL); + return &_startPosition[teamId]; } void Battleground::SendPacketToAll(WorldPacket const* packet) @@ -639,6 +653,24 @@ void Battleground::SendPacketToTeam(TeamId teamId, WorldPacket const* packet, Pl 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 localizer(builder); + BroadcastWorker(localizer); +} + void Battleground::PlaySoundToAll(uint32 soundID) { WorldPacket data; @@ -728,7 +760,7 @@ void Battleground::UpdateWorldState(uint32 variable, uint32 value) 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 // skip to avoid double rating reduce / add @@ -736,35 +768,23 @@ void Battleground::EndBattleground(TeamId winnerTeamId) // set as fast as possible if (GetStatus() == STATUS_WAIT_LEAVE) 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); - - 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); - if (winnerTeamId == TEAM_ALLIANCE) + if (winnerTeamId == PVP_TEAM_ALLIANCE) { - winmsg_id = isBattleground() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS; - PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound + if (isBattleground()) + SendBroadcastText(BG_TEXT_ALLIANCE_WINS, CHAT_MSG_BG_SYSTEM_NEUTRAL); + + 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; - PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound + if (isBattleground()) + SendBroadcastText(BG_TEXT_HORDE_WINS, CHAT_MSG_BG_SYSTEM_NEUTRAL); + + PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound } CharacterDatabasePreparedStatement* stmt = nullptr; @@ -782,7 +802,7 @@ void Battleground::EndBattleground(TeamId winnerTeamId) stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_BATTLEGROUND); stmt->SetData(0, battlegroundId); - stmt->SetData(1, GetPvPTeamId(GetWinner())); + stmt->SetData(1, GetWinner()); stmt->SetData(2, GetUniqueBracketId()); stmt->SetData(3, GetBgTypeID(true)); 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! 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; - sBattlegroundMgr->BuildPvpLogDataPacket(&pvpLogData, this); + BuildPvPLogDataPacket(pvpLogData); - uint8 aliveWinners = GetAlivePlayersCountByTeam(winnerTeamId); - for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for (auto const& [playerGuid, player] : m_Players) { - Player* player = itr->second; TeamId bgTeamId = player->GetBgTeamId(); + // should remove spirit of redemption if (player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) 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()) { player->ResurrectPlayer(1.0f); @@ -948,38 +834,12 @@ void Battleground::EndBattleground(TeamId winnerTeamId) 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 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); // Reward winner team - if (bgTeamId == winnerTeamId) + if (bgTeamId == GetTeamId(winnerTeamId)) { if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetBgTypeID(true))) { @@ -1001,7 +861,7 @@ void Battleground::EndBattleground(TeamId winnerTeamId) UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(loser_kills)); } - sScriptMgr->OnBattlegroundEndReward(this, player, winnerTeamId); + sScriptMgr->OnBattlegroundEndReward(this, player, GetTeamId(winnerTeamId)); player->ResetAllPowers(); player->CombatStopWithPets(true); @@ -1013,11 +873,11 @@ void Battleground::EndBattleground(TeamId winnerTeamId) if (isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE)) { 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(1, player->GetGUID().GetCounter()); - stmt->SetData(2, bgTeamId == winnerTeamId); + stmt->SetData(2, bgTeamId == GetTeamId(winnerTeamId)); stmt->SetData(3, score->second->GetKillingBlows()); stmt->SetData(4, score->second->GetDeaths()); stmt->SetData(5, score->second->GetHonorableKills()); @@ -1040,21 +900,7 @@ void Battleground::EndBattleground(TeamId winnerTeamId) player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, player->GetMapId()); } - if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam) - { - // 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); + sScriptMgr->OnBattlegroundEnd(this, GetTeamId(winnerTeamId)); } uint32 Battleground::GetBonusHonorFromKill(uint32 kills) const @@ -1084,7 +930,7 @@ void Battleground::RemovePlayerAtLeave(Player* player) } // delete player score if exists - BattlegroundScoreMap::iterator itr2 = PlayerScores.find(player->GetGUID()); + auto const& itr2 = PlayerScores.find(player->GetGUID().GetCounter()); if (itr2 != PlayerScores.end()) { delete itr2->second; @@ -1115,15 +961,6 @@ void Battleground::RemovePlayerAtLeave(Player* player) 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); player->GetSession()->SendPacket(&data); @@ -1157,7 +994,7 @@ void Battleground::RemovePlayerAtLeave(Player* player) // this method is called when creating bg void Battleground::Init() { - SetWinner(TEAM_NEUTRAL); + SetWinner(PVP_TEAM_NEUTRAL); SetStatus(STATUS_WAIT_QUEUE); SetStartTime(0); SetEndTime(0); @@ -1176,10 +1013,14 @@ void Battleground::Init() m_Players.clear(); - for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr) - delete itr->second; + for (auto const& itr : PlayerScores) + delete itr.second; + PlayerScores.clear(); + for (auto& itr : _arenaTeamScores) + itr.Reset(); + ResetBGSubclass(); } @@ -1220,27 +1061,12 @@ void Battleground::AddPlayer(Player* player) // add arena specific auras 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 if (Pet* pet = player->GetPet()) if (pet->IsAlive()) pet->SetHealth(pet->GetMaxHealth()); + player->RemoveArenaEnchantments(TEMP_ENCHANTMENT_SLOT); player->DestroyConjuredItems(true); player->UnsummonPetTemporaryIfAny(); @@ -1360,7 +1186,7 @@ bool Battleground::HasFreeSlots() const { if (GetStatus() != STATUS_WAIT_JOIN && GetStatus() != STATUS_IN_PROGRESS) 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) return true; 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 - BattlegroundScoreMap::const_iterator itr = PlayerScores.find(player->GetGUID()); - if (itr == PlayerScores.end()) // player not found... - return; + uint8 type = (isArena() ? 1 : 0); - 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 - itr->second->KillingBlows += value; - if (isArena() && isRated()) - { - ArenaLogEntryDataMap::iterator itr2 = ArenaLogEntries.find(player->GetGUID()); - if (itr2 != ArenaLogEntries.end()) - itr2->second.KillingBlows += value; - } - break; - case SCORE_DEATHS: // Deaths - 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 - if (doAddHonor) - player->RewardHonor(nullptr, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false - else - itr->second->BonusHonor += value; - } - break; - // 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; + for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i) + _arenaTeamScores[i].BuildRatingInfoBlock(data); + + for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i) + _arenaTeamScores[i].BuildTeamInfoBlock(data); } + + if (GetStatus() == STATUS_WAIT_LEAVE) + { + data << uint8(1); // bg ended + 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 + else + itr->second->UpdateScore(type, value); + + return true; } void Battleground::AddPlayerToResurrectQueue(ObjectGuid npc_guid, ObjectGuid player_guid) @@ -1678,7 +1487,7 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y, if (creature->IsVehicle()) creature->SetPvP(true); - return creature; + return creature; } bool Battleground::DelCreature(uint32 type) @@ -1920,7 +1729,7 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player) WorldPacket data; BlockMovement(player); - sBattlegroundMgr->BuildPvpLogDataPacket(&data, this); + BuildPvPLogDataPacket(data); player->GetSession()->SendPacket(&data); 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; } -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) { Group*& old_raid = m_BgRaids[teamId]; diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 4e5a65c1b..438c4e26e 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -18,6 +18,7 @@ #ifndef __BATTLEGROUND_H #define __BATTLEGROUND_H +#include "ArenaScore.h" #include "Common.h" #include "DBCEnums.h" #include "GameObject.h" @@ -53,6 +54,17 @@ enum BattlegroundDesertionType 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 { SOUND_HORDE_WINS = 8454, @@ -111,17 +123,12 @@ enum BattlegroundSpells SPELL_SPIRIT_HEAL = 22012, // Spirit Heal SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual 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_SPIRIT_HEAL_MANA = 44535, // Spirit Heal SPELL_RECENTLY_DROPPED_FLAG = 42792, // Recently Dropped Flag 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_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 + 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 }; enum BattlegroundReputations @@ -180,11 +187,6 @@ enum BattlegroundStatus STATUS_WAIT_LEAVE = 4 // means some faction has won BG and it is ending }; -enum BattlegroundTeams -{ - BG_TEAMS_COUNT = 2 -}; - struct BattlegroundObjectInfo { BattlegroundObjectInfo() = default; @@ -194,35 +196,7 @@ struct BattlegroundObjectInfo uint32 spellid{0}; }; -enum ScoreType -{ - 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 +enum ArenaType : uint8 { ARENA_TYPE_2v2 = 2, ARENA_TYPE_3v3 = 3, @@ -251,43 +225,15 @@ enum BattlegroundStartingEventsIds BG_STARTING_EVENT_THIRD = 2, BG_STARTING_EVENT_FOURTH = 3 }; -#define BG_STARTING_EVENT_COUNT 4 -struct BattlegroundScore -{ - 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; } -}; +constexpr auto BG_STARTING_EVENT_COUNT = 4; class ArenaLogEntryData { public: - ArenaLogEntryData() = default; - void Fill(const char* name, ObjectGuid::LowType guid, uint32 acc, uint32 arenaTeamId, std::string ip) + ArenaLogEntryData() = default; + + void Fill(std::string_view name, ObjectGuid::LowType guid, uint32 acc, uint32 arenaTeamId, std::string ip) { Name = std::string(name); Guid = guid; @@ -296,11 +242,11 @@ public: IP = ip; } - std::string Name; + std::string Name{}; ObjectGuid::LowType Guid{0}; - uint32 Acc; + uint32 Acc{0}; uint32 ArenaTeamId{0}; - std::string IP; + std::string IP{}; uint32 DamageDone{0}; uint32 HealingDone{0}; uint32 KillingBlows{0}; @@ -318,11 +264,11 @@ enum BGHonorMode #define ARENA_READY_MARKER_ENTRY 301337 /* -This class is used to: -1. Add player to battleground -2. Remove player from battleground -3. some certain cases, same for all battlegrounds -4. It has properties same for all battlegrounds + This class is used to: + 1. Add player to battleground + 2. Remove player from battleground + 3. some certain cases, same for all battlegrounds + 4. It has properties same for all battlegrounds */ enum BattlegroundQueueInvitationType @@ -344,6 +290,7 @@ public: { return true; } + virtual void Init(); virtual void StartingEventCloseDoors() { } virtual void StartingEventOpenDoors() { } @@ -357,7 +304,7 @@ public: /* Battleground */ // 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]] uint32 GetInstanceID() const { return m_InstanceID; } [[nodiscard]] BattlegroundStatus GetStatus() const { return m_Status; } @@ -374,29 +321,29 @@ public: [[nodiscard]] int32 GetStartDelayTime() const { return m_StartDelayTime; } [[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 GetBonusHonorFromKill(uint32 kills) const; - bool IsRandom() { return m_IsRandom; } + bool IsRandom() { return m_IsRandom; } // 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 SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; } void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } void SetStatus(BattlegroundStatus Status) { m_Status = Status; } void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; } - void SetStartTime(uint32 Time) { m_StartTime = Time; } - void SetEndTime(uint32 Time) { m_EndTime = Time; } + void SetStartTime(uint32 Time) { m_StartTime = Time; } + void SetEndTime(uint32 Time) { m_EndTime = Time; } void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; } void SetLevelRange(uint32 min, uint32 max) { m_LevelMin = min; m_LevelMax = max; } - void SetRated(bool state) { m_IsRated = state; } - void SetArenaType(uint8 type) { m_ArenaType = type; } + void SetRated(bool state) { m_IsRated = state; } + void SetArenaType(uint8 type) { m_ArenaType = type; } void SetArenaorBGType(bool _isArena) { m_IsArena = _isArena; } - void SetWinner(TeamId winner) { m_WinnerId = winner; } - void SetScriptId(uint32 scriptId) { ScriptId = scriptId; } - void SetRandom(bool isRandom) { m_IsRandom = isRandom; } + void SetWinner(PvPTeamId winner) { m_WinnerId = winner; } + void SetScriptId(uint32 scriptId) { ScriptId = scriptId; } + void SetRandom(bool isRandom) { m_IsRandom = isRandom; } void ModifyStartDelayTime(int32 diff) { m_StartDelayTime -= diff; } void SetStartDelayTime(int32 Time) { m_StartDelayTime = Time; } @@ -433,12 +380,11 @@ public: void ReadyMarkerClicked(Player* p); // pussywizard GuidSet readyMarkerClickedSet; // pussywizard - typedef std::map BattlegroundScoreMap; - typedef std::map ArenaLogEntryDataMap;// pussywizard + typedef std::unordered_map BattlegroundScoreMap; + typedef std::unordered_map ArenaLogEntryDataMap; // pussywizard ArenaLogEntryDataMap ArenaLogEntries; // pussywizard - [[nodiscard]] BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const { return PlayerScores.begin(); } - [[nodiscard]] BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const { return PlayerScores.end(); } - [[nodiscard]] uint32 GetPlayerScoresSize() const { return PlayerScores.size(); } + [[nodiscard]] BattlegroundScoreMap const* GetPlayerScores() const { return &PlayerScores; } + [[nodiscard]] std::size_t GetPlayerScoresSize() const { return PlayerScores.size(); } [[nodiscard]] uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); } @@ -462,25 +408,22 @@ public: [[nodiscard]] BattlegroundMap* GetBgMap() const { ASSERT(m_Map); return m_Map; } [[nodiscard]] BattlegroundMap* FindBgMap() const { return m_Map; } - void SetTeamStartLoc(TeamId teamId, float X, float Y, float Z, float O); - void GetTeamStartLoc(TeamId teamId, float& X, float& Y, float& Z, float& O) const - { - X = m_TeamStartLocX[teamId]; - Y = m_TeamStartLocY[teamId]; - Z = m_TeamStartLocZ[teamId]; - O = m_TeamStartLocO[teamId]; - } + void SetTeamStartPosition(TeamId teamId, Position const& pos); + Position const* GetTeamStartPosition(TeamId teamId) const; void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; } [[nodiscard]] float GetStartMaxDist() const { return m_StartMaxDist; } // Packet Transfer // method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!) - virtual void FillInitialWorldStates(WorldPacket& /*data*/) {} + virtual void FillInitialWorldStates(WorldPacket& /*data*/) { } void SendPacketToTeam(TeamId teamId, WorldPacket const* packet, Player* sender = nullptr, bool self = true); void SendPacketToAll(WorldPacket const* packet); 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 void BroadcastWorker(Do& _do); @@ -493,7 +436,14 @@ public: 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 SendWarningToAll(uint32 entry, ...); @@ -507,7 +457,8 @@ public: [[nodiscard]] Group* GetBgRaid(TeamId teamId) const { return m_BgRaids[teamId]; } 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 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]; } + virtual void CheckWinConditions() { } + // used for rated arena battles void SetArenaTeamIdForTeam(TeamId teamId, uint32 ArenaTeamId) { m_ArenaTeamIds[teamId] = ArenaTeamId; } - [[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; } - [[nodiscard]] uint32 GetArenaMatchmakerRating(TeamId teamId) const { return m_ArenaTeamMMR[teamId]; } - void CheckArenaAfterTimerConditions(); - void CheckArenaWinConditions(); - virtual void UpdateArenaWorldState(); + [[nodiscard]] uint32 GetArenaTeamIdForTeam(TeamId teamId) const { return m_ArenaTeamIds[teamId]; } + void SetArenaMatchmakerRating(TeamId teamId, uint32 MMR) { m_ArenaTeamMMR[teamId] = MMR; } + [[nodiscard]] uint32 GetArenaMatchmakerRating(TeamId teamId) const { return m_ArenaTeamMMR[teamId]; } // Triggers handle // must be implemented in BG subclass virtual void HandleAreaTrigger(Player* /*player*/, uint32 /*trigger*/) {} // must be implemented in BG subclass if need AND call base class generic code virtual void HandleKillPlayer(Player* player, Player* killer); - virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/); + virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/) { } // Battleground events virtual void EventPlayerDroppedFlag(Player* /*player*/) {} @@ -555,7 +503,7 @@ public: void AddOrSetPlayerToCorrectBgGroup(Player* player, TeamId teamId); - void RemovePlayerAtLeave(Player* player); + virtual void RemovePlayerAtLeave(Player* player); // can be extended in in BG subclass void HandleTriggerBuff(GameObject* gameObject); @@ -659,11 +607,13 @@ protected: // this must be filled in constructors! uint32 StartMessageIds[BG_STARTING_EVENT_COUNT]; - bool m_BuffChange; - bool m_IsRandom; + bool m_BuffChange; + bool m_IsRandom; BGHonorMode m_HonorMode; - int32 m_TeamScores[BG_TEAMS_COUNT]; + int32 m_TeamScores[PVP_TEAMS_COUNT]; + + ArenaTeamScore _arenaTeamScores[PVP_TEAMS_COUNT]; // pussywizard: uint32 m_UpdateTimer; @@ -685,12 +635,12 @@ private: 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_IsArena; - TeamId m_WinnerId; + PvPTeamId m_WinnerId; int32 m_StartDelayTime; bool m_IsRated; // is this battle rated? bool m_PrematureCountDown; uint32 m_PrematureCountDownTimer; - char const* m_Name; + std::string m_Name{}; /* 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 will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG // Invited players counters - uint32 m_BgInvitedPlayers[BG_TEAMS_COUNT]; + uint32 m_BgInvitedPlayers[PVP_TEAMS_COUNT]; // 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; ToBeTeleportedMap m_ToBeTeleported; // Players count by team - uint32 m_PlayersCount[BG_TEAMS_COUNT]; + uint32 m_PlayersCount[PVP_TEAMS_COUNT]; // Arena team ids by team - uint32 m_ArenaTeamIds[BG_TEAMS_COUNT]; - - int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT]; - uint32 m_ArenaTeamMMR[BG_TEAMS_COUNT]; + uint32 m_ArenaTeamIds[PVP_TEAMS_COUNT]; + uint32 m_ArenaTeamMMR[PVP_TEAMS_COUNT]; // Limits uint32 m_LevelMin; @@ -755,11 +703,8 @@ private: // Start location uint32 m_MapId; 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; + std::array _startPosition; uint32 ScriptId; }; #endif diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 72b3ab612..422e9b3b9 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -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) { data->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); @@ -495,8 +322,8 @@ bool BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data) bg->SetMinPlayersPerTeam(data.MinPlayersPerTeam); bg->SetMaxPlayersPerTeam(data.MaxPlayersPerTeam); bg->SetName(data.BattlegroundName); - bg->SetTeamStartLoc(TEAM_ALLIANCE, data.Team1StartLocX, data.Team1StartLocY, data.Team1StartLocZ, data.Team1StartLocO); - bg->SetTeamStartLoc(TEAM_HORDE, data.Team2StartLocX, data.Team2StartLocY, data.Team2StartLocZ, data.Team2StartLocO); + bg->SetTeamStartPosition(TEAM_ALLIANCE, data.StartLocation[TEAM_ALLIANCE]); + bg->SetTeamStartPosition(TEAM_HORDE, data.StartLocation[TEAM_HORDE]); bg->SetStartMaxDist(data.StartMaxDist); bg->SetLevelRange(data.LevelMin, data.LevelMax); bg->SetScriptId(data.scriptId); @@ -559,55 +386,38 @@ void BattlegroundMgr::CreateInitialBattlegrounds() if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam) { LOG_ERROR("bg.battleground", "Table `battleground_template` for id {} has bad values for MinPlayersPerTeam ({}) and MaxPlayersPerTeam({})", - data.bgTypeId, data.MinPlayersPerTeam, data.MaxPlayersPerTeam); + data.bgTypeId, data.MinPlayersPerTeam, data.MaxPlayersPerTeam); continue; } if (data.LevelMin == 0 || data.LevelMax == 0 || data.LevelMin > data.LevelMax) { LOG_ERROR("bg.battleground", "Table `battleground_template` for id {} has bad values for LevelMin ({}) and LevelMax({})", - data.bgTypeId, data.LevelMin, data.LevelMax); + data.bgTypeId, data.LevelMin, data.LevelMax); continue; } - if (data.bgTypeId == BATTLEGROUND_AA || data.bgTypeId == BATTLEGROUND_RB) - { - data.Team1StartLocX = 0; - data.Team1StartLocY = 0; - data.Team1StartLocZ = 0; - data.Team1StartLocO = fields[6].Get(); - data.Team2StartLocX = 0; - data.Team2StartLocY = 0; - data.Team2StartLocZ = 0; - data.Team2StartLocO = fields[8].Get(); - } - else + if (data.bgTypeId != BATTLEGROUND_AA && data.bgTypeId != BATTLEGROUND_RB) { uint32 startId = fields[5].Get(); if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId)) { - data.Team1StartLocX = start->x; - data.Team1StartLocY = start->y; - data.Team1StartLocZ = start->z; - data.Team1StartLocO = fields[6].Get(); + data.StartLocation[TEAM_ALLIANCE].Relocate(start->x, start->y, start->z, fields[6].Get()); } 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; } startId = fields[7].Get(); if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId)) { - data.Team2StartLocX = start->x; - data.Team2StartLocY = start->y; - data.Team2StartLocZ = start->z; - data.Team2StartLocO = fields[8].Get(); + data.StartLocation[TEAM_HORDE].Relocate(start->x, start->y, start->z, fields[8].Get()); } 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; } } @@ -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)) { - float x, y, z, o; - bg->GetTeamStartLoc(player->GetBgTeamId(), x, y, z, o); - player->TeleportTo(bg->GetMapId(), x, y, z, o); + uint32 mapid = bg->GetMapId(); + Position const* pos = bg->GetTeamStartPosition(player->GetBgTeamId()); + + 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); } -void BattlegroundMgr::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId) +void BattlegroundMgr::DoForAllBattlegrounds(std::function const& worker) { - 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& itr : ginfo->Players) + for (auto const& [_, bg] : m_Battlegrounds) { - // 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()); + worker(bg); } } diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index d650af31c..f4a19e5f8 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -24,6 +24,7 @@ #include "CreatureAIImpl.h" #include "DBCEnums.h" #include +#include typedef std::map BattlegroundContainer; typedef std::unordered_map BattleMastersMap; @@ -42,15 +43,8 @@ struct CreateBattlegroundData uint32 LevelMax; char const* BattlegroundName; uint32 MapID; - float Team1StartLocX; - float Team1StartLocY; - float Team1StartLocZ; - float Team1StartLocO; - float Team2StartLocX; - float Team2StartLocY; - float Team2StartLocZ; - float Team2StartLocO; float StartMaxDist; + std::array StartLocation; uint32 scriptId; uint8 Weight; }; @@ -73,7 +67,6 @@ public: void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, ObjectGuid guid); void BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere); 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 BuildPlaySoundPacket(WorldPacket* data, uint32 soundid); void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid); @@ -96,8 +89,6 @@ public: void ScheduleArenaQueueUpdate(uint32 arenaRatedTeamId, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id); uint32 GetPrematureFinishTime() const; - static void InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId); - void ToggleArenaTesting(); void ToggleTesting(); @@ -138,6 +129,8 @@ public: static std::unordered_map ArenaTypeToQueue; // ArenaType -> BattlegroundQueueTypeId static std::unordered_map QueueToArenaType; // BattlegroundQueueTypeId -> ArenaType + void DoForAllBattlegrounds(std::function const& worker); + private: bool CreateBattleground(CreateBattlegroundData& data); uint32 GetNextClientVisibleInstanceId(); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index 7449f0658..d8bab21c6 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -37,7 +37,7 @@ 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) { @@ -87,7 +87,7 @@ bool BattlegroundQueue::SelectionPool::KickGroup(const uint32 size) // find last group with proper size or largest bool foundProper = false; 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 (std::abs(int32((*itr)->Players.size()) - (int32)size) <= 1) @@ -154,7 +154,7 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, PvPDiffi uint32 index = 0; if (!isRated && !isPremade) - index += BG_TEAMS_COUNT; + index += PVP_TEAMS_COUNT; if (ginfo->teamId == TEAM_HORDE) 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(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount()); - hordeDiff = hordeFree - static_cast(m_SelectionPools[TEAM_HORDE].GetPlayerCount()); - } -} - // this method checks if premade versus premade battleground is possible // then after 30 mins (default) in queue it moves premade group to normal queue 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 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()) 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 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()) { // clear selection pools @@ -633,7 +551,7 @@ bool BattlegroundQueue::CheckSkirmishForSameFaction(BattlegroundBracketId bracke // 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 (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].AddGroup((*itr), minPlayersPerTeam)) // successfully added { @@ -676,9 +594,6 @@ void BattlegroundQueue::UpdateEvents(uint32 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 BattlegroundNeedSet; - void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId) { // 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 if (!BattlegroundMgr::IsArenaType(m_bgTypeId)) { - const BattlegroundContainer& bgList = sBattlegroundMgr->GetBattlegroundList(); - BattlegroundNeedSet bgsToCheck; + std::vector bgsToCheck; // 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()) && (bg->GetBgTypeID(true) == m_bgTypeId || m_bgTypeId == BATTLEGROUND_RB) && - bg->HasFreeSlots() && bg->GetMinLevel() <= bracketEntry->minLevel && bg->GetMaxLevel() >= bracketEntry->maxLevel) - bgsToCheck.insert(bg); - } + if (!BattlegroundMgr::IsArenaType(bg->GetBgTypeID()) && + (bg->GetBgTypeID(true) == m_bgTypeId || m_bgTypeId == BATTLEGROUND_RB) && + bg->HasFreeSlots() && bg->GetMinLevel() <= bracketEntry->minLevel && + 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 - for (auto bg : bgsToCheck) + for (auto const& bg : bgsToCheck) { // call a function that fills whatever we can from normal queues FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id); // 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) - 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 @@ -751,9 +673,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket return; // 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) - BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); + InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); bg->StartBattleground(); @@ -764,9 +686,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id); // 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) - BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); + InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); } } @@ -786,9 +708,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket return; // 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) - BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); + InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId); bg->StartBattleground(); } @@ -804,7 +726,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket const uint32 maxCountedMMR = 2500; // 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 reverse1 = urand(0, 1) != 0; @@ -937,8 +859,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket arena->SetArenaMatchmakerRating(TEAM_ALLIANCE, aTeam->ArenaMatchmakerRating); arena->SetArenaMatchmakerRating(TEAM_HORDE, hTeam->ArenaMatchmakerRating); - BattlegroundMgr::InviteGroupToBG(aTeam, arena, TEAM_ALLIANCE); - BattlegroundMgr::InviteGroupToBG(hTeam, arena, TEAM_HORDE); + InviteGroupToBG(aTeam, arena, TEAM_ALLIANCE); + InviteGroupToBG(hTeam, arena, TEAM_HORDE); arena->StartBattleground(); } @@ -980,12 +902,12 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket { _queueAnnouncementTimer[bracket_id] = -1; - char const* bgName = bg_template->GetName(); + auto bgName = bg_template->GetName(); uint32 MaxPlayers = bg_template->GetMinPlayersPerTeam() * 2; uint32 q_min_level = std::min(bracketEntry->minLevel, (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 { @@ -1031,7 +953,7 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP } BattlegroundBracketId bracketId = bracketEntry->GetBracketId(); - char const* bgName = bg->GetName(); + auto bgName = bg->GetName(); uint32 MinPlayers = bg->GetMinPlayersPerTeam(); uint32 MaxPlayers = MinPlayers * 2; 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) if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) { - ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName, q_min_level, q_max_level, - qAlliance, - (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, - qHorde, - (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0 - ); + ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName.c_str(), q_min_level, q_max_level, + qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, + qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0); } else // Show queue status to server (when joining battleground queue) { @@ -1069,7 +988,7 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP 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; } - 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 @@ -1175,6 +1094,63 @@ int32 BattlegroundQueue::GetQueueAnnouncementTimer(uint32 bracketId) const 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 ***/ /*********************************************************/ diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h index bdc0f2a01..b2b10eb09 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.h +++ b/src/server/game/Battlegrounds/BattlegroundQueue.h @@ -72,7 +72,6 @@ public: void UpdateEvents(uint32 diff); 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 CheckNormalMatch(Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers); bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam); @@ -83,6 +82,7 @@ public: bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo* ginfo); void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo); uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo) const; + void InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId); [[nodiscard]] uint32 GetPlayersCountInGroupsQueue(BattlegroundBracketId bracketId, BattlegroundQueueGroupTypes bgqueue); [[nodiscard]] bool IsAllQueuesEmpty(BattlegroundBracketId bracket_id); void SendMessageBGQueue(Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry); @@ -125,7 +125,7 @@ public: }; //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; } BattlegroundTypeId GetBGTypeID() { return m_bgTypeId; } @@ -136,8 +136,8 @@ public: private: BattlegroundTypeId m_bgTypeId; ArenaType m_arenaType; - uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; - uint32 m_WaitTimeLastIndex[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]; + uint32 m_WaitTimes[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; + uint32 m_WaitTimeLastIndex[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]; // Event handler EventProcessor m_events; diff --git a/src/server/game/Battlegrounds/BattlegroundScore.h b/src/server/game/Battlegrounds/BattlegroundScore.h new file mode 100644 index 000000000..e07c41dd7 --- /dev/null +++ b/src/server/game/Battlegrounds/BattlegroundScore.h @@ -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 . + */ + +#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 diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index c38be999c..c50ab4617 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -25,6 +25,13 @@ #include "WorldPacket.h" #include "WorldSession.h" +void BattlegroundABScore::BuildObjectivesBlock(WorldPacket& data) +{ + data << uint32(2); + data << uint32(BasesAssaulted); + data << uint32(BasesDefended); +} + BattlegroundAB::BattlegroundAB() { m_BuffChange = true; @@ -37,11 +44,6 @@ BattlegroundAB::BattlegroundAB() _teamScores500Disadvantage[TEAM_HORDE] = false; _honorTics = 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; @@ -78,8 +80,17 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff) NodeOccupied(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); - PlaySoundToAll(teamId == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_CAPTURED_ALLIANCE : BG_AB_SOUND_NODE_CAPTURED_HORDE); + if (teamId == TEAM_ALLIANCE) + { + 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; } case BG_AB_EVENT_ALLIANCE_TICK: @@ -108,12 +119,12 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff) { 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); } 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); } } @@ -165,7 +176,7 @@ void BattlegroundAB::StartingEventOpenDoors() void BattlegroundAB::AddPlayer(Player* player) { Battleground::AddPlayer(player); - PlayerScores[player->GetGUID()] = new BattlegroundABScore(player); + PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundABScore(player->GetGUID())); } void BattlegroundAB::RemovePlayer(Player* player) @@ -309,8 +320,8 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); uint32 sound = 0; - uint32 message = 0; - uint32 message2 = 0; + TeamId teamid = player->GetTeamId(); + DeleteBanner(node); CreateBanner(node, true); @@ -322,8 +333,15 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb _capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL; _bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME); 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) { @@ -334,7 +352,15 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb _capturePointInfo[node]._state = static_cast(BG_AB_NODE_STATE_ALLY_CONTESTED) + player->GetTeamId(); _capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL; _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 { @@ -343,8 +369,17 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb _capturePointInfo[node]._ownerTeamId = player->GetTeamId(); _bgEvents.CancelEvent(BG_AB_EVENT_CAPTURE_STABLE + node); 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; } else @@ -357,13 +392,20 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb ApplyPhaseMask(); _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; + + 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); 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() @@ -473,26 +515,24 @@ GraveyardStruct const* BattlegroundAB::GetClosestGraveyard(Player* player) 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 (itr == PlayerScores.end()) - return; + if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor)) + return false; switch (type) { case SCORE_BASES_ASSAULTED: - ((BattlegroundABScore*)itr->second)->BasesAssaulted += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_ASSAULT_BASE); break; case SCORE_BASES_DEFENDED: - ((BattlegroundABScore*)itr->second)->BasesDefended += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_DEFEND_BASE); break; default: - Battleground::UpdatePlayerScore(player, type, value, doAddHonor); break; } + + return true; } bool BattlegroundAB::AllNodesConrolledByTeam(TeamId teamId) const @@ -508,7 +548,8 @@ void BattlegroundAB::ApplyPhaseMask() phaseMask |= 1 << (i * 2 + 1 + _capturePointInfo[i]._ownerTeamId); const BattlegroundPlayerMap& bgPlayerMap = GetPlayers(); - for (auto itr : bgPlayerMap) + + for (auto const& itr : bgPlayerMap) { itr.second->SetPhaseMask(phaseMask, false); itr.second->UpdateObjectVisibility(true, false); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h index f515f342b..d585a7591 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h @@ -19,6 +19,7 @@ #define __BATTLEGROUNDAB_H #include "Battleground.h" +#include "BattlegroundScore.h" #include "EventMap.h" enum BG_AB_Events @@ -147,6 +148,34 @@ enum BG_AB_BattlegroundNodes 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 { 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 }; -struct BattlegroundABScore : public BattlegroundScore +struct BattlegroundABScore final : public BattlegroundScore { - explicit BattlegroundABScore(Player* player) : BattlegroundScore(player), BasesAssaulted(0), BasesDefended(0) { } - ~BattlegroundABScore() override = default; - uint32 BasesAssaulted; - uint32 BasesDefended; + friend class BattlegroundAB; - uint32 GetAttr1() const final { return BasesAssaulted; } - uint32 GetAttr2() const final { return BasesDefended; } +protected: + + 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: BattlegroundAB(); @@ -252,7 +303,7 @@ public: void EndBattleground(TeamId winnerTeamId) 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 EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override; @@ -288,7 +339,7 @@ private: EventMap _bgEvents; uint32 _honorTics; uint32 _reputationTics; - uint8 _controlledPoints[BG_TEAMS_COUNT] {}; - bool _teamScores500Disadvantage[BG_TEAMS_COUNT] {}; + uint8 _controlledPoints[PVP_TEAMS_COUNT] {}; + bool _teamScores500Disadvantage[PVP_TEAMS_COUNT] {}; }; #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index 517caf0e6..55e92a552 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -27,6 +27,16 @@ #include "WorldPacket.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() { 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) InitNode(i, TEAM_NEUTRAL, false); - StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES; - StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE; - StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE; - StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN; -} - -BattlegroundAV::~BattlegroundAV() -{ + StartMessageIds[BG_STARTING_EVENT_SECOND] = BG_AV_TEXT_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = BG_AV_TEXT_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = BG_AV_TEXT_BATTLE_HAS_BEGUN; } 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) { - 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); m_IsInformedNearVictory[teamId] = true; } @@ -456,8 +469,7 @@ void BattlegroundAV::StartingEventOpenDoors() void BattlegroundAV::AddPlayer(Player* player) { Battleground::AddPlayer(player); - //create score and add it to map, default values are set in constructor - PlayerScores[player->GetGUID()] = new BattlegroundAVScore(player); + PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundAVScore(player->GetGUID())); } 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 (itr == PlayerScores.end()) - return; + if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor)) + return false; switch (type) { case SCORE_GRAVEYARDS_ASSAULTED: - ((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD); break; case SCORE_GRAVEYARDS_DEFENDED: - ((BattlegroundAVScore*)itr->second)->GraveyardsDefended += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD); break; case SCORE_TOWERS_ASSAULTED: - ((BattlegroundAVScore*)itr->second)->TowersAssaulted += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER); break; case SCORE_TOWERS_DEFENDED: - ((BattlegroundAVScore*)itr->second)->TowersDefended += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER); break; 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; default: Battleground::UpdatePlayerScore(player, type, value, doAddHonor); break; } + + return true; } void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h index dcde68101..cd738ae5d 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h @@ -19,6 +19,7 @@ #define __BATTLEGROUNDAV_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_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 +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 { //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_H_CAPTAIN = 22751 //the buff which the horde captain does }; + enum BG_AV_States { 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); } -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) { } - ~BattlegroundAVScore() override { } - uint32 GraveyardsAssaulted; - uint32 GraveyardsDefended; - uint32 TowersAssaulted; - uint32 TowersDefended; - uint32 MinesCaptured; - uint32 LeadersKilled; - uint32 SecondaryObjectives; + friend class BattlegroundAV; + +protected: + explicit BattlegroundAVScore(ObjectGuid playerGuid) : BattlegroundScore(playerGuid) { } + + void UpdateScore(uint32 type, uint32 value) override + { + switch (type) + { + 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 GetAttr2() const final { return GraveyardsDefended; } @@ -1570,11 +1612,11 @@ struct BattlegroundAVScore : public BattlegroundScore uint32 GetAttr5() const final { return MinesCaptured; } }; -class BattlegroundAV : public Battleground +class AC_GAME_API BattlegroundAV : public Battleground { public: BattlegroundAV(); - ~BattlegroundAV() override; + ~BattlegroundAV() override = default; /* inherited from BattlegroundClass */ void AddPlayer(Player* player) override; @@ -1588,7 +1630,7 @@ public: /*general stuff*/ 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 void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp index 900735fd7..87fba47aa 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp @@ -16,7 +16,6 @@ */ #include "BattlegroundBE.h" -#include "Language.h" #include "Log.h" #include "Player.h" #include "WorldPacket.h" @@ -24,20 +23,6 @@ BattlegroundBE::BattlegroundBE() { 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() @@ -58,39 +43,6 @@ void BattlegroundBE::StartingEventOpenDoors() 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) { player->NearTeleportTo(6238.930176f, 262.963470f, 0.889519f, player->GetOrientation()); @@ -137,14 +89,8 @@ void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger) void BattlegroundBE::FillInitialWorldStates(WorldPacket& data) { - data << uint32(0x9f3) << uint32(1); // 9 - Battleground::UpdateArenaWorldState(); -} - -void BattlegroundBE::Init() -{ - //call parent's class reset - Battleground::Init(); + data << uint32(0x9f3) << uint32(1); // 9 + Arena::FillInitialWorldStates(data); } bool BattlegroundBE::SetupBattleground() @@ -167,8 +113,3 @@ bool BattlegroundBE::SetupBattleground() return true; } - -void BattlegroundBE::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) -{ - Battleground::UpdatePlayerScore(player, type, value, doAddHonor); -} diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h index d8f7db155..9d7790d9b 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h @@ -18,7 +18,7 @@ #ifndef __BATTLEGROUNDBE_H #define __BATTLEGROUNDBE_H -#include "Battleground.h" +#include "Arena.h" enum BattlegroundBEObjectTypes { @@ -33,7 +33,7 @@ enum BattlegroundBEObjectTypes BG_BE_OBJECT_MAX = 8 }; -enum BattlegroundBEObjects +enum BattlegroundBEGameObjects { BG_BE_OBJECT_TYPE_DOOR_1 = 183971, BG_BE_OBJECT_TYPE_DOOR_2 = 183973, @@ -43,26 +43,19 @@ enum BattlegroundBEObjects BG_BE_OBJECT_TYPE_BUFF_2 = 184664 }; -class BattlegroundBE : public Battleground +class AC_GAME_API BattlegroundBE : public Arena { public: BattlegroundBE(); - ~BattlegroundBE() override; /* inherited from BattlegroundClass */ - void AddPlayer(Player* player) override; void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; - void RemovePlayer(Player* player) override; void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void Init() override; void FillInitialWorldStates(WorldPacket& d) override; - void HandleKillPlayer(Player* player, Player* killer) override; bool HandlePlayerUnderMap(Player* player) override; - - /* Scorekeeping */ - void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; }; + #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp index 38ebe13e2..bd84a831e 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp @@ -16,6 +16,7 @@ */ #include "BattlegroundDS.h" +#include "ArenaScore.h" #include "Creature.h" #include "GameObject.h" #include "Language.h" @@ -30,25 +31,8 @@ BattlegroundDS::BattlegroundDS() BgObjects.resize(BG_DS_OBJECT_MAX); BgCreatures.resize(BG_DS_NPC_MAX); - _waterfallTimer = 0; - _waterfallStatus = 0; - _waterfallKnockbackTimer = 0; _pipeKnockBackTimer = 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) @@ -56,64 +40,58 @@ void BattlegroundDS::PostUpdateImpl(uint32 diff) if (GetStatus() != STATUS_IN_PROGRESS) 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) - if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[i])) + if (Creature* waterSpout = GetBGCreature(i)) waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true); - setPipeKnockBackCount(getPipeKnockBackCount() + 1); - setPipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_DELAY); + ++_pipeKnockBackCount; + _pipeKnockBackTimer = BG_DS_PIPE_KNOCKBACK_DELAY; } 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() @@ -130,11 +108,12 @@ void BattlegroundDS::StartingEventOpenDoors() for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i) SpawnBGObject(i, 60); - setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); - setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF); + _events.ScheduleEvent(BG_DS_EVENT_WATERFALL_WARNING, BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX); + //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); - setPipeKnockBackCount(0); + _pipeKnockBackCount = 0; + _pipeKnockBackTimer = BG_DS_PIPE_KNOCKBACK_FIRST_DELAY; SpawnBGObject(BG_DS_OBJECT_WATER_2, RESPAWN_IMMEDIATELY); DoorOpen(BG_DS_OBJECT_WATER_2); @@ -149,39 +128,6 @@ void BattlegroundDS::StartingEventOpenDoors() 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) { if (GetStatus() != STATUS_IN_PROGRESS) @@ -192,13 +138,13 @@ void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger) case 5347: case 5348: // Remove effects of Demonic Circle Summon - if (player->HasAura(48018)) - player->RemoveAurasDueToSpell(48018); + if (player->HasAura(SPELL_WARL_DEMONIC_CIRCLE)) + player->RemoveAurasDueToSpell(SPELL_WARL_DEMONIC_CIRCLE); // 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. - if (getPipeKnockBackCount() >= BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT) - setPipeKnockBackCount(0); + if (_pipeKnockBackCount >= BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT) + _pipeKnockBackCount = 0; break; // OUTSIDE OF ARENA, TELEPORT! case 5328: @@ -218,6 +164,9 @@ void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger) case 5344: // -60 player->NearTeleportTo(1330.0f, 800.0f, 3.16f, player->GetOrientation()); break; + /*default: + Battleground::HandleAreaTrigger(player, trigger); + break;*/ } } @@ -230,13 +179,7 @@ bool BattlegroundDS::HandlePlayerUnderMap(Player* player) void BattlegroundDS::FillInitialWorldStates(WorldPacket& data) { data << uint32(3610) << uint32(1); // 9 show - Battleground::UpdateArenaWorldState(); -} - -void BattlegroundDS::Init() -{ - //call parent's class reset - Battleground::Init(); + Arena::FillInitialWorldStates(data); } bool BattlegroundDS::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h index 42b764e99..3ff673154 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h @@ -18,7 +18,9 @@ #ifndef __BATTLEGROUNDDS_H #define __BATTLEGROUNDDS_H -#include "Battleground.h" +#include "Arena.h" +#include "Duration.h" +#include "EventMap.h" enum BattlegroundDSObjectTypes { @@ -33,7 +35,7 @@ enum BattlegroundDSObjectTypes BG_DS_OBJECT_MAX = 8 }; -enum BattlegroundDSObjects +enum BattlegroundDSGameObjects { BG_DS_OBJECT_TYPE_DOOR_1 = 192642, 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_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 + SPELL_WARL_DEMONIC_CIRCLE = 48018 // Demonic Circle Summon }; 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_DELAY = 3000, - 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, + BG_DS_PIPE_KNOCKBACK_FIRST_DELAY = 5000, + BG_DS_PIPE_KNOCKBACK_DELAY = 3000, + BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT = 2, }; -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: BattlegroundDS(); - ~BattlegroundDS() override; /* inherited from BattlegroundClass */ - void AddPlayer(Player* player) override; void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; - void RemovePlayer(Player* player) override; void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void Init() override; void FillInitialWorldStates(WorldPacket& d) override; - void HandleKillPlayer(Player* player, Player* killer) override; bool HandlePlayerUnderMap(Player* player) override; + private: - uint32 _waterfallTimer; - uint8 _waterfallStatus; - uint32 _waterfallKnockbackTimer; + void PostUpdateImpl(uint32 diff) override; + uint32 _pipeKnockBackTimer; uint8 _pipeKnockBackCount; - void PostUpdateImpl(uint32 diff) override; -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; }; + EventMap _events; }; + #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index 5af09724d..d7c00426f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -28,6 +28,12 @@ #include "WorldPacket.h" #include "WorldSession.h" +void BattlegroundEYScore::BuildObjectivesBlock(WorldPacket& data) +{ + data << uint32(1); // Objectives Count + data << uint32(FlagCaptures); +} + BattlegroundEY::BattlegroundEY() { m_BuffChange = true; @@ -43,11 +49,6 @@ BattlegroundEY::BattlegroundEY() _ownedPointsCount[TEAM_HORDE] = 0; _flagState = BG_EY_FLAG_STATE_ON_BASE; _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() @@ -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_STATUS, _capturePointInfo[point]._barStatus); ++_capturePointInfo[point]._playersCount[itr->second->GetTeamId()]; + _capturePointInfo[point].player = itr->second; // 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) @@ -165,10 +167,10 @@ void BattlegroundEY::UpdatePointsState() if (pointOwnerTeamId != _capturePointInfo[point]._ownerTeamId) { if (_capturePointInfo[point].IsUncontrolled()) - EventTeamCapturedPoint(pointOwnerTeamId, point); + EventTeamCapturedPoint(_capturePointInfo[point].player, pointOwnerTeamId, point); 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) { Battleground::AddPlayer(player); - PlayerScores[player->GetGUID()] = new BattlegroundEYScore(player); + PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundEYScore(player->GetGUID())); } void BattlegroundEY::RemovePlayer(Player* player) @@ -371,7 +373,7 @@ void BattlegroundEY::RespawnFlag() _flagCapturedObject = 0; 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); UpdateWorldState(NETHERSTORM_FLAG, 1); } @@ -413,7 +415,10 @@ void BattlegroundEY::EventPlayerDroppedFlag(Player* player) player->CastSpell(player, SPELL_RECENTLY_DROPPED_FLAG, 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) @@ -429,12 +434,16 @@ void BattlegroundEY::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb player->CastSpell(player, BG_EY_NETHERSTORM_FLAG_SPELL, true); 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); 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; 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 + 1, 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 { @@ -451,7 +460,7 @@ void BattlegroundEY::EventTeamLostPoint(TeamId /*teamId*/, uint32 point) SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 1, 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); @@ -465,7 +474,7 @@ void BattlegroundEY::EventTeamLostPoint(TeamId /*teamId*/, uint32 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 + 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 + 1, 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 { @@ -485,7 +494,7 @@ void BattlegroundEY::EventTeamCapturedPoint(TeamId teamId, uint32 point) SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 1, 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; @@ -524,12 +533,12 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType if (player->GetTeamId() == TEAM_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 { 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); @@ -537,18 +546,21 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType 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()); - if (itr != PlayerScores.end()) - ((BattlegroundEYScore*)itr->second)->FlagCaptures += value; - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_EY_OBJECTIVE_CAPTURE_FLAG); - return; + case SCORE_FLAG_CAPTURES: + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_EY_OBJECTIVE_CAPTURE_FLAG); + break; + default: + break; } - Battleground::UpdatePlayerScore(player, type, value, doAddHonor); + return true; } void BattlegroundEY::FillInitialWorldStates(WorldPacket& data) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h index c3c868df6..c55a1cfc4 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h @@ -19,8 +19,9 @@ #define __BATTLEGROUNDEY_H #include "Battleground.h" -#include "EventMap.h" +#include "BattlegroundScore.h" #include "Language.h" +#include "EventMap.h" enum BG_EY_Events { @@ -242,6 +243,35 @@ enum BG_EY_FlagState 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 { 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] = { - 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_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_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_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_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, 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, 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, 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] = { - 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_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_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_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_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, 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, 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, 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) { } - ~BattlegroundEYScore() override { } - uint32 FlagCaptures; + friend class BattlegroundEY; - 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: BattlegroundEY(); @@ -354,7 +402,7 @@ public: bool SetupBattleground() override; void Init() 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 SetDroppedFlagGUID(ObjectGuid guid, TeamId /*teamId*/ = TEAM_NEUTRAL) override { _droppedFlagGUID = guid; } ObjectGuid GetDroppedFlagGUID() const { return _droppedFlagGUID; } @@ -371,8 +419,8 @@ private: void PostUpdateImpl(uint32 diff) override; void EventPlayerCapturedFlag(Player* Source, uint32 BgObjectType); - void EventTeamLostPoint(TeamId teamId, uint32 point); - void EventTeamCapturedPoint(TeamId teamId, uint32 point); + void EventTeamLostPoint(Player* player, uint32 point); + void EventTeamCapturedPoint(Player* player, TeamId teamId, uint32 point); void UpdatePointsCount(); void UpdatePointsIcons(uint32 point); @@ -393,7 +441,8 @@ private: TeamId _ownerTeamId; int8 _barStatus; 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() const { return _ownerTeamId != TEAM_NEUTRAL; } @@ -403,7 +452,7 @@ private: CapturePointInfo _capturePointInfo[EY_POINTS_MAX]; EventMap _bgEvents; uint32 _honorTics; - uint8 _ownedPointsCount[BG_TEAMS_COUNT]; + uint8 _ownedPointsCount[PVP_TEAMS_COUNT]; ObjectGuid _flagKeeperGUID; ObjectGuid _droppedFlagGUID; uint8 _flagState; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 44be16384..4756a1c27 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -29,16 +29,18 @@ #include "WorldPacket.h" #include "WorldSession.h" +void BattlegroundICScore::BuildObjectivesBlock(WorldPacket& data) +{ + data << uint32(2); // Objectives Count + data << uint32(BasesAssaulted); + data << uint32(BasesDefended); +} + 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); 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) factionReinforcements[i] = MAX_REINFORCEMENTS; @@ -60,10 +62,6 @@ BattlegroundIC::BattlegroundIC() respawnMap.clear(); } -BattlegroundIC::~BattlegroundIC() -{ -} - void BattlegroundIC::DoAction(uint32 action, ObjectGuid guid) { if (action != ACTION_TELEPORT_PLAYER_TO_TRANSPORT) @@ -246,7 +244,14 @@ void BattlegroundIC::PostUpdateImpl(uint32 diff) UpdateNodeWorldState(&nodePoint[i]); 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].timer = BANNER_STATE_CHANGE_TIME; @@ -272,10 +277,6 @@ void BattlegroundIC::PostUpdateImpl(uint32 diff) else resourceTimer -= diff; } -void BattlegroundIC::StartingEventCloseDoors() -{ -} - void BattlegroundIC::StartingEventOpenDoors() { //after 20 seconds they should be despawned @@ -320,7 +321,7 @@ bool BattlegroundIC::IsResourceGlutAllowed(TeamId teamId) const void BattlegroundIC::AddPlayer(Player* 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)) 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 (itr == PlayerScores.end()) - return; + if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor)) + return false; switch (type) { case SCORE_BASES_ASSAULTED: - ((BattlegroundICScore*)itr->second)->BasesAssaulted += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, IC_OBJECTIVE_ASSAULT_BASE); break; case SCORE_BASES_DEFENDED: - ((BattlegroundICScore*)itr->second)->BasesDefended += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, IC_OBJECTIVE_DEFEND_BASE); break; - default: - Battleground::UpdatePlayerScore(player, type, value, doAddHonor); - break; } + + return true; } void BattlegroundIC::FillInitialWorldStates(WorldPacket& data) @@ -553,12 +550,6 @@ void BattlegroundIC::HandleKillPlayer(Player* player, Player* killer) 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) { if (GetStatus() != STATUS_IN_PROGRESS) @@ -621,8 +612,15 @@ void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); - SendMessage2ToAll(LANG_BG_IC_TEAM_ASSAULTED_NODE_1, CHAT_MSG_BG_SYSTEM_NEUTRAL, player, point.string); - 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)); + if (nodePoint[i].faction == TEAM_ALLIANCE) + { + SendBroadcastText(ICNodes[i].TextAssaulted, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); + } + else + { + SendBroadcastText(ICNodes[i].TextAssaulted, CHAT_MSG_BG_SYSTEM_HORDE, player); + } + HandleContestedNodes(&point); } 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.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); UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); } @@ -926,33 +933,41 @@ void BattlegroundIC::DestroyGate(Player* /*player*/, GameObject* go) UpdateWorldState(uws_open, 1); } + uint32 textId; + ChatMsg msgType; TeamId teamId = TEAM_ALLIANCE; - uint32 lang_entry = 0; + switch (go->GetEntry()) { 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; 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; 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; case GO_ALLIANCE_GATE_1: + textId = BG_IC_TEXT_WEST_GATE_ALLIANCE_DESTROYED; + msgType = CHAT_MSG_BG_SYSTEM_HORDE; teamId = TEAM_HORDE; - lang_entry = LANG_BG_IC_WEST_GATE_DESTROYED; break; case GO_ALLIANCE_GATE_2: + textId = BG_IC_TEXT_EAST_GATE_ALLIANCE_DESTROYED; + msgType = CHAT_MSG_BG_SYSTEM_HORDE; teamId = TEAM_HORDE; - lang_entry = LANG_BG_IC_EAST_GATE_DESTROYED; break; case GO_ALLIANCE_GATE_3: + textId = BG_IC_TEXT_FRONT_GATE_ALLIANCE_DESTROYED; + msgType = CHAT_MSG_BG_SYSTEM_HORDE; teamId = TEAM_HORDE; - lang_entry = LANG_BG_IC_SOUTH_GATE_DESTROYED; break; default: - break; + return; } if (teamId == TEAM_ALLIANCE) @@ -967,11 +982,7 @@ void BattlegroundIC::DestroyGate(Player* /*player*/, GameObject* go) } TurnBosses(true); - SendMessage2ToAll(lang_entry, CHAT_MSG_BG_SYSTEM_NEUTRAL, nullptr, (teamId == TEAM_ALLIANCE ? LANG_BG_IC_HORDE_KEEP : LANG_BG_IC_ALLIANCE_KEEP)); -} - -void BattlegroundIC::EventPlayerDamagedGO(Player* /*player*/, GameObject* /*go*/, uint32 /*eventType*/) -{ + SendBroadcastText(textId, msgType); } GraveyardStruct const* BattlegroundIC::GetClosestGraveyard(Player* player) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h index a1e0caa85..5d1a183db 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h @@ -19,10 +19,10 @@ #define __BATTLEGROUNDIC_H #include "Battleground.h" -#include "Language.h" +#include "BattlegroundScore.h" #include "Object.h" -const uint32 BG_IC_Factions[BG_TEAMS_COUNT] = +const uint32 BG_IC_Factions[PVP_TEAMS_COUNT] = { 1732, // Alliance 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 }; +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 struct ICNodePoint { @@ -867,18 +897,17 @@ struct ICNodePoint uint32 last_entry; // the last gameobject_entry uint32 worldStates[5]; // the worldstates that represent the node in the map 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_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_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_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_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_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_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_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}, + {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}, + {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}, + {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 @@ -887,45 +916,63 @@ enum HonorRewards WINNER_HONOR_AMOUNT = 500 }; -struct BattlegroundICScore : public BattlegroundScore +struct BattlegroundICScore final : public BattlegroundScore { - BattlegroundICScore(Player* player) : BattlegroundScore(player), BasesAssaulted(0), BasesDefended(0) { } - ~BattlegroundICScore() override { } - uint32 BasesAssaulted; - uint32 BasesDefended; + friend class BattlegroundIC; - uint32 GetAttr1() const final { return BasesAssaulted; } - uint32 GetAttr2() const final { return BasesDefended; } +protected: + 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: BattlegroundIC(); - ~BattlegroundIC() override; /* inherited from BattlegroundClass */ void AddPlayer(Player* player) override; - void StartingEventCloseDoors() override; + void StartingEventCloseDoors() override { } void StartingEventOpenDoors() override; void PostUpdateImpl(uint32 diff) override; void RemovePlayer(Player* player) override; void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void SpawnLeader(uint32 teamid); void HandleKillUnit(Creature* unit, Player* killer) override; void HandleKillPlayer(Player* player, Player* killer) override; - void EndBattleground(TeamId winnerTeamId) 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; GraveyardStruct const* GetClosestGraveyard(Player* player) override; /* 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; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp index 6132f1925..817014607 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp @@ -16,28 +16,12 @@ */ #include "BattlegroundNA.h" -#include "Language.h" -#include "ObjectMgr.h" #include "Player.h" #include "WorldPacket.h" BattlegroundNA::BattlegroundNA() { 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() @@ -55,39 +39,6 @@ void BattlegroundNA::StartingEventOpenDoors() 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) { 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) { data << uint32(0xa11) << uint32(1); // 9 - Battleground::UpdateArenaWorldState(); -} - -void BattlegroundNA::Init() -{ - //call parent's class reset - Battleground::Init(); + Arena::FillInitialWorldStates(data); } bool BattlegroundNA::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.h b/src/server/game/Battlegrounds/Zones/BattlegroundNA.h index e83aca2c1..c13eb9d6d 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.h @@ -18,7 +18,7 @@ #ifndef __BATTLEGROUNDNA_H #define __BATTLEGROUNDNA_H -#include "Battleground.h" +#include "Arena.h" enum BattlegroundNAObjectTypes { @@ -33,7 +33,7 @@ enum BattlegroundNAObjectTypes BG_NA_OBJECT_MAX = 8 }; -enum BattlegroundNAObjects +enum BattlegroundNAGameObjects { BG_NA_OBJECT_TYPE_DOOR_1 = 183978, BG_NA_OBJECT_TYPE_DOOR_2 = 183980, @@ -43,23 +43,19 @@ enum BattlegroundNAObjects BG_NA_OBJECT_TYPE_BUFF_2 = 184664 }; -class BattlegroundNA : public Battleground +class AC_GAME_API BattlegroundNA : public Arena { public: BattlegroundNA(); - ~BattlegroundNA() override; /* inherited from BattlegroundClass */ - void AddPlayer(Player* player) override; void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; - void RemovePlayer(Player* player) override; void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void Init() override; void FillInitialWorldStates(WorldPacket& d) override; - void HandleKillPlayer(Player* player, Player* killer) override; bool HandlePlayerUnderMap(Player* player) override; }; + #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp index 670218896..80d36ad75 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp @@ -16,6 +16,7 @@ */ #include "BattlegroundRL.h" +#include "ArenaScore.h" #include "Language.h" #include "Log.h" #include "Player.h" @@ -24,20 +25,6 @@ BattlegroundRL::BattlegroundRL() { 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() @@ -55,39 +42,6 @@ void BattlegroundRL::StartingEventOpenDoors() 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) { 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) { data << uint32(0xbba) << uint32(1); // 9 - Battleground::UpdateArenaWorldState(); -} - -void BattlegroundRL::Init() -{ - //call parent's reset - Battleground::Init(); + Arena::FillInitialWorldStates(data); } bool BattlegroundRL::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.h b/src/server/game/Battlegrounds/Zones/BattlegroundRL.h index e545b39f1..81174f9db 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.h @@ -18,7 +18,7 @@ #ifndef __BATTLEGROUNDRL_H #define __BATTLEGROUNDRL_H -#include "Battleground.h" +#include "Arena.h" enum BattlegroundRLObjectTypes { @@ -39,23 +39,19 @@ enum BattlegroundRLObjects BG_RL_OBJECT_TYPE_BUFF_2 = 184664 }; -class BattlegroundRL : public Battleground +class AC_GAME_API BattlegroundRL : public Arena { public: BattlegroundRL(); - ~BattlegroundRL() override; /* inherited from BattlegroundClass */ - void AddPlayer(Player* player) override; - void Init() override; void FillInitialWorldStates(WorldPacket& d) override; void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; - void RemovePlayer(Player* player) override; void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void HandleKillPlayer(Player* player, Player* killer) override; bool HandlePlayerUnderMap(Player* player) override; }; + #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp index b608050cc..0087d327f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp @@ -16,6 +16,7 @@ */ #include "BattlegroundRV.h" +#include "ArenaScore.h" #include "Battleground.h" #include "GameObject.h" #include "Language.h" @@ -35,24 +36,16 @@ BattlegroundRV::BattlegroundRV() { BgObjects.resize(BG_RV_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; - 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; + _checkPlayersTimer = 0; + _timer = 0s; + _state = 0; } -BattlegroundRV::~BattlegroundRV() { } - void BattlegroundRV::TeleportUnitToNewZ(Unit* unit, float newZ, bool casting) { if (!unit->IsAlive()) return; + unit->NearTeleportTo(unit->GetPositionX(), unit->GetPositionY(), newZ, unit->GetOrientation(), casting); 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_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)) { float groundZ = std::max(groundZ_vmap, groundZ_dyntree); @@ -78,97 +72,99 @@ void BattlegroundRV::PostUpdateImpl(uint32 diff) if (GetStatus() != STATUS_IN_PROGRESS) return; - if (GetTimer() < Milliseconds(diff)) + if (_timer < Milliseconds(diff)) { - switch (getState()) + switch (_state) { case BG_RV_STATE_OPEN_FENCES: + { for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++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) - if (Player* player = itr->second) + _timer = BG_RV_CLOSE_FIRE_TIMER; + _state = BG_RV_STATE_CLOSE_FIRE; + + for (auto const& [playerGuid, player] : m_Players) + { + if (!player) + continue; + + // Demonic Circle Summon + if (GameObject* gObj = player->GetGameObject(48018)) { - // Demonic Circle Summon - if (GameObject* gObj = player->GetGameObject(48018)) - { - gObj->Relocate(gObj->GetPositionX(), gObj->GetPositionY(), 28.28f); - gObj->UpdateObjectVisibility(true); - } - - if (player->GetPositionZ() < 27.0f) - TeleportUnitToNewZ(player, 28.28f, true); - - for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) - if (player->m_SummonSlot[i]) - if (Creature* totem = GetBgMap()->GetCreature(player->m_SummonSlot[i])) - if (totem->GetPositionZ() < 28.0f) - TeleportUnitToNewZ(totem, 28.28f, true); - - for (auto itr2 = player->m_Controlled.begin(); itr2 != player->m_Controlled.end(); ++itr2) - { - if ((*itr2)->GetPositionZ() < 28.0f) - TeleportUnitToNewZ((*itr2), 28.28f, true); - - // Xinef: override stay position - if (CharmInfo* charmInfo = (*itr2)->GetCharmInfo()) - if (charmInfo->IsAtStay()) - { - (*itr2)->StopMovingOnCurrentPos(); - charmInfo->SaveStayPosition(false); - } - } + gObj->Relocate(gObj->GetPositionX(), gObj->GetPositionY(), 28.28f); + gObj->UpdateObjectVisibility(true); } + if (player->GetPositionZ() < 27.0f) + TeleportUnitToNewZ(player, 28.28f, true); + + for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) + if (player->m_SummonSlot[i]) + if (Creature* totem = GetBgMap()->GetCreature(player->m_SummonSlot[i])) + if (totem->GetPositionZ() < 28.0f) + TeleportUnitToNewZ(totem, 28.28f, true); + + for (auto itr2 = player->m_Controlled.begin(); itr2 != player->m_Controlled.end(); ++itr2) + { + if ((*itr2)->GetPositionZ() < 28.0f) + TeleportUnitToNewZ((*itr2), 28.28f, true); + + // Xinef: override stay position + if (CharmInfo* charmInfo = (*itr2)->GetCharmInfo()) + if (charmInfo->IsAtStay()) + { + (*itr2)->StopMovingOnCurrentPos(); + charmInfo->SaveStayPosition(false); + } + } + } + // fix ground on elevators (so aoe spells can be casted there) { - uint32 objects[2] = {BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_ELEVATOR_2}; + uint32 objects[2] = { BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_ELEVATOR_2 }; for (uint8 i = 0; i < 2; ++i) if (GameObject* go = GetBGObject(objects[i])) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_TRANSPORT); } break; + } case BG_RV_STATE_CLOSE_FIRE: for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i) DoorClose(i); // Fire got closed after five seconds, leaves twenty seconds before toggling pillars - SetTimer(BG_RV_FIRE_TO_PILLAR_TIMER); - setState(BG_RV_STATE_SWITCH_PILLARS); + _timer = BG_RV_FIRE_TO_PILLAR_TIMER; + _state = BG_RV_STATE_SWITCH_PILLARS; break; case BG_RV_STATE_SWITCH_PILLARS: UpdatePillars(); - SetTimer(BG_RV_PILLAR_SWITCH_TIMER); + _timer = BG_RV_PILLAR_SWITCH_TIMER; break; } } else - SetTimer(GetTimer() - Milliseconds(diff)); + _timer -= Milliseconds(diff); - if (getState() == BG_RV_STATE_OPEN_FENCES) + if (_state == BG_RV_STATE_OPEN_FENCES) return; - if (CheckPlayersTimer <= diff) + if (_checkPlayersTimer <= diff) { - CheckPlayersTimer = 0; - for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - CheckPositionForUnit(itr->second); + _checkPlayersTimer = 0; + + for (auto const& itr : m_Players) + CheckPositionForUnit(itr.second); // maybe for pets and m_Controlled also, but not really necessary } else - CheckPlayersTimer -= diff; -} - -void BattlegroundRV::StartingEventCloseDoors() -{ + _checkPlayersTimer -= diff; } void BattlegroundRV::StartingEventOpenDoors() { - for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - itr->second->SetPhaseMask(1, true); + for (auto const& itr : m_Players) + itr.second->SetPhaseMask(1, true); // Buff respawn 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_2); - setState(BG_RV_STATE_OPEN_FENCES); - SetTimer(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(); + _state = BG_RV_STATE_OPEN_FENCES; + _timer = BG_RV_FIRST_TIMER; } bool BattlegroundRV::HandlePlayerUnderMap(Player* player) @@ -226,7 +186,7 @@ bool BattlegroundRV::HandlePlayerUnderMap(Player* player) 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; switch (trigger) @@ -251,13 +211,7 @@ void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger) void BattlegroundRV::FillInitialWorldStates(WorldPacket& data) { data << uint32(BG_RV_WORLD_STATE) << uint32(1); - BattlegroundRV::UpdateArenaWorldState(); -} - -void BattlegroundRV::UpdateArenaWorldState() -{ - UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(TEAM_ALLIANCE)); - UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(TEAM_HORDE)); + Arena::FillInitialWorldStates(data); } void BattlegroundRV::Init() @@ -352,5 +306,6 @@ GameObject* BattlegroundRV::GetPillarAtPosition(Position* p) uint32 pillar = GetPillarIdForPos(p); if (!pillar) return nullptr; + return GetBgMap()->GetGameObject(BgObjects[pillar]); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h index a5c00f850..5845b52dd 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h @@ -18,7 +18,7 @@ #ifndef __BATTLEGROUNDRV_H #define __BATTLEGROUNDRV_H -#include "Battleground.h" +#include "Arena.h" enum BattlegroundRVObjectTypes { @@ -48,7 +48,7 @@ enum BattlegroundRVObjectTypes BG_RV_OBJECT_MAX, }; -enum BattlegroundRVObjects +enum BattlegroundRVGameObjects { BG_RV_OBJECT_TYPE_BUFF_1 = 184663, BG_RV_OBJECT_TYPE_BUFF_2 = 184664, @@ -82,43 +82,33 @@ enum BattlegroundRVData BG_RV_WORLD_STATE = 0xe1a, }; -class BattlegroundRV : public Battleground +class AC_GAME_API BattlegroundRV : public Arena { public: BattlegroundRV(); - ~BattlegroundRV() override; /* inherited from BattlegroundClass */ - void AddPlayer(Player* player) override; - void RemovePlayer(Player* player) override; - void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; void Init() override; void FillInitialWorldStates(WorldPacket& d) override; - void UpdateArenaWorldState() override; void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void HandleKillPlayer(Player* player, Player* killer) override; bool HandlePlayerUnderMap(Player* player) override; GameObject* GetPillarAtPosition(Position* p); private: - Milliseconds Timer; - uint32 State; - uint16 CheckPlayersTimer; + Milliseconds _timer; + uint32 _state; + uint16 _checkPlayersTimer; void PostUpdateImpl(uint32 diff) override; 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 CheckPositionForUnit(Unit* unit); void UpdatePillars(); uint32 GetPillarIdForPos(Position* p); }; + #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index f084f3b67..db3dc27e3 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -29,12 +29,16 @@ constexpr Milliseconds BG_SA_BOAT_START = 1min; constexpr Milliseconds BG_SA_WARMUPLENGTH = 2min; constexpr Milliseconds BG_SA_ROUNDLENGTH = 10min; +void BattlegroundSAScore::BuildObjectivesBlock(WorldPacket& data) +{ + data << uint32(2); // Objectives Count + data << uint32(DemolishersDestroyed); + data << uint32(GatesDestroyed); +} + BattlegroundSA::BattlegroundSA() { - StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_SA_START_TWO_MINUTES; - 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; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = 0; BgObjects.resize(BG_SA_MAXOBJ); BgCreatures.resize(static_cast(BG_SA_MAXNPC) + BG_SA_MAX_GY); TimerEnabled = false; @@ -318,7 +322,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff) { SignaledRoundTwo = true; 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 @@ -370,7 +374,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff) if (!SignaledRoundTwoHalfMin) { 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(); @@ -496,11 +500,9 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data) void BattlegroundSA::AddPlayer(Player* player) { Battleground::AddPlayer(player); - //create score and add it to map, default values are set in constructor - BattlegroundSAScore* sc = new BattlegroundSAScore(player); + PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundSAScore(player->GetGUID())); SendTransportInit(player); - PlayerScores[player->GetGUID()] = sc; TeleportToEntrancePosition(player); } @@ -515,20 +517,6 @@ void BattlegroundSA::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) 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() { for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h index 337e158b8..8f3d86db8 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h @@ -19,17 +19,7 @@ #define __BATTLEGROUNDSA_H #include "Battleground.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; } -}; +#include "BattlegroundScore.h" #define BG_SA_FLAG_AMOUNT 3 #define BG_SA_DEMOLISHER_AMOUNT 4 @@ -405,6 +395,15 @@ float const BG_SA_GYOrientation[BG_SA_MAX_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 { TeamId winner; @@ -420,8 +419,40 @@ const float SOTADefPortalDest[5][4] = { 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 BattlegroundSA : public Battleground +class AC_GAME_API BattlegroundSA : public Battleground { public: BattlegroundSA(); @@ -491,10 +522,6 @@ public: void RemovePlayer(Player* player) 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 void DefendersPortalTeleport(GameObject* portal, Player* plr); @@ -620,6 +647,6 @@ private: bool _relicClicked; // Achievement: Not Even a Scratch - bool _notEvenAScratch[BG_TEAMS_COUNT]; + bool _notEvenAScratch[PVP_TEAMS_COUNT]; }; #endif diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index f8a30fe5f..a6c519202 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -26,15 +26,21 @@ #include "World.h" #include "WorldPacket.h" +void BattlegroundWGScore::BuildObjectivesBlock(WorldPacket& data) +{ + data << uint32(2); // Objectives Count + data << uint32(FlagCaptures); + data << uint32(FlagReturns); +} + BattlegroundWS::BattlegroundWS() { BgObjects.resize(BG_WS_OBJECT_MAX); BgCreatures.resize(BG_CREATURES_MAX_WS); - StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; - StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; + StartMessageIds[BG_STARTING_EVENT_SECOND] = BG_WS_TEXT_START_ONE_MINUTE; + StartMessageIds[BG_STARTING_EVENT_THIRD] = BG_WS_TEXT_START_HALF_MINUTE; + StartMessageIds[BG_STARTING_EVENT_FOURTH] = BG_WS_TEXT_BATTLE_HAS_BEGUN; _flagState[TEAM_ALLIANCE] = 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: SpawnBGObject(BG_WS_OBJECT_H_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); break; case BG_WS_EVENT_ALLIANCE_DROP_FLAG: @@ -134,7 +140,7 @@ void BattlegroundWS::StartingEventOpenDoors() void BattlegroundWS::AddPlayer(Player* player) { Battleground::AddPlayer(player); - PlayerScores[player->GetGUID()] = new BattlegroundWGScore(player); + PlayerScores.emplace(player->GetGUID().GetCounter(), new BattlegroundWGScore(player->GetGUID())); } void BattlegroundWS::RespawnFlagAfterDrop(TeamId teamId) @@ -144,7 +150,7 @@ void BattlegroundWS::RespawnFlagAfterDrop(TeamId teamId) UpdateFlagState(teamId, BG_WS_FLAG_STATE_ON_BASE); 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); if (GameObject* flag = GetBgMap()->GetGameObject(GetDroppedFlagGUID(teamId))) @@ -187,18 +193,19 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* player) AddPoints(player->GetTeamId(), 1); SetFlagPicker(ObjectGuid::Empty, GetOtherTeamId(player->GetTeamId())); UpdateFlagState(GetOtherTeamId(player->GetTeamId()), BG_WS_FLAG_STATE_ON_BASE); + if (player->GetTeamId() == TEAM_ALLIANCE) { player->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); 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); } else { player->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); 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); } @@ -241,14 +248,14 @@ void BattlegroundWS::EventPlayerDroppedFlag(Player* player) { UpdateFlagState(TEAM_HORDE, BG_WS_FLAG_STATE_ON_GROUND); 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); } else { UpdateFlagState(TEAM_ALLIANCE, BG_WS_FLAG_STATE_ON_GROUND); 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); } } @@ -270,7 +277,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED); 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) { @@ -290,7 +297,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED); 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) { @@ -315,7 +322,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1); 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_KEPT15); RemoveAssaultAuras(); @@ -332,7 +339,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb player->CastSpell(player, assaultSpellId, true); 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; } } @@ -348,7 +355,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb UpdatePlayerScore(player, SCORE_FLAG_RETURNS, 1); 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_KEPT15); RemoveAssaultAuras(); @@ -365,7 +372,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb player->CastSpell(player, assaultSpellId, true); 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; } } @@ -509,26 +516,22 @@ void BattlegroundWS::HandleKillPlayer(Player* player, 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 (itr == PlayerScores.end()) - return; + if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor)) + return false; switch (type) { case SCORE_FLAG_CAPTURES: - ((BattlegroundWGScore*)itr->second)->FlagCaptures += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG); break; case SCORE_FLAG_RETURNS: - ((BattlegroundWGScore*)itr->second)->FlagReturns += value; player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG); break; - default: - Battleground::UpdatePlayerScore(player, type, value, doAddHonor); - break; } + + return true; } GraveyardStruct const* BattlegroundWS::GetClosestGraveyard(Player* player) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h index 4330abec9..cfedd1894 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h @@ -19,6 +19,7 @@ #define __BATTLEGROUNDWS_H #include "Battleground.h" +#include "BattlegroundScore.h" #include "EventMap.h" enum BG_WS_Events @@ -43,6 +44,23 @@ enum BG_WS_TimerOrScore 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 { BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, @@ -164,18 +182,39 @@ enum BG_WS_Trigger 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) { } - ~BattlegroundWGScore() override { } - uint32 FlagCaptures; - uint32 FlagReturns; + friend class BattlegroundWS; - uint32 GetAttr1() const final { return FlagCaptures; } - uint32 GetAttr2() const final { return FlagReturns; } +protected: + 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: /* Construction */ @@ -208,7 +247,7 @@ public: GraveyardStruct const* GetClosestGraveyard(Player* player) override; 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; } ObjectGuid GetDroppedFlagGUID(TeamId teamId) const { return _droppedFlagGUID[teamId];} void FillInitialWorldStates(WorldPacket& data) override; @@ -234,4 +273,5 @@ private: void PostUpdateImpl(uint32 diff) override; }; + #endif diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index 29b5a6261..c50740cf8 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -340,7 +340,7 @@ void WorldSession::HandlePVPLogDataOpcode(WorldPacket& /*recvData*/) return; WorldPacket data; - sBattlegroundMgr->BuildPvpLogDataPacket(&data, bg); + bg->BuildPvPLogDataPacket(data); SendPacket(&data); LOG_DEBUG("network", "WORLD: Sent MSG_PVP_LOG_DATA Message"); diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index e93e920de..e5ec2da7d 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -94,7 +94,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) // TODO: find correct opcode 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; } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index ac1dde52c..df6bf3d71 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -645,79 +645,7 @@ enum AcoreStrings // End Level 3 list, continued at 1100 - // Battleground - 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, + // 600-704 - free LANG_WAIT_BEFORE_SPEAKING = 705, 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_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_GOLD_WINS = 724, // "The Gold Team wins!" - LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!" - // = 726, see LANG_ARENA_QUEUE_ANNOUNCE_WORLD + // 724-726 - free 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_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_SECS = 751, // "Not enough players. This game will close in %u seconds." // = 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 LANG_ARENA_TESTING = 785, @@ -1030,32 +953,9 @@ enum AcoreStrings LANG_DEBUG_AREATRIGGER_OFF = 1203, LANG_DEBUG_AREATRIGGER_REACHED = 1204, - // Isle of Conquest - 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, + // 1205-1299 - free - // 1302-1325 + // 1300-1333 // AV LANG_BG_AV_ALLY = 1300, LANG_BG_AV_HORDE = 1301, @@ -1086,14 +986,10 @@ enum AcoreStrings LANG_BG_AV_NODE_TOWER_FROST_W = 1324, LANG_BG_AV_NODE_GRAVE_FROST_HUT = 1325, - LANG_BG_AV_START_ONE_MINUTE = 1326, - 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, + // 1326-1330 - free + LANG_BG_AV_H_CAPTAIN_DEAD = 1331, LANG_BG_AV_A_CAPTAIN_DEAD = 1332, - LANG_BG_AV_START_TWO_MINUTES = 1333, //Player Ticket Strings LANG_TICKET_CLOSED = 1334, diff --git a/src/server/shared/SharedDefines.h b/src/server/shared/SharedDefines.h index 20c327189..7bc7f047f 100644 --- a/src/server/shared/SharedDefines.h +++ b/src/server/shared/SharedDefines.h @@ -3407,13 +3407,20 @@ enum PvPTeamId PVP_TEAM_NEUTRAL = 2 // Battleground: Neutral, Arena: None }; +uint8 constexpr PVP_TEAMS_COUNT = 2; + inline PvPTeamId GetPvPTeamId(TeamId teamId) { 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 -enum BattlegroundTypeId +enum BattlegroundTypeId : uint8 { BATTLEGROUND_TYPE_NONE = 0, // None 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 -enum BattlegroundQueueTypeId +enum BattlegroundQueueTypeId : uint8 { BATTLEGROUND_QUEUE_NONE = 0, BATTLEGROUND_QUEUE_AV = 1,