feat: add Shaman totem bar in player frame

Store active totem state (slot, spellId, duration, placedAt) from
SMSG_TOTEM_CREATED. Render 4 element slots (Earth/Fire/Water/Air) as
color-coded duration bars in the player frame for Shamans (class 7).
Shows countdown seconds, element letter when inactive, and tooltip
with spell name + remaining time on hover.
This commit is contained in:
Kelsi 2026-03-12 05:16:43 -07:00
parent 8efdaed7e4
commit 5827a8fcdd
3 changed files with 107 additions and 0 deletions

View file

@ -1277,6 +1277,26 @@ public:
};
const std::vector<FactionStandingInit>& getInitialFactions() const { return initialFactions_; }
const std::unordered_map<uint32_t, int32_t>& getFactionStandings() const { return factionStandings_; }
// Shaman totems (4 slots: 0=Earth, 1=Fire, 2=Water, 3=Air)
struct TotemSlot {
uint32_t spellId = 0;
uint32_t durationMs = 0;
std::chrono::steady_clock::time_point placedAt{};
bool active() const { return spellId != 0 && remainingMs() > 0; }
float remainingMs() const {
if (spellId == 0 || durationMs == 0) return 0.0f;
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - placedAt).count();
float rem = static_cast<float>(durationMs) - static_cast<float>(elapsed);
return rem > 0.0f ? rem : 0.0f;
}
};
static constexpr int NUM_TOTEM_SLOTS = 4;
const TotemSlot& getTotemSlot(int slot) const {
static TotemSlot empty;
return (slot >= 0 && slot < NUM_TOTEM_SLOTS) ? activeTotemSlots_[slot] : empty;
}
const std::string& getFactionNamePublic(uint32_t factionId) const;
uint32_t getWatchedFactionId() const { return watchedFactionId_; }
void setWatchedFactionId(uint32_t id) { watchedFactionId_ = id; }
@ -2254,6 +2274,9 @@ private:
uint64_t myTradeGold_ = 0;
uint64_t peerTradeGold_ = 0;
// Shaman totem state
TotemSlot activeTotemSlots_[NUM_TOTEM_SLOTS];
// Duel state
bool pendingDuelRequest_ = false;
uint64_t duelChallengerGuid_= 0;