mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 00:03:50 +00:00
Implement Dungeon Finder UI window with role/dungeon selection
- Add renderDungeonFinderWindow() with status display (not queued / role check / queued+wait time / proposal / in dungeon / finished) - Role checkboxes (Tank/Healer/DPS) and dungeon combo (25 entries covering Vanilla, TBC, and WotLK including Random/Heroic) - Accept/Decline buttons during Proposal state, Teleport button while InDungeon, Leave Queue button while Queued/RoleCheck - Store lfgProposalId_ on GameHandler so UI can pass it to lfgAcceptProposal(); expose getLfgProposalId() and getLfgTimeInQueueMs() getters - Toggle window with I key (when chat input is not active)
This commit is contained in:
parent
63c6039dbb
commit
200a00d4f5
4 changed files with 212 additions and 6 deletions
|
|
@ -738,7 +738,9 @@ public:
|
||||||
bool isLfgQueued() const { return lfgState_ == LfgState::Queued; }
|
bool isLfgQueued() const { return lfgState_ == LfgState::Queued; }
|
||||||
bool isLfgInDungeon() const { return lfgState_ == LfgState::InDungeon; }
|
bool isLfgInDungeon() const { return lfgState_ == LfgState::InDungeon; }
|
||||||
uint32_t getLfgDungeonId() const { return lfgDungeonId_; }
|
uint32_t getLfgDungeonId() const { return lfgDungeonId_; }
|
||||||
|
uint32_t getLfgProposalId() const { return lfgProposalId_; }
|
||||||
int32_t getLfgAvgWaitSec() const { return lfgAvgWaitSec_; }
|
int32_t getLfgAvgWaitSec() const { return lfgAvgWaitSec_; }
|
||||||
|
uint32_t getLfgTimeInQueueMs() const { return lfgTimeInQueueMs_; }
|
||||||
|
|
||||||
// ---- Phase 5: Loot ----
|
// ---- Phase 5: Loot ----
|
||||||
void lootTarget(uint64_t guid);
|
void lootTarget(uint64_t guid);
|
||||||
|
|
@ -1585,6 +1587,7 @@ private:
|
||||||
// LFG / Dungeon Finder state
|
// LFG / Dungeon Finder state
|
||||||
LfgState lfgState_ = LfgState::None;
|
LfgState lfgState_ = LfgState::None;
|
||||||
uint32_t lfgDungeonId_ = 0; // current dungeon entry
|
uint32_t lfgDungeonId_ = 0; // current dungeon entry
|
||||||
|
uint32_t lfgProposalId_ = 0; // pending proposal id (0 = none)
|
||||||
int32_t lfgAvgWaitSec_ = -1; // estimated wait, -1=unknown
|
int32_t lfgAvgWaitSec_ = -1; // estimated wait, -1=unknown
|
||||||
uint32_t lfgTimeInQueueMs_= 0; // ms already in queue
|
uint32_t lfgTimeInQueueMs_= 0; // ms already in queue
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ private:
|
||||||
void renderBankWindow(game::GameHandler& gameHandler);
|
void renderBankWindow(game::GameHandler& gameHandler);
|
||||||
void renderGuildBankWindow(game::GameHandler& gameHandler);
|
void renderGuildBankWindow(game::GameHandler& gameHandler);
|
||||||
void renderAuctionHouseWindow(game::GameHandler& gameHandler);
|
void renderAuctionHouseWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderDungeonFinderWindow(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inventory screen
|
* Inventory screen
|
||||||
|
|
@ -259,6 +260,11 @@ private:
|
||||||
int bagBarPickedSlot_ = -1; // Visual drag in progress (-1 = none)
|
int bagBarPickedSlot_ = -1; // Visual drag in progress (-1 = none)
|
||||||
int bagBarDragSource_ = -1; // Mouse pressed on this slot, waiting for drag or click (-1 = none)
|
int bagBarDragSource_ = -1; // Mouse pressed on this slot, waiting for drag or click (-1 = none)
|
||||||
|
|
||||||
|
// Dungeon Finder state
|
||||||
|
bool showDungeonFinder_ = false;
|
||||||
|
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
|
||||||
|
uint32_t lfgSelectedDungeon_ = 861; // default: random dungeon (entry 861 = Random Dungeon WotLK)
|
||||||
|
|
||||||
// Chat settings
|
// Chat settings
|
||||||
bool chatShowTimestamps_ = false;
|
bool chatShowTimestamps_ = false;
|
||||||
int chatFontSize_ = 1; // 0=small, 1=medium, 2=large
|
int chatFontSize_ = 1; // 0=small, 1=medium, 2=large
|
||||||
|
|
|
||||||
|
|
@ -9074,14 +9074,17 @@ void GameHandler::handleLfgProposalUpdate(network::Packet& packet) {
|
||||||
/*bool canOverride =*/ packet.readUInt8();
|
/*bool canOverride =*/ packet.readUInt8();
|
||||||
|
|
||||||
lfgDungeonId_ = dungeonId;
|
lfgDungeonId_ = dungeonId;
|
||||||
|
lfgProposalId_ = proposalId;
|
||||||
|
|
||||||
switch (proposalState) {
|
switch (proposalState) {
|
||||||
case 0:
|
case 0:
|
||||||
lfgState_ = LfgState::Queued;
|
lfgState_ = LfgState::Queued;
|
||||||
|
lfgProposalId_ = 0;
|
||||||
addSystemChatMessage("Dungeon Finder: Group proposal failed.");
|
addSystemChatMessage("Dungeon Finder: Group proposal failed.");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
lfgState_ = LfgState::InDungeon;
|
lfgState_ = LfgState::InDungeon;
|
||||||
|
lfgProposalId_ = 0;
|
||||||
addSystemChatMessage("Dungeon Finder: Group found! Entering dungeon...");
|
addSystemChatMessage("Dungeon Finder: Group found! Entering dungeon...");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
|
@ -9094,7 +9097,6 @@ void GameHandler::handleLfgProposalUpdate(network::Packet& packet) {
|
||||||
|
|
||||||
LOG_INFO("SMSG_LFG_PROPOSAL_UPDATE: dungeonId=", dungeonId,
|
LOG_INFO("SMSG_LFG_PROPOSAL_UPDATE: dungeonId=", dungeonId,
|
||||||
" proposalId=", proposalId, " state=", proposalState);
|
" proposalId=", proposalId, " state=", proposalState);
|
||||||
(void)proposalId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameHandler::handleLfgRoleCheckUpdate(network::Packet& packet) {
|
void GameHandler::handleLfgRoleCheckUpdate(network::Packet& packet) {
|
||||||
|
|
|
||||||
|
|
@ -412,6 +412,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
||||||
renderBankWindow(gameHandler);
|
renderBankWindow(gameHandler);
|
||||||
renderGuildBankWindow(gameHandler);
|
renderGuildBankWindow(gameHandler);
|
||||||
renderAuctionHouseWindow(gameHandler);
|
renderAuctionHouseWindow(gameHandler);
|
||||||
|
renderDungeonFinderWindow(gameHandler);
|
||||||
// renderQuestMarkers(gameHandler); // Disabled - using 3D billboard markers now
|
// renderQuestMarkers(gameHandler); // Disabled - using 3D billboard markers now
|
||||||
renderMinimapMarkers(gameHandler);
|
renderMinimapMarkers(gameHandler);
|
||||||
renderDeathScreen(gameHandler);
|
renderDeathScreen(gameHandler);
|
||||||
|
|
@ -8877,4 +8878,198 @@ void GameScreen::renderDingEffect() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Dungeon Finder window (toggle with hotkey or bag-bar button)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
void GameScreen::renderDungeonFinderWindow(game::GameHandler& gameHandler) {
|
||||||
|
// Toggle on I key when not typing
|
||||||
|
if (!chatInputActive && ImGui::IsKeyPressed(ImGuiKey_I, false)) {
|
||||||
|
showDungeonFinder_ = !showDungeonFinder_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!showDungeonFinder_) return;
|
||||||
|
|
||||||
|
auto* window = core::Application::getInstance().getWindow();
|
||||||
|
float screenW = window ? static_cast<float>(window->getWidth()) : 1280.0f;
|
||||||
|
float screenH = window ? static_cast<float>(window->getHeight()) : 720.0f;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(screenW * 0.5f - 175.0f, screenH * 0.2f),
|
||||||
|
ImGuiCond_FirstUseEver);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(350, 0), ImGuiCond_Always);
|
||||||
|
|
||||||
|
bool open = true;
|
||||||
|
ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize;
|
||||||
|
if (!ImGui::Begin("Dungeon Finder", &open, flags)) {
|
||||||
|
ImGui::End();
|
||||||
|
if (!open) showDungeonFinder_ = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!open) {
|
||||||
|
ImGui::End();
|
||||||
|
showDungeonFinder_ = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using LfgState = game::GameHandler::LfgState;
|
||||||
|
LfgState state = gameHandler.getLfgState();
|
||||||
|
|
||||||
|
// ---- Status banner ----
|
||||||
|
switch (state) {
|
||||||
|
case LfgState::None:
|
||||||
|
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "Status: Not queued");
|
||||||
|
break;
|
||||||
|
case LfgState::RoleCheck:
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Status: Role check in progress...");
|
||||||
|
break;
|
||||||
|
case LfgState::Queued: {
|
||||||
|
int32_t avgSec = gameHandler.getLfgAvgWaitSec();
|
||||||
|
uint32_t qMs = gameHandler.getLfgTimeInQueueMs();
|
||||||
|
int qMin = static_cast<int>(qMs / 60000);
|
||||||
|
int qSec = static_cast<int>((qMs % 60000) / 1000);
|
||||||
|
ImGui::TextColored(ImVec4(0.3f, 0.9f, 0.3f, 1.0f), "Status: In queue (%d:%02d)", qMin, qSec);
|
||||||
|
if (avgSec >= 0) {
|
||||||
|
int aMin = avgSec / 60;
|
||||||
|
int aSec = avgSec % 60;
|
||||||
|
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.8f, 1.0f),
|
||||||
|
"Avg wait: %d:%02d", aMin, aSec);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LfgState::Proposal:
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.1f, 1.0f), "Status: Group found!");
|
||||||
|
break;
|
||||||
|
case LfgState::Boot:
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "Status: Vote kick in progress");
|
||||||
|
break;
|
||||||
|
case LfgState::InDungeon:
|
||||||
|
ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f), "Status: In dungeon");
|
||||||
|
break;
|
||||||
|
case LfgState::FinishedDungeon:
|
||||||
|
ImGui::TextColored(ImVec4(0.6f, 1.0f, 0.6f, 1.0f), "Status: Dungeon complete");
|
||||||
|
break;
|
||||||
|
case LfgState::RaidBrowser:
|
||||||
|
ImGui::TextColored(ImVec4(0.8f, 0.6f, 1.0f, 1.0f), "Status: Raid browser");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// ---- Proposal accept/decline ----
|
||||||
|
if (state == LfgState::Proposal) {
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.9f, 0.3f, 1.0f),
|
||||||
|
"A group has been found for your dungeon!");
|
||||||
|
ImGui::Spacing();
|
||||||
|
if (ImGui::Button("Accept", ImVec2(120, 0))) {
|
||||||
|
gameHandler.lfgAcceptProposal(gameHandler.getLfgProposalId(), true);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Decline", ImVec2(120, 0))) {
|
||||||
|
gameHandler.lfgAcceptProposal(gameHandler.getLfgProposalId(), false);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Teleport button (in dungeon) ----
|
||||||
|
if (state == LfgState::InDungeon) {
|
||||||
|
if (ImGui::Button("Teleport to Dungeon", ImVec2(-1, 0))) {
|
||||||
|
gameHandler.lfgTeleport(true);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Role selection (only when not queued/in dungeon) ----
|
||||||
|
bool canConfigure = (state == LfgState::None || state == LfgState::FinishedDungeon);
|
||||||
|
|
||||||
|
if (canConfigure) {
|
||||||
|
ImGui::Text("Role:");
|
||||||
|
ImGui::SameLine();
|
||||||
|
bool isTank = (lfgRoles_ & 0x02) != 0;
|
||||||
|
bool isHealer = (lfgRoles_ & 0x04) != 0;
|
||||||
|
bool isDps = (lfgRoles_ & 0x08) != 0;
|
||||||
|
if (ImGui::Checkbox("Tank", &isTank)) lfgRoles_ = (lfgRoles_ & ~0x02) | (isTank ? 0x02 : 0);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Checkbox("Healer", &isHealer)) lfgRoles_ = (lfgRoles_ & ~0x04) | (isHealer ? 0x04 : 0);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Checkbox("DPS", &isDps)) lfgRoles_ = (lfgRoles_ & ~0x08) | (isDps ? 0x08 : 0);
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// ---- Dungeon selection ----
|
||||||
|
ImGui::Text("Dungeon:");
|
||||||
|
|
||||||
|
struct DungeonEntry { uint32_t id; const char* name; };
|
||||||
|
static const DungeonEntry kDungeons[] = {
|
||||||
|
{ 861, "Random Dungeon" },
|
||||||
|
{ 862, "Random Heroic" },
|
||||||
|
// Vanilla classics
|
||||||
|
{ 36, "Deadmines" },
|
||||||
|
{ 43, "Ragefire Chasm" },
|
||||||
|
{ 47, "Razorfen Kraul" },
|
||||||
|
{ 48, "Blackfathom Deeps" },
|
||||||
|
{ 52, "Uldaman" },
|
||||||
|
{ 57, "Dire Maul: East" },
|
||||||
|
{ 70, "Onyxia's Lair" },
|
||||||
|
// TBC heroics
|
||||||
|
{ 264, "The Blood Furnace" },
|
||||||
|
{ 269, "The Shattered Halls" },
|
||||||
|
// WotLK normals/heroics
|
||||||
|
{ 576, "The Nexus" },
|
||||||
|
{ 578, "The Oculus" },
|
||||||
|
{ 595, "The Culling of Stratholme" },
|
||||||
|
{ 599, "Halls of Stone" },
|
||||||
|
{ 600, "Drak'Tharon Keep" },
|
||||||
|
{ 601, "Azjol-Nerub" },
|
||||||
|
{ 604, "Gundrak" },
|
||||||
|
{ 608, "Violet Hold" },
|
||||||
|
{ 619, "Ahn'kahet: Old Kingdom" },
|
||||||
|
{ 623, "Halls of Lightning" },
|
||||||
|
{ 632, "The Forge of Souls" },
|
||||||
|
{ 650, "Trial of the Champion" },
|
||||||
|
{ 658, "Pit of Saron" },
|
||||||
|
{ 668, "Halls of Reflection" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find current index
|
||||||
|
int curIdx = 0;
|
||||||
|
for (int i = 0; i < (int)(sizeof(kDungeons)/sizeof(kDungeons[0])); ++i) {
|
||||||
|
if (kDungeons[i].id == lfgSelectedDungeon_) { curIdx = i; break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
if (ImGui::BeginCombo("##dungeon", kDungeons[curIdx].name)) {
|
||||||
|
for (int i = 0; i < (int)(sizeof(kDungeons)/sizeof(kDungeons[0])); ++i) {
|
||||||
|
bool selected = (kDungeons[i].id == lfgSelectedDungeon_);
|
||||||
|
if (ImGui::Selectable(kDungeons[i].name, selected))
|
||||||
|
lfgSelectedDungeon_ = kDungeons[i].id;
|
||||||
|
if (selected) ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// ---- Join button ----
|
||||||
|
bool rolesOk = (lfgRoles_ != 0);
|
||||||
|
if (!rolesOk) {
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
}
|
||||||
|
if (ImGui::Button("Join Dungeon Finder", ImVec2(-1, 0))) {
|
||||||
|
gameHandler.lfgJoin(lfgSelectedDungeon_, lfgRoles_);
|
||||||
|
}
|
||||||
|
if (!rolesOk) {
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "Select at least one role.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Leave button (when queued or role check) ----
|
||||||
|
if (state == LfgState::Queued || state == LfgState::RoleCheck) {
|
||||||
|
if (ImGui::Button("Leave Queue", ImVec2(-1, 0))) {
|
||||||
|
gameHandler.lfgLeave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace wowee::ui
|
}} // namespace wowee::ui
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue