mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: add Skills/Professions window (K key) with per-category progress bars
Implements renderSkillsWindow() showing all player skills grouped by DBC category (Professions, Secondary Skills, Class Skills, Weapon Skills, Armor, Languages) with value/max progress bars and a bonus breakdown tooltip. Hooked up to the TOGGLE_SKILLS keybinding (K by default).
This commit is contained in:
parent
d44d462686
commit
48cb7df4b4
2 changed files with 118 additions and 0 deletions
|
|
@ -718,6 +718,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
renderWhoWindow(gameHandler);
|
||||
renderCombatLog(gameHandler);
|
||||
renderAchievementWindow(gameHandler);
|
||||
renderSkillsWindow(gameHandler);
|
||||
renderTitlesWindow(gameHandler);
|
||||
renderEquipSetWindow(gameHandler);
|
||||
renderGmTicketWindow(gameHandler);
|
||||
|
|
@ -2766,6 +2767,9 @@ void GameScreen::processTargetInput(game::GameHandler& gameHandler) {
|
|||
if (KeybindingManager::getInstance().isActionPressed(KeybindingManager::Action::TOGGLE_ACHIEVEMENTS)) {
|
||||
showAchievementWindow_ = !showAchievementWindow_;
|
||||
}
|
||||
if (KeybindingManager::getInstance().isActionPressed(KeybindingManager::Action::TOGGLE_SKILLS)) {
|
||||
showSkillsWindow_ = !showSkillsWindow_;
|
||||
}
|
||||
|
||||
// Toggle Titles window with H (hero/title screen — no conflicting keybinding)
|
||||
if (input.isKeyJustPressed(SDL_SCANCODE_H) && !ImGui::GetIO().WantCaptureKeyboard) {
|
||||
|
|
@ -22702,4 +22706,114 @@ void GameScreen::renderEquipSetWindow(game::GameHandler& gameHandler) {
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
void GameScreen::renderSkillsWindow(game::GameHandler& gameHandler) {
|
||||
if (!showSkillsWindow_) return;
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(380, 480), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowPos(ImVec2(220, 130), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (!ImGui::Begin("Skills & Professions", &showSkillsWindow_)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& skills = gameHandler.getPlayerSkills();
|
||||
if (skills.empty()) {
|
||||
ImGui::TextDisabled("No skill data received yet.");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// Organise skills by category
|
||||
// WoW SkillLine.dbc categories: 6=Weapon, 7=Class, 8=Armor, 9=Secondary, 11=Professions, others=Misc
|
||||
struct SkillEntry {
|
||||
uint32_t skillId;
|
||||
const game::PlayerSkill* skill;
|
||||
};
|
||||
std::map<uint32_t, std::vector<SkillEntry>> byCategory;
|
||||
for (const auto& [id, sk] : skills) {
|
||||
uint32_t cat = gameHandler.getSkillCategory(id);
|
||||
byCategory[cat].push_back({id, &sk});
|
||||
}
|
||||
|
||||
static const struct { uint32_t cat; const char* label; } kCatOrder[] = {
|
||||
{11, "Professions"},
|
||||
{ 9, "Secondary Skills"},
|
||||
{ 7, "Class Skills"},
|
||||
{ 6, "Weapon Skills"},
|
||||
{ 8, "Armor"},
|
||||
{ 5, "Languages"},
|
||||
{ 0, "Other"},
|
||||
};
|
||||
|
||||
// Collect handled categories to fall back to "Other" for unknowns
|
||||
static const uint32_t kKnownCats[] = {11, 9, 7, 6, 8, 5};
|
||||
|
||||
// Redirect unknown categories into bucket 0
|
||||
for (auto& [cat, vec] : byCategory) {
|
||||
bool known = false;
|
||||
for (uint32_t kc : kKnownCats) if (cat == kc) { known = true; break; }
|
||||
if (!known && cat != 0) {
|
||||
auto& other = byCategory[0];
|
||||
other.insert(other.end(), vec.begin(), vec.end());
|
||||
vec.clear();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::BeginChild("##skillscroll", ImVec2(0, 0), false);
|
||||
|
||||
for (const auto& [cat, label] : kCatOrder) {
|
||||
auto it = byCategory.find(cat);
|
||||
if (it == byCategory.end() || it->second.empty()) continue;
|
||||
|
||||
auto& entries = it->second;
|
||||
// Sort alphabetically within each category
|
||||
std::sort(entries.begin(), entries.end(), [&](const SkillEntry& a, const SkillEntry& b) {
|
||||
return gameHandler.getSkillName(a.skillId) < gameHandler.getSkillName(b.skillId);
|
||||
});
|
||||
|
||||
if (ImGui::CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
for (const auto& e : entries) {
|
||||
const std::string& name = gameHandler.getSkillName(e.skillId);
|
||||
const char* displayName = name.empty() ? "Unknown" : name.c_str();
|
||||
uint16_t val = e.skill->effectiveValue();
|
||||
uint16_t maxVal = e.skill->maxValue;
|
||||
|
||||
ImGui::PushID(static_cast<int>(e.skillId));
|
||||
|
||||
// Name column
|
||||
ImGui::TextUnformatted(displayName);
|
||||
ImGui::SameLine(170.0f);
|
||||
|
||||
// Progress bar
|
||||
float fraction = (maxVal > 0) ? static_cast<float>(val) / static_cast<float>(maxVal) : 0.0f;
|
||||
char overlay[32];
|
||||
snprintf(overlay, sizeof(overlay), "%u / %u", val, maxVal);
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.20f, 0.55f, 0.20f, 1.0f));
|
||||
ImGui::ProgressBar(fraction, ImVec2(160.0f, 14.0f), overlay);
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s", displayName);
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Base: %u", e.skill->value);
|
||||
if (e.skill->bonusPerm > 0)
|
||||
ImGui::Text("Permanent bonus: +%u", e.skill->bonusPerm);
|
||||
if (e.skill->bonusTemp > 0)
|
||||
ImGui::Text("Temporary bonus: +%u", e.skill->bonusTemp);
|
||||
ImGui::Text("Max: %u", maxVal);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::Spacing();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
}} // namespace wowee::ui
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue