feat: show live per-player responses in ready check popup

Track each player's ready/not-ready response as MSG_RAID_READY_CHECK_CONFIRM
packets arrive. Display a color-coded table (green=Ready, red=Not Ready) in
the ready check popup so the raid leader can see who has responded in real
time. Results clear when a new check starts or finishes.
This commit is contained in:
Kelsi 2026-03-12 09:07:37 -07:00
parent 09d4a6ab41
commit d8d59dcdc8
3 changed files with 38 additions and 0 deletions

View file

@ -458,11 +458,16 @@ public:
uint64_t getPetitionNpcGuid() const { return petitionNpcGuid_; }
// Ready check
struct ReadyCheckResult {
std::string name;
bool ready = false;
};
void initiateReadyCheck();
void respondToReadyCheck(bool ready);
bool hasPendingReadyCheck() const { return pendingReadyCheck_; }
void dismissReadyCheck() { pendingReadyCheck_ = false; }
const std::string& getReadyCheckInitiator() const { return readyCheckInitiator_; }
const std::vector<ReadyCheckResult>& getReadyCheckResults() const { return readyCheckResults_; }
// Duel
void forfeitDuel();
@ -2258,6 +2263,7 @@ private:
uint32_t readyCheckReadyCount_ = 0;
uint32_t readyCheckNotReadyCount_ = 0;
std::string readyCheckInitiator_;
std::vector<ReadyCheckResult> readyCheckResults_; // per-player status live during check
// Faction standings (factionId → absolute standing value)
std::unordered_map<uint32_t, int32_t> factionStandings_;

View file

@ -3149,6 +3149,7 @@ void GameHandler::handlePacket(network::Packet& packet) {
readyCheckReadyCount_ = 0;
readyCheckNotReadyCount_ = 0;
readyCheckInitiator_.clear();
readyCheckResults_.clear();
if (packet.getSize() - packet.getReadPos() >= 8) {
uint64_t initiatorGuid = packet.readUInt64();
auto entity = entityManager.getEntity(initiatorGuid);
@ -3182,7 +3183,14 @@ void GameHandler::handlePacket(network::Packet& packet) {
auto ent = entityManager.getEntity(respGuid);
if (ent) rname = std::static_pointer_cast<game::Unit>(ent)->getName();
}
// Track per-player result for live popup display
if (!rname.empty()) {
bool found = false;
for (auto& r : readyCheckResults_) {
if (r.name == rname) { r.ready = (isReady != 0); found = true; break; }
}
if (!found) readyCheckResults_.push_back({ rname, isReady != 0 });
char rbuf[128];
std::snprintf(rbuf, sizeof(rbuf), "%s is %s.", rname.c_str(), isReady ? "Ready" : "Not Ready");
addSystemChatMessage(rbuf);
@ -3198,6 +3206,7 @@ void GameHandler::handlePacket(network::Packet& packet) {
pendingReadyCheck_ = false;
readyCheckReadyCount_ = 0;
readyCheckNotReadyCount_ = 0;
readyCheckResults_.clear();
break;
}
case Opcode::SMSG_RAID_INSTANCE_INFO:

View file

@ -8866,6 +8866,29 @@ void GameScreen::renderReadyCheckPopup(game::GameHandler& gameHandler) {
gameHandler.respondToReadyCheck(false);
gameHandler.dismissReadyCheck();
}
// Live player responses
const auto& results = gameHandler.getReadyCheckResults();
if (!results.empty()) {
ImGui::Separator();
if (ImGui::BeginTable("##rcresults", 2,
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
ImGui::TableSetupColumn("Player", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthFixed, 72.0f);
for (const auto& r : results) {
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::TextUnformatted(r.name.c_str());
ImGui::TableSetColumnIndex(1);
if (r.ready) {
ImGui::TextColored(ImVec4(0.2f, 0.9f, 0.2f, 1.0f), "Ready");
} else {
ImGui::TextColored(ImVec4(0.9f, 0.3f, 0.3f, 1.0f), "Not Ready");
}
}
ImGui::EndTable();
}
}
}
ImGui::End();
}