Parse SMSG_ARENA_TEAM_STATS and display in character screen PvP tab

This commit is contained in:
Kelsi 2026-03-12 02:35:29 -07:00
parent 2bdd024f19
commit 92db25038c
3 changed files with 74 additions and 1 deletions

View file

@ -1070,6 +1070,18 @@ public:
uint32_t getLfgBootTimeLeft() const { return lfgBootTimeLeft_; }
uint32_t getLfgBootNeeded() const { return lfgBootNeeded_; }
// ---- Arena Team Stats ----
struct ArenaTeamStats {
uint32_t teamId = 0;
uint32_t rating = 0;
uint32_t weekGames = 0;
uint32_t weekWins = 0;
uint32_t seasonGames = 0;
uint32_t seasonWins = 0;
uint32_t rank = 0;
};
const std::vector<ArenaTeamStats>& getArenaTeamStats() const { return arenaTeamStats_; }
// ---- Phase 5: Loot ----
void lootTarget(uint64_t guid);
void lootItem(uint8_t slotIndex);
@ -1774,6 +1786,7 @@ private:
void handleArenaTeamQueryResponse(network::Packet& packet);
void handleArenaTeamInvite(network::Packet& packet);
void handleArenaTeamEvent(network::Packet& packet);
void handleArenaTeamStats(network::Packet& packet);
void handleArenaError(network::Packet& packet);
// ---- Bank handlers ----
@ -2127,6 +2140,9 @@ private:
// Instance / raid lockouts
std::vector<InstanceLockout> instanceLockouts_;
// Arena team stats (indexed by team slot, updated by SMSG_ARENA_TEAM_STATS)
std::vector<ArenaTeamStats> arenaTeamStats_;
// Instance encounter boss units (slots 0-4 from SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT)
std::array<uint64_t, kMaxEncounterSlots> encounterUnitGuids_ = {}; // 0 = empty slot

View file

@ -4924,7 +4924,7 @@ void GameHandler::handlePacket(network::Packet& packet) {
handleArenaTeamEvent(packet);
break;
case Opcode::SMSG_ARENA_TEAM_STATS:
LOG_INFO("Received SMSG_ARENA_TEAM_STATS");
handleArenaTeamStats(packet);
break;
case Opcode::SMSG_ARENA_ERROR:
handleArenaError(packet);
@ -13276,6 +13276,35 @@ void GameHandler::handleArenaTeamEvent(network::Packet& packet) {
LOG_INFO("Arena team event: ", eventName, " ", param1, " ", param2);
}
void GameHandler::handleArenaTeamStats(network::Packet& packet) {
// SMSG_ARENA_TEAM_STATS (WotLK 3.3.5a):
// uint32 teamId, uint32 rating, uint32 weekGames, uint32 weekWins,
// uint32 seasonGames, uint32 seasonWins, uint32 rank
if (packet.getSize() - packet.getReadPos() < 28) return;
ArenaTeamStats stats;
stats.teamId = packet.readUInt32();
stats.rating = packet.readUInt32();
stats.weekGames = packet.readUInt32();
stats.weekWins = packet.readUInt32();
stats.seasonGames = packet.readUInt32();
stats.seasonWins = packet.readUInt32();
stats.rank = packet.readUInt32();
// Update or insert for this team
for (auto& s : arenaTeamStats_) {
if (s.teamId == stats.teamId) {
s = stats;
LOG_INFO("SMSG_ARENA_TEAM_STATS: teamId=", stats.teamId,
" rating=", stats.rating, " rank=", stats.rank);
return;
}
}
arenaTeamStats_.push_back(stats);
LOG_INFO("SMSG_ARENA_TEAM_STATS: teamId=", stats.teamId,
" rating=", stats.rating, " rank=", stats.rank);
}
void GameHandler::handleArenaError(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 4) return;
uint32_t error = packet.readUInt32();

View file

@ -1270,6 +1270,34 @@ void InventoryScreen::renderCharacterScreen(game::GameHandler& gameHandler) {
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("PvP")) {
const auto& arenaStats = gameHandler.getArenaTeamStats();
if (arenaStats.empty()) {
ImGui::Spacing();
ImGui::TextDisabled("Not a member of any Arena team.");
} else {
for (const auto& team : arenaStats) {
ImGui::PushID(static_cast<int>(team.teamId));
char header[64];
snprintf(header, sizeof(header), "Team ID %u (Rating: %u)", team.teamId, team.rating);
if (ImGui::CollapsingHeader(header, ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Columns(2, "##arenacols", false);
ImGui::Text("Rating:"); ImGui::NextColumn();
ImGui::Text("%u", team.rating); ImGui::NextColumn();
ImGui::Text("Rank:"); ImGui::NextColumn();
ImGui::Text("#%u", team.rank); ImGui::NextColumn();
ImGui::Text("This week:"); ImGui::NextColumn();
ImGui::Text("%u / %u (W/G)", team.weekWins, team.weekGames); ImGui::NextColumn();
ImGui::Text("Season:"); ImGui::NextColumn();
ImGui::Text("%u / %u (W/G)", team.seasonWins, team.seasonGames); ImGui::NextColumn();
ImGui::Columns(1);
}
ImGui::PopID();
}
}
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}