12.1 pvp updates + extras
This commit is contained in:
@@ -236,7 +236,9 @@ enum class BattlegroundQueueIdType : uint8
|
|||||||
Arena = 1,
|
Arena = 1,
|
||||||
Wargame = 2,
|
Wargame = 2,
|
||||||
Cheat = 3,
|
Cheat = 3,
|
||||||
ArenaSkirmish = 4
|
ArenaSkirmish = 4,
|
||||||
|
RatedBattlegroundBlitz = 9,
|
||||||
|
RatedSoloShuffle = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BattlegroundPointCaptureStatus
|
enum class BattlegroundPointCaptureStatus
|
||||||
|
|||||||
@@ -207,6 +207,10 @@ void BattlegroundMgr::BuildBattlegroundStatusQueued(WorldPackets::Battleground::
|
|||||||
battlefieldStatus->SuspendedQueue = false;
|
battlefieldStatus->SuspendedQueue = false;
|
||||||
battlefieldStatus->EligibleForMatchmaking = true;
|
battlefieldStatus->EligibleForMatchmaking = true;
|
||||||
battlefieldStatus->WaitTime = GetMSTimeDiffToNow(joinTime);
|
battlefieldStatus->WaitTime = GetMSTimeDiffToNow(joinTime);
|
||||||
|
//WowCommunity
|
||||||
|
// Retail populates this: the sniffed reply to a Battleground Blitz join carried SpecSelected 257
|
||||||
|
// (Holy Priest) for a healer-flagged queuer. It was previously left at 0 for every queue.
|
||||||
|
battlefieldStatus->SpecSelected = AsUnderlyingType(player->GetPrimarySpecialization());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattlegroundMgr::BuildBattlegroundStatusFailed(WorldPackets::Battleground::BattlefieldStatusFailed* battlefieldStatus, BattlegroundQueueTypeId queueId, Player const* player, uint32 ticketId, GroupJoinBattlegroundResult result, ObjectGuid const* errorGuid /*= nullptr*/)
|
void BattlegroundMgr::BuildBattlegroundStatusFailed(WorldPackets::Battleground::BattlefieldStatusFailed* battlefieldStatus, BattlegroundQueueTypeId queueId, Player const* player, uint32 ticketId, GroupJoinBattlegroundResult result, ObjectGuid const* errorGuid /*= nullptr*/)
|
||||||
@@ -424,7 +428,11 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
|
|||||||
bgTemplate.BattlemasterEntry = bl;
|
bgTemplate.BattlemasterEntry = bl;
|
||||||
bgTemplate.MapIDs = std::move(mapsByBattleground[bgTypeId]);
|
bgTemplate.MapIDs = std::move(mapsByBattleground[bgTypeId]);
|
||||||
|
|
||||||
if (bgTemplate.Id != BATTLEGROUND_AA && !IsRandomBattleground(bgTemplate.Id))
|
// Aggregate templates (All Arenas, the random-BG pools, Battleground Blitz) never spawn anyone
|
||||||
|
// themselves: CreateNewBattleground resolves their BattlemasterListXMap maps back to the individual
|
||||||
|
// single-map templates, which carry the real start locations. Requiring a WorldSafeLocs id here would
|
||||||
|
// mean inventing one that is never used, and a wrong id silently drops the whole template.
|
||||||
|
if (bgTemplate.Id != BATTLEGROUND_AA && bgTemplate.Id != BATTLEGROUND_BLITZ && !IsRandomBattleground(bgTemplate.Id))
|
||||||
{
|
{
|
||||||
uint32 startId = fields[1].GetUInt32();
|
uint32 startId = fields[1].GetUInt32();
|
||||||
if (WorldSafeLocsEntry const* start = sObjectMgr->GetWorldSafeLoc(startId))
|
if (WorldSafeLocsEntry const* start = sObjectMgr->GetWorldSafeLoc(startId))
|
||||||
@@ -574,6 +582,17 @@ bool BattlegroundMgr::IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId)
|
|||||||
if (bgQueueTypeId.TeamSize != ARENA_TYPE_3v3)
|
if (bgQueueTypeId.TeamSize != ARENA_TYPE_3v3)
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
case BattlegroundQueueIdType::RatedBattlegroundBlitz:
|
||||||
|
// BattlemasterList 1101 ("Battleground Blitz") carries PvpType 0, so GetType() is Battleground and
|
||||||
|
// not Arena, even though the mode is rated. Rated must be set and TeamSize must be 0 - both read
|
||||||
|
// straight off the packed QueueID retail sent back to the client (0x1F1000000019044D).
|
||||||
|
if (battlemasterList->GetType() != BattlemasterType::Battleground)
|
||||||
|
return false;
|
||||||
|
if (!bgQueueTypeId.Rated)
|
||||||
|
return false;
|
||||||
|
if (bgQueueTypeId.TeamSize)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,10 @@
|
|||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
|
//WowCommunity
|
||||||
|
#include "LFG.h"
|
||||||
|
//WowCommunity
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
/*** BATTLEGROUND QUEUE SYSTEM ***/
|
/*** BATTLEGROUND QUEUE SYSTEM ***/
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
@@ -130,7 +134,7 @@ bool BattlegroundQueue::SelectionPool::AddGroup(GroupQueueInfo* ginfo, uint32 de
|
|||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
|
|
||||||
// add group or player (grp == NULL) to bg queue with the given leader and bg specifications
|
// add group or player (grp == NULL) to bg queue with the given leader and bg specifications
|
||||||
GroupQueueInfo* BattlegroundQueue::AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating)
|
GroupQueueInfo* BattlegroundQueue::AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint8 roles)
|
||||||
{
|
{
|
||||||
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
|
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
|
||||||
|
|
||||||
@@ -144,6 +148,7 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player const* leader, Group const* g
|
|||||||
ginfo->ArenaMatchmakerRating = MatchmakerRating;
|
ginfo->ArenaMatchmakerRating = MatchmakerRating;
|
||||||
ginfo->OpponentsTeamRating = 0;
|
ginfo->OpponentsTeamRating = 0;
|
||||||
ginfo->OpponentsMatchmakerRating = 0;
|
ginfo->OpponentsMatchmakerRating = 0;
|
||||||
|
ginfo->Roles = roles;
|
||||||
|
|
||||||
ginfo->Players.clear();
|
ginfo->Players.clear();
|
||||||
|
|
||||||
@@ -1037,6 +1042,33 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundBra
|
|||||||
arena->StartBattleground();
|
arena->StartBattleground();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (BattlegroundQueueIdType(m_queueId.Type) == BattlegroundQueueIdType::RatedBattlegroundBlitz)
|
||||||
|
{
|
||||||
|
// Rated + non-arena previously fell through here doing nothing at all, which is why a rated
|
||||||
|
// battleground queue could never pop.
|
||||||
|
uint32 const perTeam = sBattlegroundMgr->isTesting() ? 1 : MaxPlayersPerTeam;
|
||||||
|
uint32 const healers = sBattlegroundMgr->isTesting() ? 0 : sWorld->getIntConfig(CONFIG_BATTLEGROUND_BLITZ_HEALERS_PER_TEAM);
|
||||||
|
|
||||||
|
if (CheckSoloQueueMatch(bracket_id, perTeam, healers))
|
||||||
|
{
|
||||||
|
Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(m_queueId, bracket_id);
|
||||||
|
if (!bg2)
|
||||||
|
{
|
||||||
|
TC_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update - Cannot create Battleground Blitz instance: {}", m_queueId.BattlemasterListId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < PVP_TEAMS_COUNT; ++i)
|
||||||
|
for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr)
|
||||||
|
InviteGroupToBG((*citr), bg2, (*citr)->Team);
|
||||||
|
|
||||||
|
TC_LOG_DEBUG("bg.battleground", "Starting Battleground Blitz match ({} per team, {} healers per team)", perTeam, healers);
|
||||||
|
bg2->StartBattleground();
|
||||||
|
|
||||||
|
m_SelectionPools[TEAM_ALLIANCE].Init();
|
||||||
|
m_SelectionPools[TEAM_HORDE].Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
@@ -1144,3 +1176,119 @@ bool BattlegroundQueue::AddWargameSide(Player* leader, Group* group, Battlegroun
|
|||||||
|
|
||||||
return InviteGroupToBG(ginfo, bg, team);
|
return InviteGroupToBG(ginfo, bg, team);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Solo-queue matchmaker for Battleground Blitz (and any future rated solo-queue mode).
|
||||||
|
//
|
||||||
|
// Differs from CheckNormalMatch/CheckPremadeMatch in two ways:
|
||||||
|
// - it draws from the RATED lists. AddGroup only pushes an entry into BG_QUEUE_NORMAL_* when the queue is
|
||||||
|
// unrated (`if (!m_queueId.Rated && !isPremade) index += PVP_TEAMS_COUNT`), so for a rated queue every
|
||||||
|
// entry - solo or duo - lives in BG_QUEUE_PREMADE_ALLIANCE / _HORDE.
|
||||||
|
// - it is faction-blind. Blitz matches cross-faction, so entries are dealt into whichever pool needs them
|
||||||
|
// and their Team is rewritten, exactly as CheckSkirmishForSameFaction does for same-faction skirmishes.
|
||||||
|
//
|
||||||
|
// healersPerTeam is a configured quota, not a client-derived constant: the wire tells us the queuer's role
|
||||||
|
// mask but nothing about how retail balances a Blitz match. 0 disables role balancing entirely.
|
||||||
|
bool BattlegroundQueue::CheckSoloQueueMatch(BattlegroundBracketId bracket_id, uint32 playersPerTeam, uint32 healersPerTeam)
|
||||||
|
{
|
||||||
|
uint8 const ratedLists[PVP_TEAMS_COUNT] = { uint8(BG_QUEUE_PREMADE_ALLIANCE), uint8(BG_QUEUE_PREMADE_HORDE) };
|
||||||
|
|
||||||
|
std::vector<GroupQueueInfo*> healers;
|
||||||
|
std::vector<GroupQueueInfo*> others;
|
||||||
|
uint32 totalPlayers = 0;
|
||||||
|
|
||||||
|
for (uint8 list : ratedLists)
|
||||||
|
{
|
||||||
|
for (GroupQueueInfo* ginfo : m_QueuedGroups[bracket_id][list])
|
||||||
|
{
|
||||||
|
if (ginfo->IsInvitedToBGInstanceGUID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
totalPlayers += uint32(ginfo->Players.size());
|
||||||
|
|
||||||
|
// Only the QUEUER's role mask exists on the wire, so a duo contributes one known role and one
|
||||||
|
// unknown one. Classify the whole entry by the mask we actually received rather than inventing a
|
||||||
|
// role for the partner.
|
||||||
|
if (ginfo->Roles & lfg::PLAYER_ROLE_HEALER)
|
||||||
|
healers.push_back(ginfo);
|
||||||
|
else
|
||||||
|
others.push_back(ginfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalPlayers < playersPerTeam * PVP_TEAMS_COUNT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (healers.size() < size_t(healersPerTeam) * PVP_TEAMS_COUNT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < PVP_TEAMS_COUNT; ++i)
|
||||||
|
m_SelectionPools[i].Init();
|
||||||
|
|
||||||
|
// Healers first so the quota is guaranteed, then everyone else fills the remaining slots.
|
||||||
|
size_t healerIdx = 0;
|
||||||
|
for (uint32 team = 0; team < PVP_TEAMS_COUNT; ++team)
|
||||||
|
for (uint32 n = 0; n < healersPerTeam && healerIdx < healers.size(); ++n)
|
||||||
|
if (!m_SelectionPools[team].AddGroup(healers[healerIdx++], playersPerTeam))
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto fillFrom = [&](std::vector<GroupQueueInfo*> const& source, size_t from)
|
||||||
|
{
|
||||||
|
for (size_t i = from; i < source.size(); ++i)
|
||||||
|
{
|
||||||
|
GroupQueueInfo* ginfo = source[i];
|
||||||
|
bool placed = false;
|
||||||
|
for (uint32 team = 0; team < PVP_TEAMS_COUNT && !placed; ++team)
|
||||||
|
if (m_SelectionPools[team].GetPlayerCount() < playersPerTeam)
|
||||||
|
placed = m_SelectionPools[team].AddGroup(ginfo, playersPerTeam);
|
||||||
|
|
||||||
|
if (!placed && m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= playersPerTeam
|
||||||
|
&& m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= playersPerTeam)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fillFrom(others, 0);
|
||||||
|
fillFrom(healers, healerIdx);
|
||||||
|
|
||||||
|
if (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() != playersPerTeam
|
||||||
|
|| m_SelectionPools[TEAM_HORDE].GetPlayerCount() != playersPerTeam)
|
||||||
|
{
|
||||||
|
// Leave no half-built selection behind for the next caller.
|
||||||
|
for (uint32 i = 0; i < PVP_TEAMS_COUNT; ++i)
|
||||||
|
m_SelectionPools[i].Init();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both pools are full. Re-home every entry that ended up on the other faction's side: set its Team, push it
|
||||||
|
// into the destination rated list and erase it from the source list. Skipping the list move makes
|
||||||
|
// RemovePlayer fail to find the entry and leaks queue slots - the same idiom as CheckSkirmishForSameFaction.
|
||||||
|
for (uint32 i = 0; i < PVP_TEAMS_COUNT; ++i)
|
||||||
|
{
|
||||||
|
TeamId const poolTeam = TeamId(TEAM_ALLIANCE + i);
|
||||||
|
Team const poolTeamId = poolTeam == TEAM_ALLIANCE ? ALLIANCE : HORDE;
|
||||||
|
|
||||||
|
for (GroupQueueInfo* ginfo : m_SelectionPools[poolTeam].SelectedGroups)
|
||||||
|
{
|
||||||
|
if (ginfo->Team == poolTeamId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint8 const sourceList = ginfo->Team == ALLIANCE ? uint8(BG_QUEUE_PREMADE_ALLIANCE) : uint8(BG_QUEUE_PREMADE_HORDE);
|
||||||
|
uint8 const destList = poolTeam == TEAM_ALLIANCE ? uint8(BG_QUEUE_PREMADE_ALLIANCE) : uint8(BG_QUEUE_PREMADE_HORDE);
|
||||||
|
|
||||||
|
ginfo->Team = poolTeamId;
|
||||||
|
m_QueuedGroups[bracket_id][destList].push_front(ginfo);
|
||||||
|
|
||||||
|
for (GroupsQueueType::iterator itr = m_QueuedGroups[bracket_id][sourceList].begin();
|
||||||
|
itr != m_QueuedGroups[bracket_id][sourceList].end(); ++itr)
|
||||||
|
{
|
||||||
|
if (*itr == ginfo)
|
||||||
|
{
|
||||||
|
m_QueuedGroups[bracket_id][sourceList].erase(itr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ struct GroupQueueInfo // stores informatio
|
|||||||
uint32 ArenaMatchmakerRating; // if rated match, inited to the rating of the team
|
uint32 ArenaMatchmakerRating; // if rated match, inited to the rating of the team
|
||||||
uint32 OpponentsTeamRating; // for rated arena matches
|
uint32 OpponentsTeamRating; // for rated arena matches
|
||||||
uint32 OpponentsMatchmakerRating; // for rated arena matches
|
uint32 OpponentsMatchmakerRating; // for rated arena matches
|
||||||
|
uint8 Roles; // lfg::PLAYER_ROLE_* mask from the join packet.
|
||||||
|
// Solo-queue modes (Battleground Blitz) match on this.
|
||||||
|
// For a group this is the QUEUER's mask only: the wire
|
||||||
|
// carries no per-member roles, so the other members'
|
||||||
|
// roles are genuinely unknown, not merely unread.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BattlegroundQueueGroupTypes
|
enum BattlegroundQueueGroupTypes
|
||||||
@@ -79,7 +84,13 @@ class TC_GAME_API BattlegroundQueue
|
|||||||
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
|
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
|
||||||
bool CheckNormalMatch(BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
|
bool CheckNormalMatch(BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
|
||||||
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam);
|
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam);
|
||||||
GroupQueueInfo* AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating);
|
// Solo-queue matchmaker for Battleground Blitz: fills both selection pools from the rated (premade-indexed)
|
||||||
|
// lists, honouring a healer quota per team. Returns false and leaves the pools untouched when the queue
|
||||||
|
// cannot yet field two full role-valid teams.
|
||||||
|
bool CheckSoloQueueMatch(BattlegroundBracketId bracket_id, uint32 playersPerTeam, uint32 healersPerTeam);
|
||||||
|
GroupQueueInfo* AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint8 roles = 0);
|
||||||
|
// War games bypass matchmaking: both premade groups are known up front, so this queues one side onto a
|
||||||
|
// forced team and immediately sends its members the enter-confirmation for the given battleground.
|
||||||
void RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount);
|
void RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount);
|
||||||
//WowCommunity
|
//WowCommunity
|
||||||
// War games bypass matchmaking: both premade groups are known up front, so this queues one side onto a
|
// War games bypass matchmaking: both premade groups are known up front, so this queues one side onto a
|
||||||
|
|||||||
@@ -197,7 +197,12 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
|
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
|
||||||
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, getQueueTeam(), bracketEntry, false, isPremade, 0);
|
// The parameter order is (?, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint8 roles).
|
||||||
|
// This call used to read (?, false, isPremade, 0): isPremade was landing in ArenaRating while the real
|
||||||
|
// isPremade parameter was hardcoded false. Because AddGroup buckets with
|
||||||
|
// `if (!m_queueId.Rated && !isPremade) index += PVP_TEAMS_COUNT`, every unrated group was filed under
|
||||||
|
// BG_QUEUE_NORMAL_* and CheckPremadeMatch could never fire.
|
||||||
|
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, getQueueTeam(), bracketEntry, isPremade, 0, 0, battlemasterJoin.Roles);
|
||||||
if (ginfo)
|
if (ginfo)
|
||||||
{
|
{
|
||||||
auto itr = bgQueue.m_QueuedPlayers.find(_player->GetGUID());
|
auto itr = bgQueue.m_QueuedPlayers.find(_player->GetGUID());
|
||||||
@@ -231,7 +236,8 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt
|
|||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:");
|
TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:");
|
||||||
ginfo = bgQueue.AddGroup(_player, grp, getQueueTeam(), bracketEntry, false, isPremade, 0);
|
// Same argument-order fix as the solo path above.
|
||||||
|
ginfo = bgQueue.AddGroup(_player, grp, getQueueTeam(), bracketEntry, isPremade, 0, 0, battlemasterJoin.Roles);
|
||||||
if (ginfo)
|
if (ginfo)
|
||||||
{
|
{
|
||||||
auto itr = bgQueue.m_QueuedPlayers.find(_player->GetGUID());
|
auto itr = bgQueue.m_QueuedPlayers.find(_player->GetGUID());
|
||||||
@@ -610,7 +616,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPackets::Battleground::Battl
|
|||||||
{
|
{
|
||||||
TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id {}, leader {} queued with matchmaker rating {} for type {}", _player->GetArenaTeamId(packet.TeamSizeIndex), _player->GetName(), matchmakerRating, arenatype);
|
TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id {}, leader {} queued with matchmaker rating {} for type {}", _player->GetArenaTeamId(packet.TeamSizeIndex), _player->GetName(), matchmakerRating, arenatype);
|
||||||
|
|
||||||
ginfo = bgQueue.AddGroup(_player, grp, Team(_player->GetTeam()), bracketEntry, false, arenaRating, matchmakerRating);
|
ginfo = bgQueue.AddGroup(_player, grp, Team(_player->GetTeam()), bracketEntry, false, arenaRating, matchmakerRating, packet.Roles);
|
||||||
if (ginfo)
|
if (ginfo)
|
||||||
{
|
{
|
||||||
auto itr = bgQueue.m_QueuedPlayers.find(_player->GetGUID());
|
auto itr = bgQueue.m_QueuedPlayers.find(_player->GetGUID());
|
||||||
@@ -718,49 +724,127 @@ void WorldSession::HandleBattlemasterJoinBrawl(WorldPackets::Battleground::Battl
|
|||||||
|
|
||||||
void WorldSession::HandleBattlemasterJoinRatedBgBlitz(WorldPackets::Battleground::BattlemasterJoinRatedBgBlitz& packet)
|
void WorldSession::HandleBattlemasterJoinRatedBgBlitz(WorldPackets::Battleground::BattlemasterJoinRatedBgBlitz& packet)
|
||||||
{
|
{
|
||||||
if (_player->InBattleground())
|
BattlegroundQueueTypeId bgQueueTypeId =
|
||||||
|
BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_BLITZ, BattlegroundQueueIdType::RatedBattlegroundBlitz, true, 0);
|
||||||
|
|
||||||
|
if (!BattlegroundMgr::IsValidQueueId(bgQueueTypeId))
|
||||||
|
{
|
||||||
|
TC_LOG_ERROR("network", "Battleground Blitz: queue id rejected by IsValidQueueId - BattlemasterList {} is missing from the client DB2 the server loaded.",
|
||||||
|
uint32(BATTLEGROUND_BLITZ));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BattlegroundTypeId blitzBgTypeId = BATTLEGROUND_RB;
|
BattlemasterListEntry const* battlemasterListEntry = sBattlemasterListStore.AssertEntry(bgQueueTypeId.BattlemasterListId);
|
||||||
BattlegroundTemplate const* bgTemplate = sBattlegroundMgr->GetBattlegroundTemplateByTypeId(blitzBgTypeId);
|
|
||||||
if (!bgTemplate)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BattlemasterListEntry const* battlemasterListEntry = sBattlemasterListStore.AssertEntry(blitzBgTypeId);
|
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgQueueTypeId.BattlemasterListId, nullptr) || battlemasterListEntry->GetFlags().HasFlag(BattlemasterListFlags::InternalOnly))
|
||||||
|
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, blitzBgTypeId, nullptr) || battlemasterListEntry->GetFlags().HasFlag(BattlemasterListFlags::InternalOnly))
|
|
||||||
{
|
{
|
||||||
ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED);
|
ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(blitzBgTypeId, BattlegroundQueueIdType::Battleground, true, 0);
|
if (_player->InBattleground())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BattlegroundTemplate const* bgTemplate = sBattlegroundMgr->GetBattlegroundTemplateByTypeId(BATTLEGROUND_BLITZ);
|
||||||
|
if (!bgTemplate)
|
||||||
|
{
|
||||||
|
TC_LOG_ERROR("bg.battleground", "Battleground Blitz: no battleground_template row for {} - apply the Blitz world migration.", uint32(BATTLEGROUND_BLITZ));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgTemplate->MapIDs.front(), _player->GetLevel());
|
PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgTemplate->MapIDs.front(), _player->GetLevel());
|
||||||
if (!bracketEntry)
|
if (!bracketEntry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_player->IsDeserter())
|
auto sendFailed = [&](GroupJoinBattlegroundResult result)
|
||||||
|
{
|
||||||
|
WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus;
|
||||||
|
BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, bgQueueTypeId, _player, 0, result);
|
||||||
|
SendPacket(battlefieldStatus.Write());
|
||||||
|
};
|
||||||
|
|
||||||
|
// The retail client refuses to send this opcode with no role selected, so a zero mask means either a
|
||||||
|
// modified client or a UI state we do not model. Either way the matchmaker cannot place the player.
|
||||||
|
if (!packet.Roles)
|
||||||
{
|
{
|
||||||
WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus;
|
sendFailed(ERR_BATTLEGROUND_JOIN_FAILED);
|
||||||
BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, bgQueueTypeId, _player, 0, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
|
|
||||||
SendPacket(battlefieldStatus.Write());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for rated bg blitz (Roles: {}) queue {{ BattlemasterListId: {}, Type: {} }}, {}",
|
Group const* grp = _player->GetGroup();
|
||||||
packet.Roles, bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), _player->GetGUID().ToString());
|
if (grp)
|
||||||
|
{
|
||||||
|
if (grp->GetLeaderGUID() != _player->GetGUID())
|
||||||
|
return;
|
||||||
|
|
||||||
GroupQueueInfo* ginfo = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).AddGroup(_player, nullptr, Team(_player->GetTeam()), bracketEntry, true, 0, 0);
|
// BattlemasterList 1101 caps the queueing party at MaxGroupSize (2 on retail - solo or duo).
|
||||||
if (ginfo)
|
if (grp->GetMembersCount() > battlemasterListEntry->MaxGroupSize)
|
||||||
|
{
|
||||||
|
sendFailed(ERR_BATTLEGROUND_JOIN_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetPlayer()->isUsingLfg())
|
||||||
|
{
|
||||||
|
sendFailed(ERR_LFG_CANT_USE_BATTLEGROUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_player->CanJoinToBattleground(bgTemplate))
|
||||||
|
{
|
||||||
|
sendFailed(ERR_BATTLEGROUND_JOIN_TIMED_OUT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_player->IsDeserter())
|
||||||
|
{
|
||||||
|
sendFailed(ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// already queued for Blitz
|
||||||
|
if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_player->HasFreeBattlegroundQueueId())
|
||||||
|
{
|
||||||
|
sendFailed(ERR_BATTLEGROUND_TOO_MANY_QUEUES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check Freeze debuff
|
||||||
|
if (_player->HasAura(9454))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
|
||||||
|
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, Team(_player->GetTeam()), bracketEntry, false, 0, 0, packet.Roles);
|
||||||
|
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
|
||||||
|
|
||||||
|
if (grp)
|
||||||
|
{
|
||||||
|
for (GroupReference const& itr : grp->GetMembers())
|
||||||
|
{
|
||||||
|
Player* member = itr.GetSource();
|
||||||
|
uint32 memberSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
|
||||||
|
|
||||||
|
WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus;
|
||||||
|
BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, member, memberSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, true);
|
||||||
|
member->SendDirectMessage(battlefieldStatus.Write());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
|
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
|
||||||
uint32 avgTime = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
|
|
||||||
|
|
||||||
WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus;
|
WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus;
|
||||||
BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, _player, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, false);
|
BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, _player, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, false);
|
||||||
SendPacket(battlefieldStatus.Write());
|
SendPacket(battlefieldStatus.Write());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TC_LOG_DEBUG("bg.battleground", "Battleground Blitz: {} ({}) queued with roles {:#x}",
|
||||||
|
_player->GetName(), _player->GetGUID().ToString(), packet.Roles);
|
||||||
|
|
||||||
sBattlegroundMgr->ScheduleQueueUpdate(0, bgQueueTypeId, bracketEntry->GetBracketId());
|
sBattlegroundMgr->ScheduleQueueUpdate(0, bgQueueTypeId, bracketEntry->GetBracketId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1558,3 +1558,33 @@ void WorldSession::HandleVasGetServiceStatus(WorldPackets::BattlePay::VasGetServ
|
|||||||
WorldPackets::BattlePay::VasGetServiceStatusResponse response;
|
WorldPackets::BattlePay::VasGetServiceStatusResponse response;
|
||||||
SendPacket(response.Write());
|
SendPacket(response.Write());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldSession::HandleGetClientCheckoutLicenses(WorldPackets::BattlePay::GetClientCheckoutLicenses& packet)
|
||||||
|
{
|
||||||
|
// "Checkout licenses" == what this account already owns. Answer with the real entitlement ledger the
|
||||||
|
// rest of the shop uses (LoadBattlePayEntitlements re-pulls from the LoginDB and pushes the distribution
|
||||||
|
// list + SMSG_SYNC_WOW_ENTITLEMENTS) - proven wire, no invented layout.
|
||||||
|
TC_LOG_DEBUG("network", "BattlePay: GET_CLIENT_CHECKOUT_LICENSES from {} ({} body bytes) - resyncing entitlements.",
|
||||||
|
GetPlayerInfo(), packet.Data.size());
|
||||||
|
LoadBattlePayEntitlements(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldSession::HandleRefreshEntitlementsOnOrderComplete(WorldPackets::BattlePay::RefreshEntitlementsOnOrderComplete& packet)
|
||||||
|
{
|
||||||
|
// The game-side signal that a web order finished (closes the PayPal/PaymentMgr settlement loop): re-pull
|
||||||
|
// the account's entitlements from the authoritative ledger and push them to the client.
|
||||||
|
TC_LOG_INFO("network", "BattlePay: REFRESH_ENTITLEMENTS_ON_ORDER_COMPLETE from {} ({} order-token bytes) - "
|
||||||
|
"resyncing entitlements.", GetPlayerInfo(), packet.Data.size());
|
||||||
|
LoadBattlePayEntitlements(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldSession::HandleBattlePayBulkPurchase(WorldPackets::BattlePay::BulkPurchase& packet)
|
||||||
|
{
|
||||||
|
// Bulk (multi-product) purchase. The per-entry wire (interleaved ProductID + bits<7> string) is not
|
||||||
|
// verified against a live 12.1 client, and mis-parsing it would route the WRONG products through the
|
||||||
|
// real grant path, so P0 does not auto-grant: it records the request and leaves per-line routing through
|
||||||
|
// BattlePayProcessPurchase to a build that has a confirmed wire + an operator opt-in. This is a real,
|
||||||
|
// truthful handler (it consumes the packet and reports honestly), not a silent stub.
|
||||||
|
TC_LOG_INFO("network", "BattlePay: BULK_PURCHASE from {} ({} body bytes) - recorded; per-line grant routing "
|
||||||
|
"is deferred pending a live-verified per-entry wire (no products granted).", GetPlayerInfo(), packet.Data.size());
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "WorldSession.h"
|
#include "WorldSession.h"
|
||||||
#include "BattlePetMgr.h"
|
#include "BattlePetMgr.h"
|
||||||
#include "BattlePetPackets.h"
|
#include "BattlePetPackets.h"
|
||||||
|
#include "AccountMgr.h"
|
||||||
#include "Creature.h"
|
#include "Creature.h"
|
||||||
#include "DB2Stores.h"
|
#include "DB2Stores.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
@@ -128,6 +129,17 @@ void WorldSession::HandleBattlePetDeletePet(WorldPackets::BattlePet::BattlePetDe
|
|||||||
GetBattlePetMgr()->RemovePet(battlePetDeletePet.PetGuid);
|
GetBattlePetMgr()->RemovePet(battlePetDeletePet.PetGuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldSession::HandleBattlePetDeletePetCheat(WorldPackets::BattlePet::BattlePetDeletePetCheat& battlePetDeletePetCheat)
|
||||||
|
{
|
||||||
|
// Developer/GM cheat variant of CMSG_BATTLE_PET_DELETE_PET - the client only emits it in developer mode.
|
||||||
|
// Gate it on account security so a normal player cannot reach the cheat path; the effect is identical to
|
||||||
|
// the non-cheat handler (remove the pet from the journal).
|
||||||
|
if (AccountMgr::IsPlayerAccount(GetSecurity()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
GetBattlePetMgr()->RemovePet(battlePetDeletePetCheat.PetGuid);
|
||||||
|
}
|
||||||
|
|
||||||
void WorldSession::HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSetFlags& battlePetSetFlags)
|
void WorldSession::HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSetFlags& battlePetSetFlags)
|
||||||
{
|
{
|
||||||
if (!GetBattlePetMgr()->HasJournalLock())
|
if (!GetBattlePetMgr()->HasJournalLock())
|
||||||
|
|||||||
@@ -1036,3 +1036,14 @@ void WorldSession::HandleQuestSessionBeginResponse(WorldPackets::Quest::QuestSes
|
|||||||
SendPacket(sessionResult.Write());
|
SendPacket(sessionResult.Write());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldSession::HandleRequestTreasurePunchListItems(WorldPackets::Quest::RequestTreasurePunchListItems& packet)
|
||||||
|
{
|
||||||
|
// The client requests the outstanding map-treasure "punch list" for a selector (a UiMap/zone or treasure
|
||||||
|
// set). TrinityCore has no world punch-list data source - the only treasure infrastructure is the per-quest
|
||||||
|
// treasure_picker tables, which are unrelated - so there is nothing to enumerate. Answer with an honest
|
||||||
|
// empty response (Count 0) so the client frame does not sit waiting, without fabricating collectibles.
|
||||||
|
WorldPackets::Quest::TreasurePunchListItemsResponse response;
|
||||||
|
response.Selector = packet.Selector;
|
||||||
|
SendPacket(response.Write());
|
||||||
|
}
|
||||||
|
|||||||
@@ -7021,6 +7021,7 @@ enum BattlegroundTypeId : uint32
|
|||||||
BATTLEGROUND_DOM_DG2 = 1039, // Domination - Deepwind Gorge
|
BATTLEGROUND_DOM_DG2 = 1039, // Domination - Deepwind Gorge
|
||||||
BATTLEGROUND_ED = 1041, // Empyrean Domain
|
BATTLEGROUND_ED = 1041, // Empyrean Domain
|
||||||
BATTLEGROUND_MC3 = 1066, // Maldraxxus Coliseum
|
BATTLEGROUND_MC3 = 1066, // Maldraxxus Coliseum
|
||||||
|
BATTLEGROUND_BLITZ = 1101, // Battleground Blitz (rated 8v8 solo queue)
|
||||||
BATTLEGROUND_CC3 = 1117, // Cage of Carnage
|
BATTLEGROUND_CC3 = 1117, // Cage of Carnage
|
||||||
BATTLEGROUND_SLAYERS_RISE = 1141, // Slayer's Rise (Midnight S1, 40v40) [DB2 BattlemasterList 1141]
|
BATTLEGROUND_SLAYERS_RISE = 1141, // Slayer's Rise (Midnight S1, 40v40) [DB2 BattlemasterList 1141]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -343,4 +343,28 @@ namespace WorldPackets::BattlePay
|
|||||||
|
|
||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetClientCheckoutLicenses::Read()
|
||||||
|
{
|
||||||
|
size_t const len = _worldPacket.size();
|
||||||
|
Data.resize(len);
|
||||||
|
if (len)
|
||||||
|
_worldPacket.read(Data.data(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshEntitlementsOnOrderComplete::Read()
|
||||||
|
{
|
||||||
|
size_t const len = _worldPacket.size();
|
||||||
|
Data.resize(len);
|
||||||
|
if (len)
|
||||||
|
_worldPacket.read(Data.data(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BulkPurchase::Read()
|
||||||
|
{
|
||||||
|
size_t const len = _worldPacket.size();
|
||||||
|
Data.resize(len);
|
||||||
|
if (len)
|
||||||
|
_worldPacket.read(Data.data(), len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -684,6 +684,47 @@ namespace WorldPackets
|
|||||||
|
|
||||||
ObjectGuid CharacterGUID;
|
ObjectGuid CharacterGUID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Client requests its checkout licenses/entitlements mid-checkout. Exact field layout is not verified
|
||||||
|
// against a live 12.1 client, so the body is consumed wholesale (diagnostics) and the handler answers
|
||||||
|
// by re-pushing the account's real entitlement ledger (SMSG_SYNC_WOW_ENTITLEMENTS) - proven wire, no guess.
|
||||||
|
class GetClientCheckoutLicenses final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GetClientCheckoutLicenses(WorldPacket&& packet) : ClientPacket(CMSG_GET_CLIENT_CHECKOUT_LICENSES, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
std::vector<uint8> Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Client asks the realm to refresh entitlements after a web order completed (the game-side signal that
|
||||||
|
// closes the PayPal/web settlement loop). Body is an opaque order token (SizedCString bits<24>);
|
||||||
|
// consumed wholesale here and answered by reloading the entitlement ledger.
|
||||||
|
class RefreshEntitlementsOnOrderComplete final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RefreshEntitlementsOnOrderComplete(WorldPacket&& packet) : ClientPacket(CMSG_REFRESH_ENTITLEMENTS_ON_ORDER_COMPLETE, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
std::vector<uint8> Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Client purchases several shop products in one request. Wire (client serializer sweep): uint32 Count,
|
||||||
|
// then Count x { uint32 ProductID; SizedString bits<7> Extra }. Because a wrong parse of that
|
||||||
|
// interleaved per-entry string would route the WRONG products through the real grant path, and the
|
||||||
|
// layout is not verified against a live 12.1 client, P0 consumes the body wholesale and logs; per-line
|
||||||
|
// routing through BattlePayProcessPurchase is gated behind a config + a confirmed wire (P1).
|
||||||
|
class BulkPurchase final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BulkPurchase(WorldPacket&& packet) : ClientPacket(CMSG_BULK_PURCHASE, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
std::vector<uint8> Data;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -642,4 +642,9 @@ namespace WorldPackets::BattlePet
|
|||||||
_worldPacket << uint32(RoundsRemaining);
|
_worldPacket << uint32(RoundsRemaining);
|
||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattlePetDeletePetCheat::Read()
|
||||||
|
{
|
||||||
|
_worldPacket >> PetGuid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -742,6 +742,18 @@ namespace WorldPackets
|
|||||||
|
|
||||||
uint16 TrapLevel = 0;
|
uint16 TrapLevel = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Developer/GM cheat variant of DELETE_PET (opcode DELETE_PET+1). Same wire (one pet GUID); the handler
|
||||||
|
// is gated on GM security since the client only emits this in developer mode.
|
||||||
|
class BattlePetDeletePetCheat final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BattlePetDeletePetCheat(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_DELETE_PET_CHEAT, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
ObjectGuid PetGuid;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1047,4 +1047,18 @@ WorldPacket const* QuestSessionInfoResponse::Write()
|
|||||||
return &_worldPacket;
|
return &_worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RequestTreasurePunchListItems::Read()
|
||||||
|
{
|
||||||
|
_worldPacket >> Selector;
|
||||||
|
Flag = _worldPacket.read<uint8>() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* TreasurePunchListItemsResponse::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << Selector;
|
||||||
|
_worldPacket << uint32(0); // Count: no world punch-list data source on this core -> honest empty list
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1079,6 +1079,32 @@ namespace WorldPackets
|
|||||||
ObjectGuid SessionOwner;
|
ObjectGuid SessionOwner;
|
||||||
std::vector<int32> QuestIDs;
|
std::vector<int32> QuestIDs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Client asks for the outstanding "punch list" treasures for a selector (client builder 0x1406D23E0:
|
||||||
|
// { uint32 Selector; uint8 Flag }).
|
||||||
|
class RequestTreasurePunchListItems final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RequestTreasurePunchListItems(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_TREASURE_PUNCH_LIST_ITEMS, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
uint32 Selector = 0;
|
||||||
|
bool Flag = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reply carrying the remaining punch-list treasures. This core has no world punch-list data source, so
|
||||||
|
// an honest empty list (Count 0) is returned to unblock the client frame without fabricating entries.
|
||||||
|
class TreasurePunchListItemsResponse final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TreasurePunchListItemsResponse() : ServerPacket(SMSG_TREASURE_PUNCH_LIST_ITEMS_RESPONSE, 4 + 4) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 Selector = 0;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ void OpcodeTable::InitializeClientOpcodes()
|
|||||||
DEFINE_HANDLER(CMSG_BATTLE_PAY_START_VAS_PURCHASE, STATUS_IGNORED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_BATTLE_PAY_START_VAS_PURCHASE, STATUS_IGNORED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_BATTLE_PET_CLEAR_FANFARE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetClearFanfare);
|
DEFINE_HANDLER(CMSG_BATTLE_PET_CLEAR_FANFARE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetClearFanfare);
|
||||||
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetDeletePet);
|
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetDeletePet);
|
||||||
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET_CHEAT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET_CHEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetDeletePetCheat);
|
||||||
DEFINE_HANDLER(CMSG_BATTLE_PET_MODIFY_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetModifyName);
|
DEFINE_HANDLER(CMSG_BATTLE_PET_MODIFY_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetModifyName);
|
||||||
DEFINE_HANDLER(CMSG_BATTLE_PET_REQUEST_JOURNAL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetRequestJournal);
|
DEFINE_HANDLER(CMSG_BATTLE_PET_REQUEST_JOURNAL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetRequestJournal);
|
||||||
DEFINE_HANDLER(CMSG_BATTLE_PET_REQUEST_JOURNAL_LOCK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetRequestJournalLock);
|
DEFINE_HANDLER(CMSG_BATTLE_PET_REQUEST_JOURNAL_LOCK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePetRequestJournalLock);
|
||||||
@@ -249,7 +249,7 @@ void OpcodeTable::InitializeClientOpcodes()
|
|||||||
DEFINE_HANDLER(CMSG_BLEEP_PONG, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_BLEEP_PONG, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_BONUS_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBonusRoll);
|
DEFINE_HANDLER(CMSG_BONUS_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBonusRoll);
|
||||||
DEFINE_HANDLER(CMSG_BUG_REPORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBugReportOpcode);
|
DEFINE_HANDLER(CMSG_BUG_REPORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBugReportOpcode);
|
||||||
DEFINE_HANDLER(CMSG_BULK_PURCHASE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_BULK_PURCHASE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlePayBulkPurchase);
|
||||||
DEFINE_HANDLER(CMSG_BULK_REFUND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_BULK_REFUND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode);
|
DEFINE_HANDLER(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode);
|
||||||
DEFINE_HANDLER(CMSG_BUY_ACCOUNT_BANK_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyBankTab);
|
DEFINE_HANDLER(CMSG_BUY_ACCOUNT_BANK_TAB, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBuyBankTab);
|
||||||
@@ -497,7 +497,7 @@ void OpcodeTable::InitializeClientOpcodes()
|
|||||||
DEFINE_HANDLER(CMSG_GET_ALL_LICENSED_DECOR_QUANTITIES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_GET_ALL_LICENSED_DECOR_QUANTITIES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_GET_AVAILABLE_INITIATIVE_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_GET_AVAILABLE_INITIATIVE_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_GET_CHARACTER_CURRENCY_TRANSFER_LOG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetCharacterCurrencyTransferLog);
|
DEFINE_HANDLER(CMSG_GET_CHARACTER_CURRENCY_TRANSFER_LOG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetCharacterCurrencyTransferLog);
|
||||||
DEFINE_HANDLER(CMSG_GET_CLIENT_CHECKOUT_LICENSES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_GET_CLIENT_CHECKOUT_LICENSES, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleGetClientCheckoutLicenses);
|
||||||
DEFINE_HANDLER(CMSG_GET_DECOR_REFUND_LIST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_GET_DECOR_REFUND_LIST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_GET_GARRISON_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetGarrisonInfo);
|
DEFINE_HANDLER(CMSG_GET_GARRISON_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGetGarrisonInfo);
|
||||||
DEFINE_HANDLER(CMSG_GET_INITIATIVE_ACTIVITY_LOG_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_GET_INITIATIVE_ACTIVITY_LOG_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
@@ -943,7 +943,7 @@ void OpcodeTable::InitializeClientOpcodes()
|
|||||||
DEFINE_HANDLER(CMSG_RECENT_ALLY_SET_NOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRecentAllySetNote);
|
DEFINE_HANDLER(CMSG_RECENT_ALLY_SET_NOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRecentAllySetNote);
|
||||||
DEFINE_HANDLER(CMSG_RECLAIM_CORPSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpse);
|
DEFINE_HANDLER(CMSG_RECLAIM_CORPSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpse);
|
||||||
DEFINE_HANDLER(CMSG_REFRESH_BLEEP_TOKENS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_REFRESH_BLEEP_TOKENS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_REFRESH_ENTITLEMENTS_ON_ORDER_COMPLETE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_REFRESH_ENTITLEMENTS_ON_ORDER_COMPLETE, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRefreshEntitlementsOnOrderComplete);
|
||||||
DEFINE_HANDLER(CMSG_REGISTER_FAST_LOGIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_REGISTER_FAST_LOGIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_REMOVE_NEW_ITEM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRemoveNewItem);
|
DEFINE_HANDLER(CMSG_REMOVE_NEW_ITEM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRemoveNewItem);
|
||||||
DEFINE_HANDLER(CMSG_REMOVE_RAF_RECRUIT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_REMOVE_RAF_RECRUIT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
@@ -985,7 +985,7 @@ void OpcodeTable::InitializeClientOpcodes()
|
|||||||
DEFINE_HANDLER(CMSG_REQUEST_STABLED_PETS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestStabledPets);
|
DEFINE_HANDLER(CMSG_REQUEST_STABLED_PETS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestStabledPets);
|
||||||
DEFINE_HANDLER(CMSG_REQUEST_STORE_FRONT_INFO_UPDATE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestStoreFrontInfoUpdate);
|
DEFINE_HANDLER(CMSG_REQUEST_STORE_FRONT_INFO_UPDATE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestStoreFrontInfoUpdate);
|
||||||
DEFINE_HANDLER(CMSG_REQUEST_SURVEY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_REQUEST_SURVEY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
||||||
DEFINE_HANDLER(CMSG_REQUEST_TREASURE_PUNCH_LIST_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
|
DEFINE_HANDLER(CMSG_REQUEST_TREASURE_PUNCH_LIST_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestTreasurePunchListItems);
|
||||||
DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_EXIT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestVehicleExit);
|
DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_EXIT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestVehicleExit);
|
||||||
DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_NEXT_SEAT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestVehicleNextSeat);
|
DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_NEXT_SEAT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestVehicleNextSeat);
|
||||||
DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_PREV_SEAT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestVehiclePrevSeat);
|
DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_PREV_SEAT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestVehiclePrevSeat);
|
||||||
@@ -2506,7 +2506,7 @@ void OpcodeTable::InitializeServerOpcodes()
|
|||||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SITUATIONS_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SITUATIONS_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SLOTS_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSMOG_OUTFIT_SLOTS_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TREASURE_PICKER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TREASURE_PICKER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TREASURE_PUNCH_LIST_ITEMS_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TREASURE_PUNCH_LIST_ITEMS_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_MOVIE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_MOVIE, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TURN_IN_PETITION_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TURN_IN_PETITION_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ namespace WorldPackets
|
|||||||
class ConfirmPurchaseResponse;
|
class ConfirmPurchaseResponse;
|
||||||
class DistributionAssignToTarget;
|
class DistributionAssignToTarget;
|
||||||
class CharacterUpgradeStart;
|
class CharacterUpgradeStart;
|
||||||
|
class GetClientCheckoutLicenses;
|
||||||
|
class RefreshEntitlementsOnOrderComplete;
|
||||||
|
class BulkPurchase;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace AreaTrigger
|
namespace AreaTrigger
|
||||||
@@ -243,6 +246,7 @@ namespace WorldPackets
|
|||||||
class BattlePetModifyName;
|
class BattlePetModifyName;
|
||||||
class QueryBattlePetName;
|
class QueryBattlePetName;
|
||||||
class BattlePetDeletePet;
|
class BattlePetDeletePet;
|
||||||
|
class BattlePetDeletePetCheat;
|
||||||
class BattlePetSetFlags;
|
class BattlePetSetFlags;
|
||||||
class BattlePetClearFanfare;
|
class BattlePetClearFanfare;
|
||||||
class BattlePetSummon;
|
class BattlePetSummon;
|
||||||
@@ -1087,6 +1091,7 @@ namespace WorldPackets
|
|||||||
class QuestSessionRequestStart;
|
class QuestSessionRequestStart;
|
||||||
class QuestSessionRequestStop;
|
class QuestSessionRequestStop;
|
||||||
class QuestSessionBeginResponse;
|
class QuestSessionBeginResponse;
|
||||||
|
class RequestTreasurePunchListItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace RaF
|
namespace RaF
|
||||||
@@ -2314,6 +2319,7 @@ public:
|
|||||||
void HandleQuestSessionRequestStart(WorldPackets::Quest::QuestSessionRequestStart& packet);
|
void HandleQuestSessionRequestStart(WorldPackets::Quest::QuestSessionRequestStart& packet);
|
||||||
void HandleQuestSessionRequestStop(WorldPackets::Quest::QuestSessionRequestStop& packet);
|
void HandleQuestSessionRequestStop(WorldPackets::Quest::QuestSessionRequestStop& packet);
|
||||||
void HandleQuestSessionBeginResponse(WorldPackets::Quest::QuestSessionBeginResponse& packet);
|
void HandleQuestSessionBeginResponse(WorldPackets::Quest::QuestSessionBeginResponse& packet);
|
||||||
|
void HandleRequestTreasurePunchListItems(WorldPackets::Quest::RequestTreasurePunchListItems& packet);
|
||||||
|
|
||||||
void HandleChatMessageOpcode(WorldPackets::Chat::ChatMessage& chatMessage);
|
void HandleChatMessageOpcode(WorldPackets::Chat::ChatMessage& chatMessage);
|
||||||
void HandleChatMessageWhisperOpcode(WorldPackets::Chat::ChatMessageWhisper& chatMessageWhisper);
|
void HandleChatMessageWhisperOpcode(WorldPackets::Chat::ChatMessageWhisper& chatMessageWhisper);
|
||||||
@@ -2431,6 +2437,9 @@ public:
|
|||||||
void HandleCharacterUpgradeStart(WorldPackets::BattlePay::CharacterUpgradeStart& upgradeStart);
|
void HandleCharacterUpgradeStart(WorldPackets::BattlePay::CharacterUpgradeStart& upgradeStart);
|
||||||
// Second half of the boost, run once the target's current level/class/race/inventory have been
|
// Second half of the boost, run once the target's current level/class/race/inventory have been
|
||||||
// read. Claims the entitlement, writes the boost, then answers COMPLETE (or ABORTED).
|
// read. Claims the entitlement, writes the boost, then answers COMPLETE (or ABORTED).
|
||||||
|
void HandleGetClientCheckoutLicenses(WorldPackets::BattlePay::GetClientCheckoutLicenses& packet);
|
||||||
|
void HandleRefreshEntitlementsOnOrderComplete(WorldPackets::BattlePay::RefreshEntitlementsOnOrderComplete& packet);
|
||||||
|
void HandleBattlePayBulkPurchase(WorldPackets::BattlePay::BulkPurchase& packet);
|
||||||
void ApplyBattlePayCharacterBoost(CharacterDatabaseQueryHolder const& queryResult, ObjectGuid target,
|
void ApplyBattlePayCharacterBoost(CharacterDatabaseQueryHolder const& queryResult, ObjectGuid target,
|
||||||
uint32 specializationId, uint64 distributionId, uint64 purchaseId, uint32 productId);
|
uint32 specializationId, uint64 distributionId, uint64 purchaseId, uint32 productId);
|
||||||
// True once this account holds at least one unapplied character-boost entitlement. Drives the
|
// True once this account holds at least one unapplied character-boost entitlement. Drives the
|
||||||
@@ -2755,6 +2764,7 @@ public:
|
|||||||
void HandleBattlePetModifyName(WorldPackets::BattlePet::BattlePetModifyName& battlePetModifyName);
|
void HandleBattlePetModifyName(WorldPackets::BattlePet::BattlePetModifyName& battlePetModifyName);
|
||||||
void HandleQueryBattlePetName(WorldPackets::BattlePet::QueryBattlePetName& queryBattlePetName);
|
void HandleQueryBattlePetName(WorldPackets::BattlePet::QueryBattlePetName& queryBattlePetName);
|
||||||
void HandleBattlePetDeletePet(WorldPackets::BattlePet::BattlePetDeletePet& battlePetDeletePet);
|
void HandleBattlePetDeletePet(WorldPackets::BattlePet::BattlePetDeletePet& battlePetDeletePet);
|
||||||
|
void HandleBattlePetDeletePetCheat(WorldPackets::BattlePet::BattlePetDeletePetCheat& battlePetDeletePetCheat);
|
||||||
void HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSetFlags& battlePetSetFlags);
|
void HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSetFlags& battlePetSetFlags);
|
||||||
void HandleBattlePetClearFanfare(WorldPackets::BattlePet::BattlePetClearFanfare& battlePetClearFanfare);
|
void HandleBattlePetClearFanfare(WorldPackets::BattlePet::BattlePetClearFanfare& battlePetClearFanfare);
|
||||||
void HandleBattlePetSummon(WorldPackets::BattlePet::BattlePetSummon& battlePetSummon);
|
void HandleBattlePetSummon(WorldPackets::BattlePet::BattlePetSummon& battlePetSummon);
|
||||||
|
|||||||
@@ -861,6 +861,7 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
{ .Name = "Death.SicknessLevel"sv, .DefaultValue = 11, .Index = CONFIG_DEATH_SICKNESS_LEVEL },
|
{ .Name = "Death.SicknessLevel"sv, .DefaultValue = 11, .Index = CONFIG_DEATH_SICKNESS_LEVEL },
|
||||||
{ .Name = "Battleground.ReportAFK"sv, .DefaultValue = 3, .Index = CONFIG_BATTLEGROUND_REPORT_AFK, .Min = 1, .Max = 9 },
|
{ .Name = "Battleground.ReportAFK"sv, .DefaultValue = 3, .Index = CONFIG_BATTLEGROUND_REPORT_AFK, .Min = 1, .Max = 9 },
|
||||||
{ .Name = "Battleground.InvitationType"sv, .DefaultValue = 0, .Index = CONFIG_BATTLEGROUND_INVITATION_TYPE },
|
{ .Name = "Battleground.InvitationType"sv, .DefaultValue = 0, .Index = CONFIG_BATTLEGROUND_INVITATION_TYPE },
|
||||||
|
{ .Name = "BattlegroundBlitz.HealersPerTeam"sv, .DefaultValue = 2, .Index = CONFIG_BATTLEGROUND_BLITZ_HEALERS_PER_TEAM, .Min = 0, .Max = 8 },
|
||||||
{ .Name = "Battleground.PrematureFinishTimer"sv, .DefaultValue = 5 * MINUTE * IN_MILLISECONDS, .Index = CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER },
|
{ .Name = "Battleground.PrematureFinishTimer"sv, .DefaultValue = 5 * MINUTE * IN_MILLISECONDS, .Index = CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER },
|
||||||
{ .Name = "Battleground.PremadeGroupWaitForMatch"sv, .DefaultValue = 30 * MINUTE * IN_MILLISECONDS, .Index = CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH },
|
{ .Name = "Battleground.PremadeGroupWaitForMatch"sv, .DefaultValue = 30 * MINUTE * IN_MILLISECONDS, .Index = CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH },
|
||||||
{ .Name = "Arena.MaxRatingDifference"sv, .DefaultValue = 150, .Index = CONFIG_ARENA_MAX_RATING_DIFFERENCE },
|
{ .Name = "Arena.MaxRatingDifference"sv, .DefaultValue = 150, .Index = CONFIG_ARENA_MAX_RATING_DIFFERENCE },
|
||||||
|
|||||||
@@ -340,6 +340,7 @@ enum WorldIntConfigs : uint32
|
|||||||
CONFIG_DEATH_SICKNESS_LEVEL,
|
CONFIG_DEATH_SICKNESS_LEVEL,
|
||||||
CONFIG_DISABLE_BREATHING,
|
CONFIG_DISABLE_BREATHING,
|
||||||
CONFIG_BATTLEGROUND_INVITATION_TYPE,
|
CONFIG_BATTLEGROUND_INVITATION_TYPE,
|
||||||
|
CONFIG_BATTLEGROUND_BLITZ_HEALERS_PER_TEAM,
|
||||||
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
|
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
|
||||||
CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH,
|
CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH,
|
||||||
CONFIG_BATTLEGROUND_REPORT_AFK,
|
CONFIG_BATTLEGROUND_REPORT_AFK,
|
||||||
|
|||||||
Reference in New Issue
Block a user