mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Spell icons now render with a purple desaturated tint when the player lacks enough mana/rage/energy/runic power to cast them. Power cost and type are read from Spell.dbc via the spellbook's DBC cache. The spell tooltip also shows "Not enough power" in purple when applicable. Priority: cooldown > GCD > out-of-range > insufficient-power so states don't conflict. Adds SpellbookScreen::getSpellPowerInfo() as a public DBC accessor.
122 lines
4.8 KiB
C++
122 lines
4.8 KiB
C++
#pragma once
|
|
|
|
#include "game/game_handler.hpp"
|
|
#include <vulkan/vulkan.h>
|
|
#include <imgui.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
|
|
namespace wowee {
|
|
|
|
namespace pipeline { class AssetManager; }
|
|
|
|
namespace ui {
|
|
|
|
struct SpellInfo {
|
|
uint32_t spellId = 0;
|
|
std::string name;
|
|
std::string rank;
|
|
std::string description; // Tooltip/description text from Spell.dbc
|
|
uint32_t iconId = 0; // SpellIconID
|
|
uint32_t attributes = 0; // Spell attributes (field 4)
|
|
uint32_t castTimeMs = 0; // Cast time in ms (0 = instant)
|
|
uint32_t manaCost = 0; // Mana cost
|
|
uint32_t powerType = 0; // 0=mana, 1=rage, 2=focus, 3=energy
|
|
uint32_t rangeIndex = 0; // Range index from SpellRange.dbc
|
|
uint32_t schoolMask = 0; // School bitmask (1=phys,2=holy,4=fire,8=nature,16=frost,32=shadow,64=arcane)
|
|
bool isPassive() const { return (attributes & 0x40) != 0; }
|
|
};
|
|
|
|
struct SpellTabInfo {
|
|
std::string name;
|
|
std::vector<const SpellInfo*> spells;
|
|
};
|
|
|
|
class SpellbookScreen {
|
|
public:
|
|
void render(game::GameHandler& gameHandler, pipeline::AssetManager* assetManager);
|
|
bool isOpen() const { return open; }
|
|
void toggle() { open = !open; }
|
|
void setOpen(bool o) { open = o; }
|
|
|
|
// Spell name lookup — triggers DBC load if needed, used by action bar tooltips
|
|
std::string lookupSpellName(uint32_t spellId, pipeline::AssetManager* assetManager);
|
|
|
|
// Rich tooltip — renders a full spell tooltip (inside an already-open BeginTooltip block).
|
|
// Triggers DBC load if needed. Returns true if spell data was found.
|
|
bool renderSpellInfoTooltip(uint32_t spellId, game::GameHandler& gameHandler,
|
|
pipeline::AssetManager* assetManager);
|
|
|
|
// Drag-and-drop state for action bar assignment
|
|
bool isDraggingSpell() const { return draggingSpell_; }
|
|
uint32_t getDragSpellId() const { return dragSpellId_; }
|
|
void consumeDragSpell() { draggingSpell_ = false; dragSpellId_ = 0; dragSpellIconTex_ = VK_NULL_HANDLE; }
|
|
|
|
/// Returns the max range in yards for a spell (0 if self-cast, unknown, or melee).
|
|
/// Triggers DBC load if needed. Used by the action bar for out-of-range tinting.
|
|
uint32_t getSpellMaxRange(uint32_t spellId, pipeline::AssetManager* assetManager);
|
|
|
|
/// Returns the power cost and type for a spell (cost=0 if unknown/free).
|
|
/// powerType: 0=mana, 1=rage, 2=focus, 3=energy, 6=runic power.
|
|
/// Triggers DBC load if needed. Used by the action bar for insufficient-power tinting.
|
|
void getSpellPowerInfo(uint32_t spellId, pipeline::AssetManager* assetManager,
|
|
uint32_t& outCost, uint32_t& outPowerType);
|
|
|
|
/// Returns a WoW spell link string if the user shift-clicked a spell, then clears it.
|
|
std::string getAndClearPendingChatLink() {
|
|
std::string out = std::move(pendingChatSpellLink_);
|
|
pendingChatSpellLink_.clear();
|
|
return out;
|
|
}
|
|
|
|
private:
|
|
bool open = false;
|
|
bool pKeyWasDown = false;
|
|
|
|
// Spell data (loaded from Spell.dbc)
|
|
bool dbcLoaded = false;
|
|
bool dbcLoadAttempted = false;
|
|
std::unordered_map<uint32_t, SpellInfo> spellData;
|
|
|
|
// Icon data (loaded from SpellIcon.dbc)
|
|
bool iconDbLoaded = false;
|
|
std::unordered_map<uint32_t, std::string> spellIconPaths; // SpellIconID -> path
|
|
std::unordered_map<uint32_t, VkDescriptorSet> spellIconCache; // SpellIconID -> texture
|
|
|
|
// Skill line data (loaded from SkillLine.dbc + SkillLineAbility.dbc)
|
|
bool skillLineDbLoaded = false;
|
|
std::unordered_map<uint32_t, std::string> skillLineNames;
|
|
std::unordered_map<uint32_t, uint32_t> skillLineCategories;
|
|
std::unordered_multimap<uint32_t, uint32_t> spellToSkillLine;
|
|
|
|
// Categorized spell tabs
|
|
std::vector<SpellTabInfo> spellTabs;
|
|
size_t lastKnownSpellCount = 0;
|
|
bool categorizedWithSkillLines = false;
|
|
|
|
// Search filter
|
|
char searchFilter_[128] = "";
|
|
|
|
// Drag-and-drop from spellbook to action bar
|
|
bool draggingSpell_ = false;
|
|
uint32_t dragSpellId_ = 0;
|
|
VkDescriptorSet dragSpellIconTex_ = VK_NULL_HANDLE;
|
|
|
|
// Pending chat spell link from shift-click
|
|
std::string pendingChatSpellLink_;
|
|
|
|
void loadSpellDBC(pipeline::AssetManager* assetManager);
|
|
void loadSpellIconDBC(pipeline::AssetManager* assetManager);
|
|
void loadSkillLineDBCs(pipeline::AssetManager* assetManager);
|
|
void categorizeSpells(const std::unordered_set<uint32_t>& knownSpells);
|
|
VkDescriptorSet getSpellIcon(uint32_t iconId, pipeline::AssetManager* assetManager);
|
|
const SpellInfo* getSpellInfo(uint32_t spellId) const;
|
|
|
|
// Tooltip rendering helper (showUsageHints=false when called from action bar)
|
|
void renderSpellTooltip(const SpellInfo* info, game::GameHandler& gameHandler, bool showUsageHints = true);
|
|
};
|
|
|
|
} // namespace ui
|
|
} // namespace wowee
|