#pragma once #include "game/game_handler.hpp" #include #include #include #include #include #include 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 bool isPassive() const { return (attributes & 0x40) != 0; } }; struct SpellTabInfo { std::string name; std::vector 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); // 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; } private: bool open = false; bool pKeyWasDown = false; // Spell data (loaded from Spell.dbc) bool dbcLoaded = false; bool dbcLoadAttempted = false; std::unordered_map spellData; // Icon data (loaded from SpellIcon.dbc) bool iconDbLoaded = false; std::unordered_map spellIconPaths; // SpellIconID -> path std::unordered_map spellIconCache; // SpellIconID -> texture // Skill line data (loaded from SkillLine.dbc + SkillLineAbility.dbc) bool skillLineDbLoaded = false; std::unordered_map skillLineNames; std::unordered_map skillLineCategories; std::unordered_multimap spellToSkillLine; // Categorized spell tabs std::vector 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; void loadSpellDBC(pipeline::AssetManager* assetManager); void loadSpellIconDBC(pipeline::AssetManager* assetManager); void loadSkillLineDBCs(pipeline::AssetManager* assetManager); void categorizeSpells(const std::unordered_set& knownSpells); VkDescriptorSet getSpellIcon(uint32_t iconId, pipeline::AssetManager* assetManager); const SpellInfo* getSpellInfo(uint32_t spellId) const; // Tooltip rendering helper void renderSpellTooltip(const SpellInfo* info, game::GameHandler& gameHandler); }; } // namespace ui } // namespace wowee