Add Achievements list window (Y key toggle) with search filter

This commit is contained in:
Kelsi 2026-03-12 02:09:35 -07:00
parent 7a1f330655
commit f4754797bc
4 changed files with 79 additions and 0 deletions

View file

@ -354,6 +354,11 @@ private:
// Dungeon Finder state
bool showDungeonFinder_ = false;
// Achievements window
bool showAchievementWindow_ = false;
char achievementSearchBuf_[128] = {};
void renderAchievementWindow(game::GameHandler& gameHandler);
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
uint32_t lfgSelectedDungeon_ = 861; // default: random dungeon (entry 861 = Random Dungeon WotLK)

View file

@ -30,6 +30,7 @@ public:
TOGGLE_NAMEPLATES,
TOGGLE_RAID_FRAMES,
TOGGLE_QUEST_LOG,
TOGGLE_ACHIEVEMENTS,
ACTION_COUNT
};

View file

@ -497,6 +497,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
renderAuctionHouseWindow(gameHandler);
renderDungeonFinderWindow(gameHandler);
renderInstanceLockouts(gameHandler);
renderAchievementWindow(gameHandler);
// renderQuestMarkers(gameHandler); // Disabled - using 3D billboard markers now
if (showMinimap_) {
renderMinimapMarkers(gameHandler);
@ -1762,6 +1763,10 @@ void GameScreen::processTargetInput(game::GameHandler& gameHandler) {
questLogScreen.toggle();
}
if (KeybindingManager::getInstance().isActionPressed(KeybindingManager::Action::TOGGLE_ACHIEVEMENTS)) {
showAchievementWindow_ = !showAchievementWindow_;
}
// Action bar keys (1-9, 0, -, =)
static const SDL_Scancode actionBarKeys[] = {
SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_4,
@ -14326,4 +14331,68 @@ void GameScreen::renderBattlegroundScore(game::GameHandler& gameHandler) {
ImGui::PopStyleVar(2);
}
// ─── Achievement Window ───────────────────────────────────────────────────────
void GameScreen::renderAchievementWindow(game::GameHandler& gameHandler) {
if (!showAchievementWindow_) return;
ImGui::SetNextWindowSize(ImVec2(420, 480), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(200, 150), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Achievements", &showAchievementWindow_)) {
ImGui::End();
return;
}
const auto& earned = gameHandler.getEarnedAchievements();
ImGui::Text("Earned: %u", static_cast<unsigned>(earned.size()));
ImGui::SameLine();
ImGui::SetNextItemWidth(180.0f);
ImGui::InputText("##achsearch", achievementSearchBuf_, sizeof(achievementSearchBuf_));
ImGui::SameLine();
if (ImGui::Button("Clear")) achievementSearchBuf_[0] = '\0';
ImGui::Separator();
if (earned.empty()) {
ImGui::TextDisabled("No achievements earned yet.");
ImGui::End();
return;
}
ImGui::BeginChild("##achlist", ImVec2(0, 0), false);
std::string filter(achievementSearchBuf_);
// lower-case filter for case-insensitive matching
for (char& c : filter) c = static_cast<char>(tolower(static_cast<unsigned char>(c)));
// Collect and sort ids for stable display
std::vector<uint32_t> ids(earned.begin(), earned.end());
std::sort(ids.begin(), ids.end());
for (uint32_t id : ids) {
const std::string& name = gameHandler.getAchievementName(id);
const std::string& display = name.empty() ? std::to_string(id) : name;
if (!filter.empty()) {
std::string lower = display;
for (char& c : lower) c = static_cast<char>(tolower(static_cast<unsigned char>(c)));
if (lower.find(filter) == std::string::npos) continue;
}
ImGui::PushID(static_cast<int>(id));
ImGui::TextColored(ImVec4(1.0f, 0.85f, 0.0f, 1.0f), "[Achievement]");
ImGui::SameLine();
ImGui::TextUnformatted(display.c_str());
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("ID: %u", id);
if (!name.empty()) ImGui::TextDisabled("%s", name.c_str());
ImGui::EndTooltip();
}
ImGui::PopID();
}
ImGui::EndChild();
ImGui::End();
}
}} // namespace wowee::ui

View file

@ -31,6 +31,7 @@ void KeybindingManager::initializeDefaults() {
bindings_[static_cast<int>(Action::TOGGLE_NAMEPLATES)] = ImGuiKey_V;
bindings_[static_cast<int>(Action::TOGGLE_RAID_FRAMES)] = ImGuiKey_F; // Reassigned from R (now camera reset)
bindings_[static_cast<int>(Action::TOGGLE_QUEST_LOG)] = ImGuiKey_Q;
bindings_[static_cast<int>(Action::TOGGLE_ACHIEVEMENTS)] = ImGuiKey_Y; // WoW standard key (Shift+Y in retail)
}
bool KeybindingManager::isActionPressed(Action action, bool repeat) {
@ -71,6 +72,7 @@ const char* KeybindingManager::getActionName(Action action) {
case Action::TOGGLE_NAMEPLATES: return "Nameplates";
case Action::TOGGLE_RAID_FRAMES: return "Raid Frames";
case Action::TOGGLE_QUEST_LOG: return "Quest Log";
case Action::TOGGLE_ACHIEVEMENTS: return "Achievements";
case Action::ACTION_COUNT: break;
}
return "Unknown";
@ -135,6 +137,7 @@ void KeybindingManager::loadFromConfigFile(const std::string& filePath) {
else if (action == "toggle_nameplates") actionIdx = static_cast<int>(Action::TOGGLE_NAMEPLATES);
else if (action == "toggle_raid_frames") actionIdx = static_cast<int>(Action::TOGGLE_RAID_FRAMES);
else if (action == "toggle_quest_log") actionIdx = static_cast<int>(Action::TOGGLE_QUEST_LOG);
else if (action == "toggle_achievements") actionIdx = static_cast<int>(Action::TOGGLE_ACHIEVEMENTS);
if (actionIdx < 0) continue;
@ -226,6 +229,7 @@ void KeybindingManager::saveToConfigFile(const std::string& filePath) const {
{Action::TOGGLE_NAMEPLATES, "toggle_nameplates"},
{Action::TOGGLE_RAID_FRAMES, "toggle_raid_frames"},
{Action::TOGGLE_QUEST_LOG, "toggle_quest_log"},
{Action::TOGGLE_ACHIEVEMENTS, "toggle_achievements"},
};
for (const auto& [action, nameStr] : actionMap) {