mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: add Shaman totem frame with element-colored duration bars
- Renders below pet frame, visible only for Shaman (class 7) - Shows each active totem (Earth/Fire/Water/Air) with its spell name and a colored countdown progress bar - Colored element dot (brown/red/blue/light-blue) identifies element - Only rendered when at least one totem is active
This commit is contained in:
parent
ef08366efc
commit
1f7f1076ca
2 changed files with 87 additions and 0 deletions
|
|
@ -283,6 +283,7 @@ private:
|
|||
* Render pet frame (below player frame when player has an active pet)
|
||||
*/
|
||||
void renderPetFrame(game::GameHandler& gameHandler);
|
||||
void renderTotemFrame(game::GameHandler& gameHandler);
|
||||
|
||||
/**
|
||||
* Process targeting input (Tab, Escape, click)
|
||||
|
|
|
|||
|
|
@ -516,6 +516,11 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
renderPetFrame(gameHandler);
|
||||
}
|
||||
|
||||
// Totem frame (Shaman only, when any totem is active)
|
||||
if (gameHandler.getPlayerClass() == 7) {
|
||||
renderTotemFrame(gameHandler);
|
||||
}
|
||||
|
||||
// Target frame (only when we have a target)
|
||||
if (gameHandler.hasTarget()) {
|
||||
renderTargetFrame(gameHandler);
|
||||
|
|
@ -3032,6 +3037,87 @@ void GameScreen::renderPetFrame(game::GameHandler& gameHandler) {
|
|||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Totem Frame (Shaman — below pet frame / player frame)
|
||||
// ============================================================
|
||||
|
||||
void GameScreen::renderTotemFrame(game::GameHandler& gameHandler) {
|
||||
// Only show if at least one totem is active
|
||||
bool anyActive = false;
|
||||
for (int i = 0; i < game::GameHandler::NUM_TOTEM_SLOTS; ++i) {
|
||||
if (gameHandler.getTotemSlot(i).active()) { anyActive = true; break; }
|
||||
}
|
||||
if (!anyActive) return;
|
||||
|
||||
static const struct { const char* name; ImU32 color; } kTotemInfo[4] = {
|
||||
{ "Earth", IM_COL32(139, 90, 43, 255) }, // brown
|
||||
{ "Fire", IM_COL32(220, 80, 30, 255) }, // red-orange
|
||||
{ "Water", IM_COL32( 30,120, 220, 255) }, // blue
|
||||
{ "Air", IM_COL32(180,220, 255, 255) }, // light blue
|
||||
};
|
||||
|
||||
// Position: below pet frame / player frame, left side
|
||||
// Pet frame is at ~y=200 if active, player frame is at y=20; totem frame near y=300
|
||||
// We anchor relative to screen left edge like pet frame
|
||||
ImGui::SetNextWindowPos(ImVec2(8.0f, 300.0f), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(130.0f, 0.0f), ImGuiCond_Always);
|
||||
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoTitleBar;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.1f, 0.08f, 0.06f, 0.88f));
|
||||
|
||||
if (ImGui::Begin("##TotemFrame", nullptr, flags)) {
|
||||
ImGui::TextColored(ImVec4(0.9f, 0.75f, 0.3f, 1.0f), "Totems");
|
||||
ImGui::Separator();
|
||||
|
||||
for (int i = 0; i < game::GameHandler::NUM_TOTEM_SLOTS; ++i) {
|
||||
const auto& slot = gameHandler.getTotemSlot(i);
|
||||
if (!slot.active()) continue;
|
||||
|
||||
ImGui::PushID(i);
|
||||
|
||||
// Colored element dot
|
||||
ImVec2 dotPos = ImGui::GetCursorScreenPos();
|
||||
dotPos.x += 4.0f; dotPos.y += 6.0f;
|
||||
ImGui::GetWindowDrawList()->AddCircleFilled(
|
||||
ImVec2(dotPos.x + 4.0f, dotPos.y + 4.0f), 4.0f, kTotemInfo[i].color);
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 14.0f);
|
||||
|
||||
// Totem name or spell name
|
||||
const std::string& spellName = gameHandler.getSpellName(slot.spellId);
|
||||
const char* displayName = spellName.empty() ? kTotemInfo[i].name : spellName.c_str();
|
||||
ImGui::Text("%s", displayName);
|
||||
|
||||
// Duration countdown bar
|
||||
float remMs = slot.remainingMs();
|
||||
float totMs = static_cast<float>(slot.durationMs);
|
||||
float frac = (totMs > 0.0f) ? std::min(remMs / totMs, 1.0f) : 0.0f;
|
||||
float remSec = remMs / 1000.0f;
|
||||
|
||||
// Color bar with totem element tint
|
||||
ImVec4 barCol(
|
||||
static_cast<float>((kTotemInfo[i].color >> IM_COL32_R_SHIFT) & 0xFF) / 255.0f,
|
||||
static_cast<float>((kTotemInfo[i].color >> IM_COL32_G_SHIFT) & 0xFF) / 255.0f,
|
||||
static_cast<float>((kTotemInfo[i].color >> IM_COL32_B_SHIFT) & 0xFF) / 255.0f,
|
||||
0.9f);
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, barCol);
|
||||
char timeBuf[16];
|
||||
snprintf(timeBuf, sizeof(timeBuf), "%.0fs", remSec);
|
||||
ImGui::ProgressBar(frac, ImVec2(-1, 8), timeBuf);
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) {
|
||||
auto target = gameHandler.getTarget();
|
||||
if (!target) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue