mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-09 02:23:52 +00:00
Merge pull request #33 from ldmonster/chore/game-screen-extract
[chore] refactor(ui): GameScreen — extract 7 UI sub-panels
This commit is contained in:
commit
9eb8ca2988
24 changed files with 20568 additions and 19417 deletions
|
|
@ -616,6 +616,14 @@ set(WOWEE_SOURCES
|
||||||
src/ui/character_create_screen.cpp
|
src/ui/character_create_screen.cpp
|
||||||
src/ui/character_screen.cpp
|
src/ui/character_screen.cpp
|
||||||
src/ui/game_screen.cpp
|
src/ui/game_screen.cpp
|
||||||
|
src/ui/chat_panel.cpp
|
||||||
|
src/ui/toast_manager.cpp
|
||||||
|
src/ui/dialog_manager.cpp
|
||||||
|
src/ui/settings_panel.cpp
|
||||||
|
src/ui/combat_ui.cpp
|
||||||
|
src/ui/social_panel.cpp
|
||||||
|
src/ui/action_bar_panel.cpp
|
||||||
|
src/ui/window_manager.cpp
|
||||||
src/ui/inventory_screen.cpp
|
src/ui/inventory_screen.cpp
|
||||||
src/ui/quest_log_screen.cpp
|
src/ui/quest_log_screen.cpp
|
||||||
src/ui/spellbook_screen.cpp
|
src/ui/spellbook_screen.cpp
|
||||||
|
|
|
||||||
|
|
@ -143,28 +143,25 @@ private:
|
||||||
void applyUpdateObjectBlock(const UpdateBlock& block, bool& newItemCreated);
|
void applyUpdateObjectBlock(const UpdateBlock& block, bool& newItemCreated);
|
||||||
void finalizeUpdateObjectBatch(bool newItemCreated);
|
void finalizeUpdateObjectBatch(bool newItemCreated);
|
||||||
|
|
||||||
// --- Phase 1: Extracted helper methods ---
|
|
||||||
bool extractPlayerAppearance(const std::map<uint16_t, uint32_t>& fields,
|
bool extractPlayerAppearance(const std::map<uint16_t, uint32_t>& fields,
|
||||||
uint8_t& outRace, uint8_t& outGender,
|
uint8_t& outRace, uint8_t& outGender,
|
||||||
uint32_t& outAppearanceBytes, uint8_t& outFacial) const;
|
uint32_t& outAppearanceBytes, uint8_t& outFacial) const;
|
||||||
void maybeDetectCoinageIndex(const std::map<uint16_t, uint32_t>& oldFields,
|
void maybeDetectCoinageIndex(const std::map<uint16_t, uint32_t>& oldFields,
|
||||||
const std::map<uint16_t, uint32_t>& newFields);
|
const std::map<uint16_t, uint32_t>& newFields);
|
||||||
|
|
||||||
// --- Phase 2: Update type handlers ---
|
|
||||||
void handleCreateObject(const UpdateBlock& block, bool& newItemCreated);
|
void handleCreateObject(const UpdateBlock& block, bool& newItemCreated);
|
||||||
void handleValuesUpdate(const UpdateBlock& block);
|
void handleValuesUpdate(const UpdateBlock& block);
|
||||||
void handleMovementUpdate(const UpdateBlock& block);
|
void handleMovementUpdate(const UpdateBlock& block);
|
||||||
|
|
||||||
// --- Phase 3: Concern-specific helpers ---
|
// Update transport-relative child attachment (non-player entities).
|
||||||
// 3i: Update transport-relative child attachment (non-player entities).
|
|
||||||
// Consolidates identical logic from CREATE/VALUES/MOVEMENT handlers.
|
// Consolidates identical logic from CREATE/VALUES/MOVEMENT handlers.
|
||||||
void updateNonPlayerTransportAttachment(const UpdateBlock& block,
|
void updateNonPlayerTransportAttachment(const UpdateBlock& block,
|
||||||
const std::shared_ptr<Entity>& entity,
|
const std::shared_ptr<Entity>& entity,
|
||||||
ObjectType entityType);
|
ObjectType entityType);
|
||||||
// 3f: Rebuild playerAuras_ from UNIT_FIELD_AURAS (Classic/vanilla only).
|
// Rebuild playerAuras_ from UNIT_FIELD_AURAS (Classic/vanilla only).
|
||||||
// Consolidates identical logic from CREATE and VALUES handlers.
|
// Consolidates identical logic from CREATE and VALUES handlers.
|
||||||
void syncClassicAurasFromFields(const std::shared_ptr<Entity>& entity);
|
void syncClassicAurasFromFields(const std::shared_ptr<Entity>& entity);
|
||||||
// 3h: Detect mount/dismount from UNIT_FIELD_MOUNTDISPLAYID changes (self-player only).
|
// Detect mount/dismount from UNIT_FIELD_MOUNTDISPLAYID changes (self-player only).
|
||||||
// Consolidates identical logic from CREATE and VALUES handlers.
|
// Consolidates identical logic from CREATE and VALUES handlers.
|
||||||
void detectPlayerMountChange(uint32_t newMountDisplayId,
|
void detectPlayerMountChange(uint32_t newMountDisplayId,
|
||||||
const std::map<uint16_t, uint32_t>& blockFields);
|
const std::map<uint16_t, uint32_t>& blockFields);
|
||||||
|
|
@ -172,7 +169,6 @@ private:
|
||||||
// Shared player-death handler: caches corpse position, sets death state.
|
// Shared player-death handler: caches corpse position, sets death state.
|
||||||
void markPlayerDead(const char* source);
|
void markPlayerDead(const char* source);
|
||||||
|
|
||||||
// --- Phase 4: Field index cache structs ---
|
|
||||||
// Cached field indices resolved once per handler call to avoid repeated lookups.
|
// Cached field indices resolved once per handler call to avoid repeated lookups.
|
||||||
struct UnitFieldIndices {
|
struct UnitFieldIndices {
|
||||||
uint16_t health, maxHealth, powerBase, maxPowerBase;
|
uint16_t health, maxHealth, powerBase, maxPowerBase;
|
||||||
|
|
@ -202,43 +198,42 @@ private:
|
||||||
uint32_t oldDisplayId = 0;
|
uint32_t oldDisplayId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Phase 3: Extracted concern-specific helpers (continued) ---
|
// Entity factory — creates the correct Entity subclass for the given block.
|
||||||
// 3a: Entity factory — creates the correct Entity subclass for the given block.
|
|
||||||
std::shared_ptr<Entity> createEntityFromBlock(const UpdateBlock& block);
|
std::shared_ptr<Entity> createEntityFromBlock(const UpdateBlock& block);
|
||||||
// 3b: Track player-on-transport state from movement blocks.
|
// Track player-on-transport state from movement blocks.
|
||||||
void applyPlayerTransportState(const UpdateBlock& block,
|
void applyPlayerTransportState(const UpdateBlock& block,
|
||||||
const std::shared_ptr<Entity>& entity,
|
const std::shared_ptr<Entity>& entity,
|
||||||
const glm::vec3& canonicalPos, float oCanonical,
|
const glm::vec3& canonicalPos, float oCanonical,
|
||||||
bool updateMovementInfoPos);
|
bool updateMovementInfoPos);
|
||||||
// 3c: Apply unit fields during CREATE — returns true if entity is initially dead.
|
// Apply unit fields during CREATE — returns true if entity is initially dead.
|
||||||
bool applyUnitFieldsOnCreate(const UpdateBlock& block,
|
bool applyUnitFieldsOnCreate(const UpdateBlock& block,
|
||||||
std::shared_ptr<Unit>& unit,
|
std::shared_ptr<Unit>& unit,
|
||||||
const UnitFieldIndices& ufi);
|
const UnitFieldIndices& ufi);
|
||||||
// 3c: Apply unit fields during VALUES — returns change tracking result.
|
// Apply unit fields during VALUES — returns change tracking result.
|
||||||
UnitFieldUpdateResult applyUnitFieldsOnUpdate(const UpdateBlock& block,
|
UnitFieldUpdateResult applyUnitFieldsOnUpdate(const UpdateBlock& block,
|
||||||
const std::shared_ptr<Entity>& entity,
|
const std::shared_ptr<Entity>& entity,
|
||||||
std::shared_ptr<Unit>& unit,
|
std::shared_ptr<Unit>& unit,
|
||||||
const UnitFieldIndices& ufi);
|
const UnitFieldIndices& ufi);
|
||||||
// 3d: Apply player stat fields (XP, inventory, skills, etc.). isCreate=true for CREATE path.
|
// Apply player stat fields (XP, inventory, skills, etc.). isCreate=true for CREATE path.
|
||||||
bool applyPlayerStatFields(const std::map<uint16_t, uint32_t>& fields,
|
bool applyPlayerStatFields(const std::map<uint16_t, uint32_t>& fields,
|
||||||
const PlayerFieldIndices& pfi, bool isCreate);
|
const PlayerFieldIndices& pfi, bool isCreate);
|
||||||
// 3e: Dispatch spawn callbacks (creature/player) — deduplicates CREATE and VALUES paths.
|
// Dispatch spawn callbacks (creature/player) — deduplicates CREATE and VALUES paths.
|
||||||
void dispatchEntitySpawn(uint64_t guid, ObjectType objectType,
|
void dispatchEntitySpawn(uint64_t guid, ObjectType objectType,
|
||||||
const std::shared_ptr<Entity>& entity,
|
const std::shared_ptr<Entity>& entity,
|
||||||
const std::shared_ptr<Unit>& unit, bool isDead);
|
const std::shared_ptr<Unit>& unit, bool isDead);
|
||||||
// 3g: Track item/container on CREATE.
|
// Track item/container on CREATE.
|
||||||
void trackItemOnCreate(const UpdateBlock& block, bool& newItemCreated);
|
void trackItemOnCreate(const UpdateBlock& block, bool& newItemCreated);
|
||||||
// 3g: Update item fields on VALUES update.
|
// Update item fields on VALUES update.
|
||||||
void updateItemOnValuesUpdate(const UpdateBlock& block,
|
void updateItemOnValuesUpdate(const UpdateBlock& block,
|
||||||
const std::shared_ptr<Entity>& entity);
|
const std::shared_ptr<Entity>& entity);
|
||||||
|
|
||||||
// --- Phase 5: Strategy pattern — object-type handler interface ---
|
|
||||||
// Allows extending object-type handling without modifying handler dispatch.
|
// Allows extending object-type handling without modifying handler dispatch.
|
||||||
struct IObjectTypeHandler {
|
struct IObjectTypeHandler {
|
||||||
virtual ~IObjectTypeHandler() = default;
|
virtual ~IObjectTypeHandler() = default;
|
||||||
virtual void onCreate(const UpdateBlock&, std::shared_ptr<Entity>&, bool&) {}
|
virtual void onCreate(const UpdateBlock& /*block*/, std::shared_ptr<Entity>& /*entity*/,
|
||||||
virtual void onValuesUpdate(const UpdateBlock&, std::shared_ptr<Entity>&) {}
|
bool& /*newItemCreated*/) {}
|
||||||
virtual void onMovementUpdate(const UpdateBlock&, std::shared_ptr<Entity>&) {}
|
virtual void onValuesUpdate(const UpdateBlock& /*block*/, std::shared_ptr<Entity>& /*entity*/) {}
|
||||||
|
virtual void onMovementUpdate(const UpdateBlock& /*block*/, std::shared_ptr<Entity>& /*entity*/) {}
|
||||||
};
|
};
|
||||||
struct UnitTypeHandler;
|
struct UnitTypeHandler;
|
||||||
struct PlayerTypeHandler;
|
struct PlayerTypeHandler;
|
||||||
|
|
@ -249,7 +244,6 @@ private:
|
||||||
void initTypeHandlers();
|
void initTypeHandlers();
|
||||||
IObjectTypeHandler* getTypeHandler(ObjectType type) const;
|
IObjectTypeHandler* getTypeHandler(ObjectType type) const;
|
||||||
|
|
||||||
// --- Phase 5: Type-specific handler implementations (trampolined from handlers) ---
|
|
||||||
void onCreateUnit(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
void onCreateUnit(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||||
void onCreatePlayer(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
void onCreatePlayer(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||||
void onCreateGameObject(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
void onCreateGameObject(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||||
|
|
@ -264,7 +258,6 @@ private:
|
||||||
void onValuesUpdateItem(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
void onValuesUpdateItem(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||||
void onValuesUpdateGameObject(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
void onValuesUpdateGameObject(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||||
|
|
||||||
// --- Phase 6: Deferred event bus ---
|
|
||||||
// Collects addon events during block processing, flushes at the end.
|
// Collects addon events during block processing, flushes at the end.
|
||||||
struct PendingEvents {
|
struct PendingEvents {
|
||||||
std::vector<std::pair<std::string, std::vector<std::string>>> events;
|
std::vector<std::pair<std::string, std::vector<std::string>>> events;
|
||||||
|
|
|
||||||
|
|
@ -627,7 +627,6 @@ public:
|
||||||
void resetWardenState(); // clear all warden module/crypto state for connect/disconnect
|
void resetWardenState(); // clear all warden module/crypto state for connect/disconnect
|
||||||
void clearUnitCaches(); // clear per-unit cast states and aura caches
|
void clearUnitCaches(); // clear per-unit cast states and aura caches
|
||||||
|
|
||||||
// ---- Phase 1: Name queries (delegated to EntityController) ----
|
|
||||||
void queryPlayerName(uint64_t guid);
|
void queryPlayerName(uint64_t guid);
|
||||||
void queryCreatureInfo(uint32_t entry, uint64_t guid);
|
void queryCreatureInfo(uint32_t entry, uint64_t guid);
|
||||||
void queryGameObjectInfo(uint32_t entry, uint64_t guid);
|
void queryGameObjectInfo(uint32_t entry, uint64_t guid);
|
||||||
|
|
@ -661,7 +660,6 @@ public:
|
||||||
return entityController_->getCreatureFamily(entry);
|
return entityController_->getCreatureFamily(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Phase 2: Combat (delegated to CombatHandler) ----
|
|
||||||
void startAutoAttack(uint64_t targetGuid);
|
void startAutoAttack(uint64_t targetGuid);
|
||||||
void stopAutoAttack();
|
void stopAutoAttack();
|
||||||
bool isAutoAttacking() const;
|
bool isAutoAttacking() const;
|
||||||
|
|
@ -696,7 +694,6 @@ public:
|
||||||
const std::vector<ThreatEntry>* getThreatList(uint64_t unitGuid) const;
|
const std::vector<ThreatEntry>* getThreatList(uint64_t unitGuid) const;
|
||||||
const std::vector<ThreatEntry>* getTargetThreatList() const;
|
const std::vector<ThreatEntry>* getTargetThreatList() const;
|
||||||
|
|
||||||
// ---- Phase 3: Spells ----
|
|
||||||
void castSpell(uint32_t spellId, uint64_t targetGuid = 0);
|
void castSpell(uint32_t spellId, uint64_t targetGuid = 0);
|
||||||
void cancelCast();
|
void cancelCast();
|
||||||
void cancelAura(uint32_t spellId);
|
void cancelAura(uint32_t spellId);
|
||||||
|
|
@ -1239,7 +1236,7 @@ public:
|
||||||
void acceptResurrect();
|
void acceptResurrect();
|
||||||
void declineResurrect();
|
void declineResurrect();
|
||||||
|
|
||||||
// ---- Phase 4: Group ----
|
// ---- Group ----
|
||||||
void inviteToGroup(const std::string& playerName);
|
void inviteToGroup(const std::string& playerName);
|
||||||
void acceptGroupInvite();
|
void acceptGroupInvite();
|
||||||
void declineGroupInvite();
|
void declineGroupInvite();
|
||||||
|
|
@ -1396,7 +1393,7 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Phase 5: Loot ----
|
// ---- Loot ----
|
||||||
void lootTarget(uint64_t guid);
|
void lootTarget(uint64_t guid);
|
||||||
void lootItem(uint8_t slotIndex);
|
void lootItem(uint8_t slotIndex);
|
||||||
void closeLoot();
|
void closeLoot();
|
||||||
|
|
@ -2177,7 +2174,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void handlePong(network::Packet& packet);
|
void handlePong(network::Packet& packet);
|
||||||
|
|
||||||
// ---- Phase 1 handlers (entity queries delegated to EntityController) ----
|
|
||||||
void handleItemQueryResponse(network::Packet& packet);
|
void handleItemQueryResponse(network::Packet& packet);
|
||||||
void queryItemInfo(uint32_t entry, uint64_t guid);
|
void queryItemInfo(uint32_t entry, uint64_t guid);
|
||||||
void rebuildOnlineInventory();
|
void rebuildOnlineInventory();
|
||||||
|
|
@ -2190,7 +2186,6 @@ private:
|
||||||
void extractContainerFields(uint64_t containerGuid, const std::map<uint16_t, uint32_t>& fields);
|
void extractContainerFields(uint64_t containerGuid, const std::map<uint16_t, uint32_t>& fields);
|
||||||
uint64_t resolveOnlineItemGuid(uint32_t itemId) const;
|
uint64_t resolveOnlineItemGuid(uint32_t itemId) const;
|
||||||
|
|
||||||
// ---- Phase 2 handlers (dead — dispatched via CombatHandler) ----
|
|
||||||
// handleAttackStart, handleAttackStop, handleAttackerStateUpdate,
|
// handleAttackStart, handleAttackStop, handleAttackerStateUpdate,
|
||||||
// handleSpellDamageLog, handleSpellHealLog removed
|
// handleSpellDamageLog, handleSpellHealLog removed
|
||||||
|
|
||||||
|
|
@ -2198,12 +2193,6 @@ private:
|
||||||
void handleUpdateAuraDuration(uint8_t slot, uint32_t durationMs);
|
void handleUpdateAuraDuration(uint8_t slot, uint32_t durationMs);
|
||||||
// handleSetForcedReactions — dispatched via CombatHandler
|
// handleSetForcedReactions — dispatched via CombatHandler
|
||||||
|
|
||||||
// ---- Phase 3 handlers ----
|
|
||||||
|
|
||||||
// ---- Talent handlers ----
|
|
||||||
|
|
||||||
// ---- Phase 4 handlers ----
|
|
||||||
|
|
||||||
// ---- Guild handlers ----
|
// ---- Guild handlers ----
|
||||||
void handlePetSpells(network::Packet& packet);
|
void handlePetSpells(network::Packet& packet);
|
||||||
|
|
||||||
|
|
@ -2217,7 +2206,6 @@ private:
|
||||||
|
|
||||||
// ---- Other player movement (MSG_MOVE_* from server) ----
|
// ---- Other player movement (MSG_MOVE_* from server) ----
|
||||||
|
|
||||||
// ---- Phase 5 handlers ----
|
|
||||||
void clearPendingQuestAccept(uint32_t questId);
|
void clearPendingQuestAccept(uint32_t questId);
|
||||||
void triggerQuestAcceptResync(uint32_t questId, uint64_t npcGuid, const char* reason);
|
void triggerQuestAcceptResync(uint32_t questId, uint64_t npcGuid, const char* reason);
|
||||||
bool hasQuestInLog(uint32_t questId) const;
|
bool hasQuestInLog(uint32_t questId) const;
|
||||||
|
|
@ -2411,7 +2399,6 @@ private:
|
||||||
uint32_t homeBindZoneId_ = 0;
|
uint32_t homeBindZoneId_ = 0;
|
||||||
glm::vec3 homeBindPos_{0.0f};
|
glm::vec3 homeBindPos_{0.0f};
|
||||||
|
|
||||||
// ---- Phase 1: Name caches (moved to EntityController) ----
|
|
||||||
|
|
||||||
// ---- Friend/contact list cache ----
|
// ---- Friend/contact list cache ----
|
||||||
std::unordered_map<std::string, uint64_t> friendsCache; // name -> guid
|
std::unordered_map<std::string, uint64_t> friendsCache; // name -> guid
|
||||||
|
|
@ -2510,11 +2497,10 @@ private:
|
||||||
std::unordered_set<uint64_t> pendingAutoInspect_;
|
std::unordered_set<uint64_t> pendingAutoInspect_;
|
||||||
float inspectRateLimit_ = 0.0f;
|
float inspectRateLimit_ = 0.0f;
|
||||||
|
|
||||||
// ---- Phase 2: Combat (state moved to CombatHandler) ----
|
// ---- Combat ----
|
||||||
bool wasCombat_ = false; // Previous frame combat state for PLAYER_REGEN edge detection
|
bool wasCombat_ = false; // Previous frame combat state for PLAYER_REGEN edge detection
|
||||||
std::deque<std::string> areaTriggerMsgs_;
|
std::deque<std::string> areaTriggerMsgs_;
|
||||||
|
|
||||||
// ---- Phase 3: Spells ----
|
|
||||||
WorldEntryCallback worldEntryCallback_;
|
WorldEntryCallback worldEntryCallback_;
|
||||||
KnockBackCallback knockBackCallback_;
|
KnockBackCallback knockBackCallback_;
|
||||||
CameraShakeCallback cameraShakeCallback_;
|
CameraShakeCallback cameraShakeCallback_;
|
||||||
|
|
@ -2674,7 +2660,7 @@ private:
|
||||||
void loadFactionNameCache() const;
|
void loadFactionNameCache() const;
|
||||||
std::string getFactionName(uint32_t factionId) const;
|
std::string getFactionName(uint32_t factionId) const;
|
||||||
|
|
||||||
// ---- Phase 4: Group ----
|
// ---- Group ----
|
||||||
GroupListData partyData;
|
GroupListData partyData;
|
||||||
bool pendingGroupInvite = false;
|
bool pendingGroupInvite = false;
|
||||||
std::string pendingInviterName;
|
std::string pendingInviterName;
|
||||||
|
|
@ -2745,7 +2731,7 @@ private:
|
||||||
// Barber shop
|
// Barber shop
|
||||||
bool barberShopOpen_ = false;
|
bool barberShopOpen_ = false;
|
||||||
|
|
||||||
// ---- Phase 5: Loot ----
|
// ---- Loot ----
|
||||||
bool lootWindowOpen = false;
|
bool lootWindowOpen = false;
|
||||||
bool autoLoot_ = false;
|
bool autoLoot_ = false;
|
||||||
bool autoSellGrey_ = false;
|
bool autoSellGrey_ = false;
|
||||||
|
|
|
||||||
|
|
@ -1460,7 +1460,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Phase 1: Foundation — Targeting, Name Queries
|
// Foundation — Targeting, Name Queries
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** CMSG_SET_SELECTION packet builder */
|
/** CMSG_SET_SELECTION packet builder */
|
||||||
|
|
@ -1663,7 +1663,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Phase 2: Combat Core
|
// Combat Core
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** SMSG_MONSTER_MOVE data */
|
/** SMSG_MONSTER_MOVE data */
|
||||||
|
|
@ -1805,7 +1805,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Phase 3: Spells, Action Bar, Auras
|
// Spells, Action Bar, Auras
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** SMSG_INITIAL_SPELLS data */
|
/** SMSG_INITIAL_SPELLS data */
|
||||||
|
|
@ -1930,7 +1930,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Phase 4: Group/Party System
|
// Group/Party System
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** CMSG_GROUP_INVITE packet builder */
|
/** CMSG_GROUP_INVITE packet builder */
|
||||||
|
|
@ -1998,7 +1998,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Phase 5: Loot System
|
// Loot System
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** Loot item entry */
|
/** Loot item entry */
|
||||||
|
|
@ -2100,7 +2100,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Phase 5: NPC Gossip
|
// NPC Gossip
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** Gossip menu option */
|
/** Gossip menu option */
|
||||||
|
|
@ -2278,7 +2278,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Phase 5: Vendor
|
// Vendor
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/** Vendor item entry */
|
/** Vendor item entry */
|
||||||
|
|
|
||||||
78
include/ui/action_bar_panel.hpp
Normal file
78
include/ui/action_bar_panel.hpp
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
// ============================================================
|
||||||
|
// ActionBarPanel — extracted from GameScreen
|
||||||
|
// Owns all action bar rendering: main bar, stance bar, bag bar,
|
||||||
|
// XP bar, reputation bar, macro resolution.
|
||||||
|
// ============================================================
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace game { class GameHandler; }
|
||||||
|
namespace pipeline { class AssetManager; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class ChatPanel;
|
||||||
|
class SettingsPanel;
|
||||||
|
class InventoryScreen;
|
||||||
|
class SpellbookScreen;
|
||||||
|
class QuestLogScreen;
|
||||||
|
|
||||||
|
class ActionBarPanel {
|
||||||
|
public:
|
||||||
|
// Callback type for resolving spell icons (spellId, assetMgr) → VkDescriptorSet
|
||||||
|
using SpellIconFn = std::function<VkDescriptorSet(uint32_t, pipeline::AssetManager*)>;
|
||||||
|
|
||||||
|
// ---- Action bar render methods ----
|
||||||
|
void renderActionBar(game::GameHandler& gameHandler,
|
||||||
|
SettingsPanel& settingsPanel,
|
||||||
|
ChatPanel& chatPanel,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
SpellbookScreen& spellbookScreen,
|
||||||
|
QuestLogScreen& questLogScreen,
|
||||||
|
SpellIconFn getSpellIcon);
|
||||||
|
void renderStanceBar(game::GameHandler& gameHandler,
|
||||||
|
SettingsPanel& settingsPanel,
|
||||||
|
SpellbookScreen& spellbookScreen,
|
||||||
|
SpellIconFn getSpellIcon);
|
||||||
|
void renderBagBar(game::GameHandler& gameHandler,
|
||||||
|
SettingsPanel& settingsPanel,
|
||||||
|
InventoryScreen& inventoryScreen);
|
||||||
|
void renderXpBar(game::GameHandler& gameHandler,
|
||||||
|
SettingsPanel& settingsPanel);
|
||||||
|
void renderRepBar(game::GameHandler& gameHandler,
|
||||||
|
SettingsPanel& settingsPanel);
|
||||||
|
|
||||||
|
// ---- State owned by this panel ----
|
||||||
|
|
||||||
|
// Action bar error-flash: spellId → wall-clock time (seconds) when the flash ends
|
||||||
|
std::unordered_map<uint32_t, float> actionFlashEndTimes_;
|
||||||
|
static constexpr float kActionFlashDuration = 0.5f;
|
||||||
|
|
||||||
|
// Action bar drag state (-1 = not dragging)
|
||||||
|
int actionBarDragSlot_ = -1;
|
||||||
|
VkDescriptorSet actionBarDragIcon_ = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
// Bag bar state
|
||||||
|
VkDescriptorSet backpackIconTexture_ = VK_NULL_HANDLE;
|
||||||
|
VkDescriptorSet emptyBagSlotTexture_ = VK_NULL_HANDLE;
|
||||||
|
int bagBarPickedSlot_ = -1;
|
||||||
|
int bagBarDragSource_ = -1;
|
||||||
|
|
||||||
|
// Macro editor popup state
|
||||||
|
uint32_t macroEditorId_ = 0;
|
||||||
|
bool macroEditorOpen_ = false;
|
||||||
|
char macroEditorBuf_[256] = {};
|
||||||
|
|
||||||
|
// Macro cooldown cache: maps macro ID → resolved primary spell ID
|
||||||
|
std::unordered_map<uint32_t, uint32_t> macroPrimarySpellCache_;
|
||||||
|
size_t macroCacheSpellCount_ = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t resolveMacroPrimarySpellId(uint32_t macroId, game::GameHandler& gameHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
194
include/ui/chat_panel.hpp
Normal file
194
include/ui/chat_panel.hpp
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "game/game_handler.hpp"
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace pipeline { class AssetManager; }
|
||||||
|
namespace rendering { class Renderer; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class InventoryScreen;
|
||||||
|
class SpellbookScreen;
|
||||||
|
class QuestLogScreen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Self-contained chat UI panel extracted from GameScreen.
|
||||||
|
*
|
||||||
|
* Owns all chat state: input buffer, sent-history, tab filtering,
|
||||||
|
* slash-command parsing, chat bubbles, and chat-related settings.
|
||||||
|
*/
|
||||||
|
class ChatPanel {
|
||||||
|
public:
|
||||||
|
ChatPanel();
|
||||||
|
|
||||||
|
// ---- Main entry points (called by GameScreen) ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the chat window (tabs, history, input, etc.)
|
||||||
|
*/
|
||||||
|
void render(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
SpellbookScreen& spellbookScreen,
|
||||||
|
QuestLogScreen& questLogScreen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render 3D-projected chat bubbles above entities.
|
||||||
|
*/
|
||||||
|
void renderBubbles(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register one-shot callbacks on GameHandler (call once per session).
|
||||||
|
* Sets up the chat-bubble callback.
|
||||||
|
*/
|
||||||
|
void setupCallbacks(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
// ---- Input helpers (called by GameScreen keybind handling) ----
|
||||||
|
|
||||||
|
bool isChatInputActive() const { return chatInputActive_; }
|
||||||
|
|
||||||
|
/** Insert a spell / item link into the chat input buffer (shift-click). */
|
||||||
|
void insertChatLink(const std::string& link);
|
||||||
|
|
||||||
|
/** Activate the input field with a leading '/' (slash key). */
|
||||||
|
void activateSlashInput();
|
||||||
|
|
||||||
|
/** Activate (focus) the input field (Enter key). */
|
||||||
|
void activateInput();
|
||||||
|
|
||||||
|
/** Request that the chat input be focused next frame. */
|
||||||
|
void requestRefocus() { refocusChatInput_ = true; }
|
||||||
|
|
||||||
|
/** Set up a whisper to the given player name and focus input. */
|
||||||
|
void setWhisperTarget(const std::string& name);
|
||||||
|
|
||||||
|
/** Execute a macro body (one line per 'click'). */
|
||||||
|
void executeMacroText(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
SpellbookScreen& spellbookScreen,
|
||||||
|
QuestLogScreen& questLogScreen,
|
||||||
|
const std::string& macroText);
|
||||||
|
|
||||||
|
// ---- Slash-command side-effects ----
|
||||||
|
// GameScreen reads these each frame, then clears them.
|
||||||
|
|
||||||
|
struct SlashCommands {
|
||||||
|
bool showInspect = false;
|
||||||
|
bool toggleThreat = false;
|
||||||
|
bool showBgScore = false;
|
||||||
|
bool showGmTicket = false;
|
||||||
|
bool showWho = false;
|
||||||
|
bool toggleCombatLog = false;
|
||||||
|
bool takeScreenshot = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Return accumulated slash-command flags and reset them. */
|
||||||
|
SlashCommands consumeSlashCommands();
|
||||||
|
|
||||||
|
// ---- Chat settings (read/written by GameScreen save/load & settings tab) ----
|
||||||
|
|
||||||
|
bool chatShowTimestamps = false;
|
||||||
|
int chatFontSize = 1; // 0=small, 1=medium, 2=large
|
||||||
|
bool chatAutoJoinGeneral = true;
|
||||||
|
bool chatAutoJoinTrade = true;
|
||||||
|
bool chatAutoJoinLocalDefense = true;
|
||||||
|
bool chatAutoJoinLFG = true;
|
||||||
|
bool chatAutoJoinLocal = true;
|
||||||
|
int activeChatTab = 0;
|
||||||
|
|
||||||
|
/** Spell icon lookup callback — set by GameScreen each frame before render(). */
|
||||||
|
std::function<VkDescriptorSet(uint32_t, pipeline::AssetManager*)> getSpellIcon;
|
||||||
|
|
||||||
|
/** Render the "Chat" tab inside the Settings window. */
|
||||||
|
void renderSettingsTab(std::function<void()> saveSettingsFn);
|
||||||
|
|
||||||
|
/** Reset all chat settings to defaults. */
|
||||||
|
void restoreDefaults();
|
||||||
|
|
||||||
|
/** Replace $g/$G and $n/$N gender/name placeholders in quest/chat text. */
|
||||||
|
std::string replaceGenderPlaceholders(const std::string& text, game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// ---- Chat input state ----
|
||||||
|
char chatInputBuffer_[512] = "";
|
||||||
|
char whisperTargetBuffer_[256] = "";
|
||||||
|
bool chatInputActive_ = false;
|
||||||
|
int selectedChatType_ = 0; // 0=SAY .. 10=CHANNEL
|
||||||
|
int lastChatType_ = 0;
|
||||||
|
int selectedChannelIdx_ = 0;
|
||||||
|
bool chatInputMoveCursorToEnd_ = false;
|
||||||
|
bool refocusChatInput_ = false;
|
||||||
|
|
||||||
|
// Sent-message history (Up/Down arrow recall)
|
||||||
|
std::vector<std::string> chatSentHistory_;
|
||||||
|
int chatHistoryIdx_ = -1;
|
||||||
|
|
||||||
|
// Macro stop flag
|
||||||
|
bool macroStopped_ = false;
|
||||||
|
|
||||||
|
// Tab-completion state
|
||||||
|
std::string chatTabPrefix_;
|
||||||
|
std::vector<std::string> chatTabMatches_;
|
||||||
|
int chatTabMatchIdx_ = -1;
|
||||||
|
|
||||||
|
// Mention notification
|
||||||
|
size_t chatMentionSeenCount_ = 0;
|
||||||
|
|
||||||
|
// ---- Chat tabs ----
|
||||||
|
struct ChatTab {
|
||||||
|
std::string name;
|
||||||
|
uint64_t typeMask;
|
||||||
|
};
|
||||||
|
std::vector<ChatTab> chatTabs_;
|
||||||
|
std::vector<int> chatTabUnread_;
|
||||||
|
size_t chatTabSeenCount_ = 0;
|
||||||
|
|
||||||
|
void initChatTabs();
|
||||||
|
bool shouldShowMessage(const game::MessageChatData& msg, int tabIndex) const;
|
||||||
|
|
||||||
|
// ---- Chat window visual state ----
|
||||||
|
bool chatScrolledUp_ = false;
|
||||||
|
bool chatForceScrollToBottom_ = false;
|
||||||
|
bool chatWindowLocked_ = true;
|
||||||
|
ImVec2 chatWindowPos_ = ImVec2(0.0f, 0.0f);
|
||||||
|
bool chatWindowPosInit_ = false;
|
||||||
|
|
||||||
|
// ---- Chat bubbles ----
|
||||||
|
struct ChatBubble {
|
||||||
|
uint64_t senderGuid = 0;
|
||||||
|
std::string message;
|
||||||
|
float timeRemaining = 0.0f;
|
||||||
|
float totalDuration = 0.0f;
|
||||||
|
bool isYell = false;
|
||||||
|
};
|
||||||
|
std::vector<ChatBubble> chatBubbles_;
|
||||||
|
bool chatBubbleCallbackSet_ = false;
|
||||||
|
|
||||||
|
// ---- Whisper toast state (populated in render, rendered by GameScreen/ToastManager) ----
|
||||||
|
// Whisper scanning lives here because it's tightly coupled to chat history iteration.
|
||||||
|
size_t whisperSeenCount_ = 0;
|
||||||
|
|
||||||
|
// ---- Helpers ----
|
||||||
|
void sendChatMessage(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
SpellbookScreen& spellbookScreen,
|
||||||
|
QuestLogScreen& questLogScreen);
|
||||||
|
const char* getChatTypeName(game::ChatType type) const;
|
||||||
|
ImVec4 getChatTypeColor(game::ChatType type) const;
|
||||||
|
|
||||||
|
// Cached game handler for input callback (set each frame in render)
|
||||||
|
game::GameHandler* cachedGameHandler_ = nullptr;
|
||||||
|
|
||||||
|
// Join channel input buffer
|
||||||
|
char joinChannelBuffer_[128] = "";
|
||||||
|
|
||||||
|
// Slash command flags (accumulated, consumed by GameScreen)
|
||||||
|
SlashCommands slashCmds_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
76
include/ui/combat_ui.hpp
Normal file
76
include/ui/combat_ui.hpp
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace game { class GameHandler; }
|
||||||
|
namespace pipeline { class AssetManager; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class SettingsPanel;
|
||||||
|
class SpellbookScreen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combat UI overlay manager (extracted from GameScreen)
|
||||||
|
*
|
||||||
|
* Owns all combat-related rendering:
|
||||||
|
* cast bar, cooldown tracker, raid warning overlay, floating combat text,
|
||||||
|
* DPS/HPS meter, buff bar, battleground score HUD, combat log,
|
||||||
|
* threat window, BG scoreboard.
|
||||||
|
*/
|
||||||
|
class CombatUI {
|
||||||
|
public:
|
||||||
|
CombatUI() = default;
|
||||||
|
|
||||||
|
// ---- Callback type for spell icon lookup (stays in GameScreen) ----
|
||||||
|
using SpellIconFn = std::function<VkDescriptorSet(uint32_t spellId, pipeline::AssetManager*)>;
|
||||||
|
|
||||||
|
// ---- Toggle booleans (written by slash commands / escape handler / settings) ----
|
||||||
|
bool showCombatLog_ = false;
|
||||||
|
bool showThreatWindow_ = false;
|
||||||
|
bool showBgScoreboard_ = false;
|
||||||
|
|
||||||
|
// ---- Raid Warning / Boss Emote big-text overlay ----
|
||||||
|
struct RaidWarnEntry {
|
||||||
|
std::string text;
|
||||||
|
float age = 0.0f;
|
||||||
|
bool isBossEmote = false;
|
||||||
|
static constexpr float LIFETIME = 5.0f;
|
||||||
|
};
|
||||||
|
std::vector<RaidWarnEntry> raidWarnEntries_;
|
||||||
|
bool raidWarnCallbackSet_ = false;
|
||||||
|
size_t raidWarnChatSeenCount_ = 0;
|
||||||
|
|
||||||
|
// ---- DPS meter state ----
|
||||||
|
float dpsCombatAge_ = 0.0f;
|
||||||
|
bool dpsWasInCombat_ = false;
|
||||||
|
float dpsEncounterDamage_ = 0.0f;
|
||||||
|
float dpsEncounterHeal_ = 0.0f;
|
||||||
|
size_t dpsLogSeenCount_ = 0;
|
||||||
|
|
||||||
|
// ---- Public render methods ----
|
||||||
|
void renderCastBar(game::GameHandler& gameHandler, SpellIconFn getSpellIcon);
|
||||||
|
void renderCooldownTracker(game::GameHandler& gameHandler,
|
||||||
|
const SettingsPanel& settings,
|
||||||
|
SpellIconFn getSpellIcon);
|
||||||
|
void renderRaidWarningOverlay(game::GameHandler& gameHandler);
|
||||||
|
void renderCombatText(game::GameHandler& gameHandler);
|
||||||
|
void renderDPSMeter(game::GameHandler& gameHandler,
|
||||||
|
const SettingsPanel& settings);
|
||||||
|
void renderBuffBar(game::GameHandler& gameHandler,
|
||||||
|
SpellbookScreen& spellbookScreen,
|
||||||
|
SpellIconFn getSpellIcon);
|
||||||
|
void renderBattlegroundScore(game::GameHandler& gameHandler);
|
||||||
|
void renderCombatLog(game::GameHandler& gameHandler,
|
||||||
|
SpellbookScreen& spellbookScreen);
|
||||||
|
void renderThreatWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderBgScoreboard(game::GameHandler& gameHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
71
include/ui/dialog_manager.hpp
Normal file
71
include/ui/dialog_manager.hpp
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace game { class GameHandler; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class ChatPanel;
|
||||||
|
class InventoryScreen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog / popup overlay manager
|
||||||
|
*
|
||||||
|
* Owns all yes/no popup rendering:
|
||||||
|
* group invite, duel request, duel countdown, loot roll, trade request,
|
||||||
|
* trade window, summon request, shared quest, item text, guild invite,
|
||||||
|
* ready check, BG invite, BF manager invite, LFG proposal, LFG role check,
|
||||||
|
* resurrect, talent wipe confirm, pet unlearn confirm.
|
||||||
|
*/
|
||||||
|
class DialogManager {
|
||||||
|
public:
|
||||||
|
DialogManager() = default;
|
||||||
|
|
||||||
|
/// Render "early" dialogs (group invite through LFG role check)
|
||||||
|
/// called in render() before guild roster / social frame
|
||||||
|
void renderDialogs(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
|
||||||
|
/// Render "late" dialogs (resurrect, talent wipe, pet unlearn)
|
||||||
|
/// called in render() after reclaim corpse button
|
||||||
|
void renderLateDialogs(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Common ImGui window flags for popup dialogs
|
||||||
|
static constexpr ImGuiWindowFlags kDialogFlags =
|
||||||
|
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;
|
||||||
|
|
||||||
|
// ---- LFG role state ----
|
||||||
|
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
|
||||||
|
|
||||||
|
// ---- Individual dialog renderers ----
|
||||||
|
void renderGroupInvitePopup(game::GameHandler& gameHandler);
|
||||||
|
void renderDuelRequestPopup(game::GameHandler& gameHandler);
|
||||||
|
void renderDuelCountdown(game::GameHandler& gameHandler);
|
||||||
|
void renderItemTextWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderSharedQuestPopup(game::GameHandler& gameHandler);
|
||||||
|
void renderSummonRequestPopup(game::GameHandler& gameHandler);
|
||||||
|
void renderTradeRequestPopup(game::GameHandler& gameHandler);
|
||||||
|
void renderTradeWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderLootRollPopup(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderGuildInvitePopup(game::GameHandler& gameHandler);
|
||||||
|
void renderReadyCheckPopup(game::GameHandler& gameHandler);
|
||||||
|
void renderBgInvitePopup(game::GameHandler& gameHandler);
|
||||||
|
void renderBfMgrInvitePopup(game::GameHandler& gameHandler);
|
||||||
|
void renderLfgProposalPopup(game::GameHandler& gameHandler);
|
||||||
|
void renderLfgRoleCheckPopup(game::GameHandler& gameHandler);
|
||||||
|
void renderResurrectDialog(game::GameHandler& gameHandler);
|
||||||
|
void renderTalentWipeConfirmDialog(game::GameHandler& gameHandler);
|
||||||
|
void renderPetUnlearnConfirmDialog(game::GameHandler& gameHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
|
|
@ -9,6 +9,14 @@
|
||||||
#include "ui/spellbook_screen.hpp"
|
#include "ui/spellbook_screen.hpp"
|
||||||
#include "ui/talent_screen.hpp"
|
#include "ui/talent_screen.hpp"
|
||||||
#include "ui/keybinding_manager.hpp"
|
#include "ui/keybinding_manager.hpp"
|
||||||
|
#include "ui/chat_panel.hpp"
|
||||||
|
#include "ui/toast_manager.hpp"
|
||||||
|
#include "ui/dialog_manager.hpp"
|
||||||
|
#include "ui/settings_panel.hpp"
|
||||||
|
#include "ui/combat_ui.hpp"
|
||||||
|
#include "ui/social_panel.hpp"
|
||||||
|
#include "ui/action_bar_panel.hpp"
|
||||||
|
#include "ui/window_manager.hpp"
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -37,82 +45,46 @@ public:
|
||||||
/**
|
/**
|
||||||
* Check if chat input is active
|
* Check if chat input is active
|
||||||
*/
|
*/
|
||||||
bool isChatInputActive() const { return chatInputActive; }
|
bool isChatInputActive() const { return chatPanel_.isChatInputActive(); }
|
||||||
|
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void applyAudioVolumes(rendering::Renderer* renderer);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Chat state
|
// Chat panel (extracted from GameScreen — owns all chat state and rendering)
|
||||||
char chatInputBuffer[512] = "";
|
ChatPanel chatPanel_;
|
||||||
char whisperTargetBuffer[256] = "";
|
|
||||||
bool chatInputActive = false;
|
|
||||||
int selectedChatType = 0; // 0=SAY, 1=YELL, 2=PARTY, 3=GUILD, 4=WHISPER, ..., 10=CHANNEL
|
|
||||||
int lastChatType = 0; // Track chat type changes
|
|
||||||
int selectedChannelIdx = 0; // Index into joinedChannels_ when selectedChatType==10
|
|
||||||
bool chatInputMoveCursorToEnd = false;
|
|
||||||
|
|
||||||
// Chat sent-message history (Up/Down arrow recall)
|
// Toast manager (extracted from GameScreen — owns all toast/notification state and rendering)
|
||||||
std::vector<std::string> chatSentHistory_;
|
ToastManager toastManager_;
|
||||||
int chatHistoryIdx_ = -1; // -1 = not browsing history
|
|
||||||
|
|
||||||
// Set to true by /stopmacro; checked in executeMacroText to halt remaining commands.
|
// Dialog manager (extracted from GameScreen — owns all popup/dialog rendering)
|
||||||
bool macroStopped_ = false;
|
DialogManager dialogManager_;
|
||||||
|
|
||||||
// Action bar error-flash: spellId → wall-clock time (seconds) when the flash ends.
|
// Settings panel (extracted from GameScreen — owns all settings UI and config state)
|
||||||
// Populated by the SpellCastFailedCallback; queried during action bar button rendering.
|
SettingsPanel settingsPanel_;
|
||||||
std::unordered_map<uint32_t, float> actionFlashEndTimes_;
|
|
||||||
|
|
||||||
// Cached game handler for input callbacks (set each frame in render)
|
// Combat UI (extracted from GameScreen — owns all combat overlay rendering)
|
||||||
game::GameHandler* cachedGameHandler_ = nullptr;
|
CombatUI combatUI_;
|
||||||
|
|
||||||
// Tab-completion state for slash commands and player names
|
// Social panel (extracted from GameScreen — owns all social/group UI rendering)
|
||||||
std::string chatTabPrefix_; // prefix captured on first Tab press
|
SocialPanel socialPanel_;
|
||||||
std::vector<std::string> chatTabMatches_; // matching command list
|
|
||||||
int chatTabMatchIdx_ = -1; // active match index (-1 = inactive)
|
|
||||||
|
|
||||||
// Mention notification: plays a sound when the player's name appears in chat
|
// Action bar panel (extracted from GameScreen — owns action/stance/bag/xp/rep bars)
|
||||||
size_t chatMentionSeenCount_ = 0; // how many messages have been scanned for mentions
|
ActionBarPanel actionBarPanel_;
|
||||||
|
|
||||||
// Chat tabs
|
// Window manager (extracted from GameScreen — owns NPC windows, popups, overlays)
|
||||||
int activeChatTab_ = 0;
|
WindowManager windowManager_;
|
||||||
struct ChatTab {
|
|
||||||
std::string name;
|
|
||||||
uint64_t typeMask; // bitmask of ChatType values to show (64-bit: types go up to 84)
|
|
||||||
};
|
|
||||||
std::vector<ChatTab> chatTabs_;
|
|
||||||
std::vector<int> chatTabUnread_; // unread message count per tab (0 = none)
|
|
||||||
size_t chatTabSeenCount_ = 0; // how many history messages have been processed
|
|
||||||
void initChatTabs();
|
|
||||||
bool shouldShowMessage(const game::MessageChatData& msg, int tabIndex) const;
|
|
||||||
|
|
||||||
// UI state
|
// UI state
|
||||||
bool showEntityWindow = false;
|
bool showEntityWindow = false;
|
||||||
bool showChatWindow = true;
|
bool showChatWindow = true;
|
||||||
bool showMinimap_ = true; // M key toggles minimap
|
bool showMinimap_ = true; // M key toggles minimap
|
||||||
bool showNameplates_ = true; // V key toggles enemy/NPC nameplates
|
bool showNameplates_ = true; // V key toggles enemy/NPC nameplates
|
||||||
bool showFriendlyNameplates_ = true; // Shift+V toggles friendly player nameplates
|
|
||||||
float nameplateScale_ = 1.0f; // Scale multiplier for nameplate bar dimensions
|
|
||||||
uint64_t nameplateCtxGuid_ = 0; // GUID of nameplate right-clicked (0 = none)
|
uint64_t nameplateCtxGuid_ = 0; // GUID of nameplate right-clicked (0 = none)
|
||||||
ImVec2 nameplateCtxPos_{}; // Screen position of nameplate right-click
|
ImVec2 nameplateCtxPos_{}; // Screen position of nameplate right-click
|
||||||
uint32_t lastPlayerHp_ = 0; // Previous frame HP for damage flash detection
|
uint32_t lastPlayerHp_ = 0; // Previous frame HP for damage flash detection
|
||||||
float damageFlashAlpha_ = 0.0f; // Screen edge flash intensity (fades to 0)
|
float damageFlashAlpha_ = 0.0f; // Screen edge flash intensity (fades to 0)
|
||||||
bool damageFlashEnabled_ = true;
|
|
||||||
bool lowHealthVignetteEnabled_ = true; // Persistent pulsing red vignette below 20% HP
|
|
||||||
float levelUpFlashAlpha_ = 0.0f; // Golden level-up burst effect (fades to 0)
|
|
||||||
uint32_t levelUpDisplayLevel_ = 0; // Level shown in level-up text
|
|
||||||
|
|
||||||
// Raid Warning / Boss Emote big-text overlay (center-screen, fades after 5s)
|
|
||||||
struct RaidWarnEntry {
|
|
||||||
std::string text;
|
|
||||||
float age = 0.0f;
|
|
||||||
bool isBossEmote = false; // true = amber, false (raid warning) = red+yellow
|
|
||||||
static constexpr float LIFETIME = 5.0f;
|
|
||||||
};
|
|
||||||
std::vector<RaidWarnEntry> raidWarnEntries_;
|
|
||||||
bool raidWarnCallbackSet_ = false;
|
|
||||||
size_t raidWarnChatSeenCount_ = 0; // index into chat history for unread scan
|
|
||||||
|
|
||||||
// UIErrorsFrame: WoW-style center-bottom error messages (spell fails, out of range, etc.)
|
// UIErrorsFrame: WoW-style center-bottom error messages (spell fails, out of range, etc.)
|
||||||
struct UIErrorEntry { std::string text; float age = 0.0f; };
|
struct UIErrorEntry { std::string text; float age = 0.0f; };
|
||||||
|
|
@ -120,161 +92,15 @@ private:
|
||||||
bool uiErrorCallbackSet_ = false;
|
bool uiErrorCallbackSet_ = false;
|
||||||
static constexpr float kUIErrorLifetime = 2.5f;
|
static constexpr float kUIErrorLifetime = 2.5f;
|
||||||
bool castFailedCallbackSet_ = false;
|
bool castFailedCallbackSet_ = false;
|
||||||
static constexpr float kActionFlashDuration = 0.5f; // seconds for error-red overlay to fade
|
|
||||||
|
|
||||||
// Reputation change toast: brief colored slide-in below minimap
|
|
||||||
struct RepToastEntry { std::string factionName; int32_t delta = 0; int32_t standing = 0; float age = 0.0f; };
|
|
||||||
std::vector<RepToastEntry> repToasts_;
|
|
||||||
bool repChangeCallbackSet_ = false;
|
|
||||||
static constexpr float kRepToastLifetime = 3.5f;
|
|
||||||
|
|
||||||
// Quest completion toast: slide-in when a quest is turned in
|
|
||||||
struct QuestCompleteToastEntry { uint32_t questId = 0; std::string title; float age = 0.0f; };
|
|
||||||
std::vector<QuestCompleteToastEntry> questCompleteToasts_;
|
|
||||||
bool questCompleteCallbackSet_ = false;
|
|
||||||
static constexpr float kQuestCompleteToastLifetime = 4.0f;
|
|
||||||
|
|
||||||
// Zone entry toast: brief banner when entering a new zone
|
|
||||||
struct ZoneToastEntry { std::string zoneName; float age = 0.0f; };
|
|
||||||
std::vector<ZoneToastEntry> zoneToasts_;
|
|
||||||
|
|
||||||
struct AreaTriggerToast { std::string text; float age = 0.0f; };
|
|
||||||
std::vector<AreaTriggerToast> areaTriggerToasts_;
|
|
||||||
void renderAreaTriggerToasts(float deltaTime, game::GameHandler& gameHandler);
|
|
||||||
std::string lastKnownZone_;
|
|
||||||
static constexpr float kZoneToastLifetime = 3.0f;
|
|
||||||
|
|
||||||
// Death screen: elapsed time since the death dialog first appeared
|
|
||||||
float deathElapsed_ = 0.0f;
|
|
||||||
bool deathTimerRunning_ = false;
|
|
||||||
// WoW forces release after ~6 minutes; show countdown until then
|
|
||||||
static constexpr float kForcedReleaseSec = 360.0f;
|
|
||||||
void renderZoneToasts(float deltaTime);
|
|
||||||
bool showPlayerInfo = false;
|
bool showPlayerInfo = false;
|
||||||
bool showSocialFrame_ = false; // O key toggles social/friends list
|
|
||||||
bool showGuildRoster_ = false;
|
|
||||||
bool showRaidFrames_ = true; // F key toggles raid/party frames
|
|
||||||
bool showWorldMap_ = false; // W key toggles world map
|
bool showWorldMap_ = false; // W key toggles world map
|
||||||
std::string selectedGuildMember_;
|
|
||||||
bool showGuildNoteEdit_ = false;
|
|
||||||
bool editingOfficerNote_ = false;
|
|
||||||
char guildNoteEditBuffer_[256] = {0};
|
|
||||||
int guildRosterTab_ = 0; // 0=Roster, 1=Guild Info
|
|
||||||
char guildMotdEditBuffer_[256] = {0};
|
|
||||||
bool showMotdEdit_ = false;
|
|
||||||
char petitionNameBuffer_[64] = {0};
|
|
||||||
char addRankNameBuffer_[64] = {0};
|
|
||||||
bool showAddRankModal_ = false;
|
|
||||||
bool refocusChatInput = false;
|
|
||||||
bool vendorBagsOpened_ = false; // Track if bags were auto-opened for current vendor session
|
|
||||||
bool chatScrolledUp_ = false; // true when user has scrolled above the latest messages
|
|
||||||
bool chatForceScrollToBottom_ = false; // set to true to jump to bottom next frame
|
|
||||||
bool chatWindowLocked = true;
|
|
||||||
ImVec2 chatWindowPos_ = ImVec2(0.0f, 0.0f);
|
|
||||||
bool chatWindowPosInit_ = false;
|
|
||||||
ImVec2 questTrackerPos_ = ImVec2(-1.0f, -1.0f); // <0 = use default
|
ImVec2 questTrackerPos_ = ImVec2(-1.0f, -1.0f); // <0 = use default
|
||||||
ImVec2 questTrackerSize_ = ImVec2(220.0f, 200.0f); // saved size
|
ImVec2 questTrackerSize_ = ImVec2(220.0f, 200.0f); // saved size
|
||||||
float questTrackerRightOffset_ = -1.0f; // pixels from right edge; <0 = use default
|
float questTrackerRightOffset_ = -1.0f; // pixels from right edge; <0 = use default
|
||||||
bool questTrackerPosInit_ = false;
|
bool questTrackerPosInit_ = false;
|
||||||
bool showEscapeMenu = false;
|
|
||||||
bool showEscapeSettingsNotice = false;
|
|
||||||
bool showSettingsWindow = false;
|
|
||||||
bool settingsInit = false;
|
|
||||||
bool pendingFullscreen = false;
|
|
||||||
bool pendingVsync = false;
|
|
||||||
int pendingResIndex = 0;
|
|
||||||
bool pendingShadows = true;
|
|
||||||
float pendingShadowDistance = 300.0f;
|
|
||||||
bool pendingWaterRefraction = true;
|
|
||||||
int pendingBrightness = 50; // 0-100, maps to 0.0-2.0 (50 = 1.0 default)
|
|
||||||
int pendingMasterVolume = 100;
|
|
||||||
int pendingMusicVolume = 30;
|
|
||||||
int pendingAmbientVolume = 100;
|
|
||||||
int pendingUiVolume = 100;
|
|
||||||
int pendingCombatVolume = 100;
|
|
||||||
int pendingSpellVolume = 100;
|
|
||||||
int pendingMovementVolume = 100;
|
|
||||||
int pendingFootstepVolume = 100;
|
|
||||||
int pendingNpcVoiceVolume = 100;
|
|
||||||
int pendingMountVolume = 100;
|
|
||||||
int pendingActivityVolume = 100;
|
|
||||||
float pendingMouseSensitivity = 0.2f;
|
|
||||||
bool pendingInvertMouse = false;
|
|
||||||
bool pendingExtendedZoom = false;
|
|
||||||
float pendingCameraStiffness = 30.0f; // Camera smooth speed (higher = tighter, less sway)
|
|
||||||
float pendingPivotHeight = 1.6f; // Camera pivot height above feet (lower = less detached feel)
|
|
||||||
float pendingFov = 70.0f; // degrees, default matches WoW's ~70° horizontal FOV
|
|
||||||
int pendingUiOpacity = 65;
|
|
||||||
bool pendingMinimapRotate = false;
|
|
||||||
bool pendingMinimapSquare = false;
|
|
||||||
bool pendingMinimapNpcDots = false;
|
|
||||||
bool pendingShowLatencyMeter = true;
|
|
||||||
bool pendingSeparateBags = true;
|
|
||||||
bool pendingShowKeyring = true;
|
|
||||||
bool pendingAutoLoot = false;
|
|
||||||
bool pendingAutoSellGrey = false;
|
|
||||||
bool pendingAutoRepair = false;
|
|
||||||
|
|
||||||
// Keybinding customization
|
|
||||||
int pendingRebindAction = -1; // -1 = not rebinding, otherwise action index
|
|
||||||
bool awaitingKeyPress = false;
|
|
||||||
// Macro editor popup state
|
|
||||||
uint32_t macroEditorId_ = 0; // macro index being edited
|
|
||||||
bool macroEditorOpen_ = false; // deferred OpenPopup flag
|
|
||||||
char macroEditorBuf_[256] = {}; // edit buffer
|
|
||||||
bool pendingUseOriginalSoundtrack = true;
|
|
||||||
bool pendingShowActionBar2 = true; // Show second action bar above main bar
|
|
||||||
float pendingActionBarScale = 1.0f; // Multiplier for action bar slot size (0.5–1.5)
|
|
||||||
float pendingActionBar2OffsetX = 0.0f; // Horizontal offset from default center position
|
|
||||||
float pendingActionBar2OffsetY = 0.0f; // Vertical offset from default (above bar 1)
|
|
||||||
bool pendingShowRightBar = false; // Right-edge vertical action bar (bar 3, slots 24-35)
|
|
||||||
bool pendingShowLeftBar = false; // Left-edge vertical action bar (bar 4, slots 36-47)
|
|
||||||
float pendingRightBarOffsetY = 0.0f; // Vertical offset from screen center
|
|
||||||
float pendingLeftBarOffsetY = 0.0f; // Vertical offset from screen center
|
|
||||||
int pendingGroundClutterDensity = 100;
|
|
||||||
int pendingAntiAliasing = 0; // 0=Off, 1=2x, 2=4x, 3=8x
|
|
||||||
bool pendingFXAA = false; // FXAA post-process (combinable with MSAA)
|
|
||||||
bool pendingNormalMapping = true; // on by default
|
|
||||||
float pendingNormalMapStrength = 0.8f; // 0.0-2.0
|
|
||||||
bool pendingPOM = true; // on by default
|
|
||||||
int pendingPOMQuality = 1; // 0=Low(16), 1=Medium(32), 2=High(64)
|
|
||||||
bool pendingFSR = false;
|
|
||||||
int pendingUpscalingMode = 0; // 0=Off, 1=FSR1, 2=FSR3
|
|
||||||
int pendingFSRQuality = 3; // 0=UltraQuality, 1=Quality, 2=Balanced, 3=Native(100%)
|
|
||||||
float pendingFSRSharpness = 1.6f;
|
|
||||||
float pendingFSR2JitterSign = 0.38f;
|
|
||||||
float pendingFSR2MotionVecScaleX = 1.0f;
|
|
||||||
float pendingFSR2MotionVecScaleY = 1.0f;
|
|
||||||
bool pendingAMDFramegen = false;
|
|
||||||
bool fsrSettingsApplied_ = false;
|
|
||||||
|
|
||||||
// Graphics quality presets
|
|
||||||
enum class GraphicsPreset : int {
|
|
||||||
CUSTOM = 0,
|
|
||||||
LOW = 1,
|
|
||||||
MEDIUM = 2,
|
|
||||||
HIGH = 3,
|
|
||||||
ULTRA = 4
|
|
||||||
};
|
|
||||||
GraphicsPreset currentGraphicsPreset = GraphicsPreset::CUSTOM;
|
|
||||||
GraphicsPreset pendingGraphicsPreset = GraphicsPreset::CUSTOM;
|
|
||||||
|
|
||||||
// UI element transparency (0.0 = fully transparent, 1.0 = fully opaque)
|
|
||||||
float uiOpacity_ = 0.65f;
|
|
||||||
bool minimapRotate_ = false;
|
|
||||||
bool minimapSquare_ = false;
|
|
||||||
bool minimapNpcDots_ = false;
|
|
||||||
bool showLatencyMeter_ = true; // Show server latency indicator
|
|
||||||
bool minimapSettingsApplied_ = false;
|
|
||||||
bool volumeSettingsApplied_ = false; // True once saved volume settings applied to audio managers
|
|
||||||
bool msaaSettingsApplied_ = false; // True once saved MSAA setting applied to renderer
|
|
||||||
bool fxaaSettingsApplied_ = false; // True once saved FXAA setting applied to renderer
|
|
||||||
bool waterRefractionApplied_ = false;
|
|
||||||
bool normalMapSettingsApplied_ = false; // True once saved normal map/POM settings applied
|
|
||||||
|
|
||||||
// Mute state: mute bypasses master volume without touching slider values
|
|
||||||
bool soundMuted_ = false;
|
|
||||||
float preMuteVolume_ = 1.0f; // AudioEngine master volume before muting
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render player info window
|
* Render player info window
|
||||||
|
|
@ -286,27 +112,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void renderEntityList(game::GameHandler& gameHandler);
|
void renderEntityList(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
/**
|
|
||||||
* Render chat window
|
|
||||||
*/
|
|
||||||
void renderChatWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send chat message
|
|
||||||
*/
|
|
||||||
void sendChatMessage(game::GameHandler& gameHandler);
|
|
||||||
void executeMacroText(game::GameHandler& gameHandler, const std::string& macroText);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get chat type name
|
|
||||||
*/
|
|
||||||
const char* getChatTypeName(game::ChatType type) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get chat type color
|
|
||||||
*/
|
|
||||||
ImVec4 getChatTypeColor(game::ChatType type) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render player unit frame (top-left)
|
* Render player unit frame (top-left)
|
||||||
*/
|
*/
|
||||||
|
|
@ -339,80 +144,13 @@ private:
|
||||||
*/
|
*/
|
||||||
void updateCharacterTextures(game::Inventory& inventory);
|
void updateCharacterTextures(game::Inventory& inventory);
|
||||||
|
|
||||||
// ---- New UI renders ----
|
|
||||||
void renderActionBar(game::GameHandler& gameHandler);
|
|
||||||
void renderStanceBar(game::GameHandler& gameHandler);
|
|
||||||
void renderBagBar(game::GameHandler& gameHandler);
|
|
||||||
void renderXpBar(game::GameHandler& gameHandler);
|
|
||||||
void renderRepBar(game::GameHandler& gameHandler);
|
|
||||||
void renderCastBar(game::GameHandler& gameHandler);
|
|
||||||
void renderMirrorTimers(game::GameHandler& gameHandler);
|
void renderMirrorTimers(game::GameHandler& gameHandler);
|
||||||
void renderCooldownTracker(game::GameHandler& gameHandler);
|
|
||||||
void renderCombatText(game::GameHandler& gameHandler);
|
|
||||||
void renderRaidWarningOverlay(game::GameHandler& gameHandler);
|
|
||||||
void renderPartyFrames(game::GameHandler& gameHandler);
|
|
||||||
void renderBossFrames(game::GameHandler& gameHandler);
|
|
||||||
void renderUIErrors(game::GameHandler& gameHandler, float deltaTime);
|
void renderUIErrors(game::GameHandler& gameHandler, float deltaTime);
|
||||||
void renderRepToasts(float deltaTime);
|
|
||||||
void renderQuestCompleteToasts(float deltaTime);
|
|
||||||
void renderGroupInvitePopup(game::GameHandler& gameHandler);
|
|
||||||
void renderDuelRequestPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderDuelCountdown(game::GameHandler& gameHandler);
|
|
||||||
void renderLootRollPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderTradeRequestPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderTradeWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderSummonRequestPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderSharedQuestPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderItemTextWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderBuffBar(game::GameHandler& gameHandler);
|
|
||||||
void renderSocialFrame(game::GameHandler& gameHandler);
|
|
||||||
void renderLootWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderGossipWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderQuestDetailsWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderQuestRequestItemsWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderQuestOfferRewardWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderVendorWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderTrainerWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderBarberShopWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderStableWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderTaxiWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderLogoutCountdown(game::GameHandler& gameHandler);
|
|
||||||
void renderDeathScreen(game::GameHandler& gameHandler);
|
|
||||||
void renderReclaimCorpseButton(game::GameHandler& gameHandler);
|
|
||||||
void renderResurrectDialog(game::GameHandler& gameHandler);
|
|
||||||
void renderTalentWipeConfirmDialog(game::GameHandler& gameHandler);
|
|
||||||
void renderPetUnlearnConfirmDialog(game::GameHandler& gameHandler);
|
|
||||||
void renderEscapeMenu();
|
|
||||||
void renderSettingsWindow();
|
|
||||||
void renderSettingsAudioTab();
|
|
||||||
void renderSettingsChatTab();
|
|
||||||
void renderSettingsAboutTab();
|
|
||||||
void renderSettingsInterfaceTab();
|
|
||||||
void renderSettingsGameplayTab();
|
|
||||||
void renderSettingsControlsTab();
|
|
||||||
void applyGraphicsPreset(GraphicsPreset preset);
|
|
||||||
void updateGraphicsPresetFromCurrentSettings();
|
|
||||||
void renderQuestMarkers(game::GameHandler& gameHandler);
|
void renderQuestMarkers(game::GameHandler& gameHandler);
|
||||||
void renderMinimapMarkers(game::GameHandler& gameHandler);
|
void renderMinimapMarkers(game::GameHandler& gameHandler);
|
||||||
void renderQuestObjectiveTracker(game::GameHandler& gameHandler);
|
void renderQuestObjectiveTracker(game::GameHandler& gameHandler);
|
||||||
void renderGuildRoster(game::GameHandler& gameHandler);
|
|
||||||
void renderGuildInvitePopup(game::GameHandler& gameHandler);
|
|
||||||
void renderReadyCheckPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderBgInvitePopup(game::GameHandler& gameHandler);
|
|
||||||
void renderBfMgrInvitePopup(game::GameHandler& gameHandler);
|
|
||||||
void renderLfgProposalPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderLfgRoleCheckPopup(game::GameHandler& gameHandler);
|
|
||||||
void renderChatBubbles(game::GameHandler& gameHandler);
|
|
||||||
void renderMailWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderMailComposeWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderBankWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderGuildBankWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderAuctionHouseWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderDungeonFinderWindow(game::GameHandler& gameHandler);
|
|
||||||
void renderInstanceLockouts(game::GameHandler& gameHandler);
|
|
||||||
void renderNameplates(game::GameHandler& gameHandler);
|
void renderNameplates(game::GameHandler& gameHandler);
|
||||||
void renderBattlegroundScore(game::GameHandler& gameHandler);
|
|
||||||
void renderDPSMeter(game::GameHandler& gameHandler);
|
|
||||||
void renderDurabilityWarning(game::GameHandler& gameHandler);
|
void renderDurabilityWarning(game::GameHandler& gameHandler);
|
||||||
void takeScreenshot(game::GameHandler& gameHandler);
|
void takeScreenshot(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
|
@ -437,298 +175,29 @@ private:
|
||||||
bool spellIconDbLoaded_ = false;
|
bool spellIconDbLoaded_ = false;
|
||||||
VkDescriptorSet getSpellIcon(uint32_t spellId, pipeline::AssetManager* am);
|
VkDescriptorSet getSpellIcon(uint32_t spellId, pipeline::AssetManager* am);
|
||||||
|
|
||||||
// ItemExtendedCost.dbc cache: extendedCostId -> cost details
|
|
||||||
struct ExtendedCostEntry {
|
|
||||||
uint32_t honorPoints = 0;
|
|
||||||
uint32_t arenaPoints = 0;
|
|
||||||
uint32_t itemId[5] = {};
|
|
||||||
uint32_t itemCount[5] = {};
|
|
||||||
};
|
|
||||||
std::unordered_map<uint32_t, ExtendedCostEntry> extendedCostCache_;
|
|
||||||
bool extendedCostDbLoaded_ = false;
|
|
||||||
void loadExtendedCostDBC();
|
|
||||||
std::string formatExtendedCost(uint32_t extendedCostId, game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Macro cooldown cache: maps macro ID → resolved primary spell ID (0 = no spell found)
|
|
||||||
std::unordered_map<uint32_t, uint32_t> macroPrimarySpellCache_;
|
|
||||||
size_t macroCacheSpellCount_ = 0; // invalidates cache when spell list changes
|
|
||||||
uint32_t resolveMacroPrimarySpellId(uint32_t macroId, game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Death Knight rune bar: client-predicted fill (0.0=depleted, 1.0=ready) for smooth animation
|
// Death Knight rune bar: client-predicted fill (0.0=depleted, 1.0=ready) for smooth animation
|
||||||
float runeClientFill_[6] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
float runeClientFill_[6] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
|
||||||
// Action bar drag state (-1 = not dragging)
|
|
||||||
int actionBarDragSlot_ = -1;
|
|
||||||
VkDescriptorSet actionBarDragIcon_ = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
// Bag bar state
|
|
||||||
VkDescriptorSet backpackIconTexture_ = VK_NULL_HANDLE;
|
|
||||||
VkDescriptorSet emptyBagSlotTexture_ = VK_NULL_HANDLE;
|
|
||||||
int bagBarPickedSlot_ = -1; // Visual drag in progress (-1 = none)
|
|
||||||
int bagBarDragSource_ = -1; // Mouse pressed on this slot, waiting for drag or click (-1 = none)
|
|
||||||
|
|
||||||
// Who Results window
|
|
||||||
bool showWhoWindow_ = false;
|
|
||||||
void renderWhoWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Combat Log window
|
|
||||||
bool showCombatLog_ = false;
|
|
||||||
void renderCombatLog(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Instance Lockouts window
|
|
||||||
bool showInstanceLockouts_ = false;
|
|
||||||
|
|
||||||
// Dungeon Finder state
|
|
||||||
bool showDungeonFinder_ = false;
|
|
||||||
|
|
||||||
// Achievements window
|
|
||||||
bool showAchievementWindow_ = false;
|
|
||||||
char achievementSearchBuf_[128] = {};
|
|
||||||
void renderAchievementWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Skills / Professions window (K key)
|
|
||||||
bool showSkillsWindow_ = false;
|
|
||||||
void renderSkillsWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Titles window
|
|
||||||
bool showTitlesWindow_ = false;
|
|
||||||
void renderTitlesWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Equipment Set Manager window
|
|
||||||
bool showEquipSetWindow_ = false;
|
|
||||||
void renderEquipSetWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// GM Ticket window
|
|
||||||
bool showGmTicketWindow_ = false;
|
|
||||||
bool gmTicketWindowWasOpen_ = false; ///< Previous frame state; used to fire one-shot query
|
|
||||||
char gmTicketBuf_[2048] = {};
|
|
||||||
void renderGmTicketWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Pet rename modal (triggered from pet frame context menu)
|
// Pet rename modal (triggered from pet frame context menu)
|
||||||
bool petRenameOpen_ = false;
|
bool petRenameOpen_ = false;
|
||||||
char petRenameBuf_[16] = {};
|
char petRenameBuf_[16] = {};
|
||||||
|
|
||||||
// Inspect window
|
|
||||||
bool showInspectWindow_ = false;
|
|
||||||
void renderInspectWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Readable text window (books / scrolls / notes)
|
|
||||||
bool showBookWindow_ = false;
|
|
||||||
int bookCurrentPage_ = 0;
|
|
||||||
void renderBookWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Threat window
|
|
||||||
bool showThreatWindow_ = false;
|
|
||||||
void renderThreatWindow(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// BG scoreboard window
|
|
||||||
bool showBgScoreboard_ = false;
|
|
||||||
void renderBgScoreboard(game::GameHandler& gameHandler);
|
|
||||||
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
|
|
||||||
uint32_t lfgSelectedDungeon_ = 861; // default: random dungeon (entry 861 = Random Dungeon WotLK)
|
|
||||||
|
|
||||||
// Chat settings
|
|
||||||
bool chatShowTimestamps_ = false;
|
|
||||||
int chatFontSize_ = 1; // 0=small, 1=medium, 2=large
|
|
||||||
bool chatAutoJoinGeneral_ = true;
|
|
||||||
bool chatAutoJoinTrade_ = true;
|
|
||||||
bool chatAutoJoinLocalDefense_ = true;
|
|
||||||
bool chatAutoJoinLFG_ = true;
|
|
||||||
bool chatAutoJoinLocal_ = true;
|
|
||||||
|
|
||||||
// Join channel input buffer
|
|
||||||
char joinChannelBuffer_[128] = "";
|
|
||||||
|
|
||||||
static std::string getSettingsPath();
|
|
||||||
|
|
||||||
// Gender placeholder replacement
|
|
||||||
std::string replaceGenderPlaceholders(const std::string& text, game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// Chat bubbles
|
|
||||||
struct ChatBubble {
|
|
||||||
uint64_t senderGuid = 0;
|
|
||||||
std::string message;
|
|
||||||
float timeRemaining = 0.0f;
|
|
||||||
float totalDuration = 0.0f;
|
|
||||||
bool isYell = false;
|
|
||||||
};
|
|
||||||
std::vector<ChatBubble> chatBubbles_;
|
|
||||||
bool chatBubbleCallbackSet_ = false;
|
|
||||||
bool levelUpCallbackSet_ = false;
|
|
||||||
bool achievementCallbackSet_ = false;
|
|
||||||
|
|
||||||
// Mail compose state
|
|
||||||
char mailRecipientBuffer_[256] = "";
|
|
||||||
char mailSubjectBuffer_[256] = "";
|
|
||||||
char mailBodyBuffer_[2048] = "";
|
|
||||||
int mailComposeMoney_[3] = {0, 0, 0}; // gold, silver, copper
|
|
||||||
|
|
||||||
// Vendor search filter
|
|
||||||
char vendorSearchFilter_[128] = "";
|
|
||||||
|
|
||||||
// Vendor purchase confirmation for expensive items
|
|
||||||
bool vendorConfirmOpen_ = false;
|
|
||||||
uint64_t vendorConfirmGuid_ = 0;
|
|
||||||
uint32_t vendorConfirmItemId_ = 0;
|
|
||||||
uint32_t vendorConfirmSlot_ = 0;
|
|
||||||
uint32_t vendorConfirmQty_ = 1;
|
|
||||||
uint32_t vendorConfirmPrice_ = 0;
|
|
||||||
std::string vendorConfirmItemName_;
|
|
||||||
|
|
||||||
// Barber shop UI state
|
|
||||||
int barberHairStyle_ = 0;
|
|
||||||
int barberHairColor_ = 0;
|
|
||||||
int barberFacialHair_ = 0;
|
|
||||||
int barberOrigHairStyle_ = 0;
|
|
||||||
int barberOrigHairColor_ = 0;
|
|
||||||
int barberOrigFacialHair_ = 0;
|
|
||||||
bool barberInitialized_ = false;
|
|
||||||
|
|
||||||
// Trainer search filter
|
|
||||||
char trainerSearchFilter_[128] = "";
|
|
||||||
|
|
||||||
// Auction house UI state
|
|
||||||
char auctionSearchName_[256] = "";
|
|
||||||
int auctionLevelMin_ = 0;
|
|
||||||
int auctionLevelMax_ = 0;
|
|
||||||
int auctionQuality_ = 0;
|
|
||||||
int auctionSellDuration_ = 2; // 0=12h, 1=24h, 2=48h
|
|
||||||
int auctionSellBid_[3] = {0, 0, 0}; // gold, silver, copper
|
|
||||||
int auctionSellBuyout_[3] = {0, 0, 0}; // gold, silver, copper
|
|
||||||
int auctionSelectedItem_ = -1;
|
|
||||||
int auctionSellSlotIndex_ = -1; // Selected backpack slot for selling
|
|
||||||
uint32_t auctionBrowseOffset_ = 0; // Pagination offset for browse results
|
|
||||||
int auctionItemClass_ = -1; // Item class filter (-1 = All)
|
|
||||||
int auctionItemSubClass_ = -1; // Item subclass filter (-1 = All)
|
|
||||||
bool auctionUsableOnly_ = false; // Filter to items usable by current class/level
|
|
||||||
|
|
||||||
// Guild bank money input
|
|
||||||
int guildBankMoneyInput_[3] = {0, 0, 0}; // gold, silver, copper
|
|
||||||
|
|
||||||
// Left-click targeting: distinguish click from camera drag
|
// Left-click targeting: distinguish click from camera drag
|
||||||
glm::vec2 leftClickPressPos_ = glm::vec2(0.0f);
|
glm::vec2 leftClickPressPos_ = glm::vec2(0.0f);
|
||||||
bool leftClickWasPress_ = false;
|
bool leftClickWasPress_ = false;
|
||||||
|
|
||||||
// Level-up ding animation
|
|
||||||
static constexpr float DING_DURATION = 4.0f;
|
|
||||||
float dingTimer_ = 0.0f;
|
|
||||||
uint32_t dingLevel_ = 0;
|
|
||||||
uint32_t dingHpDelta_ = 0;
|
|
||||||
uint32_t dingManaDelta_ = 0;
|
|
||||||
uint32_t dingStats_[5] = {}; // str/agi/sta/int/spi deltas
|
|
||||||
void renderDingEffect();
|
|
||||||
|
|
||||||
// Achievement toast banner
|
|
||||||
static constexpr float ACHIEVEMENT_TOAST_DURATION = 5.0f;
|
|
||||||
float achievementToastTimer_ = 0.0f;
|
|
||||||
uint32_t achievementToastId_ = 0;
|
|
||||||
std::string achievementToastName_;
|
|
||||||
void renderAchievementToast();
|
|
||||||
|
|
||||||
// Area discovery toast ("Discovered! <AreaName> +XP XP")
|
|
||||||
static constexpr float DISCOVERY_TOAST_DURATION = 4.0f;
|
|
||||||
float discoveryToastTimer_ = 0.0f;
|
|
||||||
std::string discoveryToastName_;
|
|
||||||
uint32_t discoveryToastXP_ = 0;
|
|
||||||
bool areaDiscoveryCallbackSet_ = false;
|
|
||||||
void renderDiscoveryToast();
|
|
||||||
|
|
||||||
// Whisper toast — brief overlay at screen top when a whisper arrives while chat is not focused
|
|
||||||
struct WhisperToastEntry {
|
|
||||||
std::string sender;
|
|
||||||
std::string preview; // first ~60 chars of message
|
|
||||||
float age = 0.0f;
|
|
||||||
};
|
|
||||||
static constexpr float WHISPER_TOAST_DURATION = 5.0f;
|
|
||||||
std::vector<WhisperToastEntry> whisperToasts_;
|
|
||||||
size_t whisperSeenCount_ = 0; // how many chat entries have been scanned for whispers
|
|
||||||
void renderWhisperToasts();
|
|
||||||
|
|
||||||
// Quest objective progress toast ("Quest: <ObjectiveName> X/Y")
|
|
||||||
struct QuestProgressToastEntry {
|
|
||||||
std::string questTitle;
|
|
||||||
std::string objectiveName;
|
|
||||||
uint32_t current = 0;
|
|
||||||
uint32_t required = 0;
|
|
||||||
float age = 0.0f;
|
|
||||||
};
|
|
||||||
static constexpr float QUEST_TOAST_DURATION = 4.0f;
|
|
||||||
std::vector<QuestProgressToastEntry> questToasts_;
|
|
||||||
bool questProgressCallbackSet_ = false;
|
|
||||||
void renderQuestProgressToasts();
|
|
||||||
|
|
||||||
// Nearby player level-up toast ("<Name> is now level X!")
|
|
||||||
struct PlayerLevelUpToastEntry {
|
|
||||||
uint64_t guid = 0;
|
|
||||||
std::string playerName; // resolved lazily at render time
|
|
||||||
uint32_t newLevel = 0;
|
|
||||||
float age = 0.0f;
|
|
||||||
};
|
|
||||||
static constexpr float PLAYER_LEVELUP_TOAST_DURATION = 4.0f;
|
|
||||||
std::vector<PlayerLevelUpToastEntry> playerLevelUpToasts_;
|
|
||||||
bool otherPlayerLevelUpCallbackSet_ = false;
|
|
||||||
void renderPlayerLevelUpToasts(game::GameHandler& gameHandler);
|
|
||||||
|
|
||||||
// PvP honor credit toast ("+N Honor" shown when an honorable kill is credited)
|
|
||||||
struct PvpHonorToastEntry {
|
|
||||||
uint32_t honor = 0;
|
|
||||||
uint32_t victimRank = 0; // 0 = unranked / not available
|
|
||||||
float age = 0.0f;
|
|
||||||
};
|
|
||||||
static constexpr float PVP_HONOR_TOAST_DURATION = 3.5f;
|
|
||||||
std::vector<PvpHonorToastEntry> pvpHonorToasts_;
|
|
||||||
bool pvpHonorCallbackSet_ = false;
|
|
||||||
void renderPvpHonorToasts();
|
|
||||||
|
|
||||||
// Item loot toast — quality-coloured popup when an item is received
|
|
||||||
struct ItemLootToastEntry {
|
|
||||||
uint32_t itemId = 0;
|
|
||||||
uint32_t count = 0;
|
|
||||||
uint32_t quality = 1; // 0=grey,1=white,2=green,3=blue,4=purple,5=orange
|
|
||||||
std::string name;
|
|
||||||
float age = 0.0f;
|
|
||||||
};
|
|
||||||
static constexpr float ITEM_LOOT_TOAST_DURATION = 3.0f;
|
|
||||||
std::vector<ItemLootToastEntry> itemLootToasts_;
|
|
||||||
bool itemLootCallbackSet_ = false;
|
|
||||||
void renderItemLootToasts();
|
|
||||||
|
|
||||||
// Resurrection flash: brief "You have been resurrected!" overlay on ghost→alive transition
|
|
||||||
float resurrectFlashTimer_ = 0.0f;
|
|
||||||
static constexpr float kResurrectFlashDuration = 3.0f;
|
|
||||||
bool ghostStateCallbackSet_ = false;
|
|
||||||
bool appearanceCallbackSet_ = false;
|
bool appearanceCallbackSet_ = false;
|
||||||
bool ghostOpacityStateKnown_ = false;
|
bool ghostOpacityStateKnown_ = false;
|
||||||
bool ghostOpacityLastState_ = false;
|
bool ghostOpacityLastState_ = false;
|
||||||
uint32_t ghostOpacityLastInstanceId_ = 0;
|
uint32_t ghostOpacityLastInstanceId_ = 0;
|
||||||
void renderResurrectFlash();
|
|
||||||
|
|
||||||
// Zone discovery text ("Entering: <ZoneName>")
|
|
||||||
static constexpr float ZONE_TEXT_DURATION = 5.0f;
|
|
||||||
float zoneTextTimer_ = 0.0f;
|
|
||||||
std::string zoneTextName_;
|
|
||||||
std::string lastKnownZoneName_;
|
|
||||||
uint32_t lastKnownWorldStateZoneId_ = 0;
|
|
||||||
void renderZoneText(game::GameHandler& gameHandler);
|
|
||||||
void renderWeatherOverlay(game::GameHandler& gameHandler);
|
void renderWeatherOverlay(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
// Cooldown tracker
|
|
||||||
bool showCooldownTracker_ = false;
|
|
||||||
|
|
||||||
// DPS / HPS meter
|
|
||||||
bool showDPSMeter_ = false;
|
|
||||||
float dpsCombatAge_ = 0.0f; // seconds in current combat (for accurate early-combat DPS)
|
|
||||||
bool dpsWasInCombat_ = false;
|
|
||||||
float dpsEncounterDamage_ = 0.0f; // total player damage this combat
|
|
||||||
float dpsEncounterHeal_ = 0.0f; // total player healing this combat
|
|
||||||
size_t dpsLogSeenCount_ = 0; // log entries already scanned
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void triggerDing(uint32_t newLevel, uint32_t hpDelta = 0, uint32_t manaDelta = 0,
|
void openDungeonFinder() { socialPanel_.showDungeonFinder_ = true; }
|
||||||
uint32_t str = 0, uint32_t agi = 0, uint32_t sta = 0,
|
ToastManager& toastManager() { return toastManager_; }
|
||||||
uint32_t intel = 0, uint32_t spi = 0);
|
|
||||||
void triggerAchievementToast(uint32_t achievementId, std::string name = {});
|
|
||||||
void openDungeonFinder() { showDungeonFinder_ = true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
||||||
169
include/ui/settings_panel.hpp
Normal file
169
include/ui/settings_panel.hpp
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace rendering { class Renderer; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class InventoryScreen;
|
||||||
|
class ChatPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings panel (extracted from GameScreen)
|
||||||
|
*
|
||||||
|
* Owns all settings UI rendering, settings state variables, and
|
||||||
|
* graphics preset logic. Save/load remains in GameScreen since
|
||||||
|
* it serialises cross-cutting state (chat, quest tracker, etc.).
|
||||||
|
*/
|
||||||
|
class SettingsPanel {
|
||||||
|
public:
|
||||||
|
// ---- Settings UI visibility flags (written by EscapeMenu / Escape key) ----
|
||||||
|
bool showEscapeSettingsNotice = false;
|
||||||
|
bool showSettingsWindow = false;
|
||||||
|
bool settingsInit = false;
|
||||||
|
|
||||||
|
// ---- Pending video / graphics settings ----
|
||||||
|
bool pendingFullscreen = false;
|
||||||
|
bool pendingVsync = false;
|
||||||
|
int pendingResIndex = 0;
|
||||||
|
bool pendingShadows = true;
|
||||||
|
float pendingShadowDistance = 300.0f;
|
||||||
|
bool pendingWaterRefraction = true;
|
||||||
|
int pendingBrightness = 50; // 0-100, maps to 0.0-2.0 (50 = 1.0 default)
|
||||||
|
|
||||||
|
// ---- Pending audio settings ----
|
||||||
|
int pendingMasterVolume = 100;
|
||||||
|
int pendingMusicVolume = 30;
|
||||||
|
int pendingAmbientVolume = 100;
|
||||||
|
int pendingUiVolume = 100;
|
||||||
|
int pendingCombatVolume = 100;
|
||||||
|
int pendingSpellVolume = 100;
|
||||||
|
int pendingMovementVolume = 100;
|
||||||
|
int pendingFootstepVolume = 100;
|
||||||
|
int pendingNpcVoiceVolume = 100;
|
||||||
|
int pendingMountVolume = 100;
|
||||||
|
int pendingActivityVolume = 100;
|
||||||
|
|
||||||
|
// ---- Pending camera / controls ----
|
||||||
|
float pendingMouseSensitivity = 0.2f;
|
||||||
|
bool pendingInvertMouse = false;
|
||||||
|
bool pendingExtendedZoom = false;
|
||||||
|
float pendingCameraStiffness = 30.0f; // Camera smooth speed (higher = tighter, less sway)
|
||||||
|
float pendingPivotHeight = 1.6f; // Camera pivot height above feet (lower = less detached feel)
|
||||||
|
float pendingFov = 70.0f; // degrees, default matches WoW's ~70° horizontal FOV
|
||||||
|
|
||||||
|
// ---- Pending UI / interface ----
|
||||||
|
int pendingUiOpacity = 65;
|
||||||
|
bool pendingMinimapRotate = false;
|
||||||
|
bool pendingMinimapSquare = false;
|
||||||
|
bool pendingMinimapNpcDots = false;
|
||||||
|
bool pendingShowLatencyMeter = true;
|
||||||
|
bool pendingSeparateBags = true;
|
||||||
|
bool pendingShowKeyring = true;
|
||||||
|
|
||||||
|
// ---- Pending gameplay ----
|
||||||
|
bool pendingAutoLoot = false;
|
||||||
|
bool pendingAutoSellGrey = false;
|
||||||
|
bool pendingAutoRepair = false;
|
||||||
|
|
||||||
|
// ---- Pending soundtrack ----
|
||||||
|
bool pendingUseOriginalSoundtrack = true;
|
||||||
|
|
||||||
|
// ---- Pending action bar layout ----
|
||||||
|
bool pendingShowActionBar2 = true; // Show second action bar above main bar
|
||||||
|
float pendingActionBarScale = 1.0f; // Multiplier for action bar slot size (0.5–1.5)
|
||||||
|
float pendingActionBar2OffsetX = 0.0f; // Horizontal offset from default center position
|
||||||
|
float pendingActionBar2OffsetY = 0.0f; // Vertical offset from default (above bar 1)
|
||||||
|
bool pendingShowRightBar = false; // Right-edge vertical action bar (bar 3, slots 24-35)
|
||||||
|
bool pendingShowLeftBar = false; // Left-edge vertical action bar (bar 4, slots 36-47)
|
||||||
|
float pendingRightBarOffsetY = 0.0f; // Vertical offset from screen center
|
||||||
|
float pendingLeftBarOffsetY = 0.0f; // Vertical offset from screen center
|
||||||
|
|
||||||
|
// ---- Pending graphics quality ----
|
||||||
|
int pendingGroundClutterDensity = 100;
|
||||||
|
int pendingAntiAliasing = 0; // 0=Off, 1=2x, 2=4x, 3=8x
|
||||||
|
bool pendingFXAA = false; // FXAA post-process (combinable with MSAA)
|
||||||
|
bool pendingNormalMapping = true; // on by default
|
||||||
|
float pendingNormalMapStrength = 0.8f; // 0.0-2.0
|
||||||
|
bool pendingPOM = true; // on by default
|
||||||
|
int pendingPOMQuality = 1; // 0=Low(16), 1=Medium(32), 2=High(64)
|
||||||
|
bool pendingFSR = false;
|
||||||
|
int pendingUpscalingMode = 0; // 0=Off, 1=FSR1, 2=FSR3
|
||||||
|
int pendingFSRQuality = 3; // 0=UltraQuality, 1=Quality, 2=Balanced, 3=Native(100%)
|
||||||
|
float pendingFSRSharpness = 1.6f;
|
||||||
|
float pendingFSR2JitterSign = 0.38f;
|
||||||
|
float pendingFSR2MotionVecScaleX = 1.0f;
|
||||||
|
float pendingFSR2MotionVecScaleY = 1.0f;
|
||||||
|
bool pendingAMDFramegen = false;
|
||||||
|
|
||||||
|
// ---- Graphics quality presets ----
|
||||||
|
enum class GraphicsPreset : int {
|
||||||
|
CUSTOM = 0,
|
||||||
|
LOW = 1,
|
||||||
|
MEDIUM = 2,
|
||||||
|
HIGH = 3,
|
||||||
|
ULTRA = 4
|
||||||
|
};
|
||||||
|
GraphicsPreset currentGraphicsPreset = GraphicsPreset::CUSTOM;
|
||||||
|
GraphicsPreset pendingGraphicsPreset = GraphicsPreset::CUSTOM;
|
||||||
|
|
||||||
|
// ---- Applied-once flags (used by GameScreen::render() one-time-apply blocks) ----
|
||||||
|
bool fsrSettingsApplied_ = false;
|
||||||
|
float uiOpacity_ = 0.65f; // UI element transparency (0.0 = fully transparent, 1.0 = fully opaque)
|
||||||
|
bool minimapRotate_ = false;
|
||||||
|
bool minimapSquare_ = false;
|
||||||
|
bool minimapNpcDots_ = false;
|
||||||
|
bool showLatencyMeter_ = true; // Show server latency indicator
|
||||||
|
bool minimapSettingsApplied_ = false;
|
||||||
|
bool volumeSettingsApplied_ = false; // True once saved volume settings applied to audio managers
|
||||||
|
bool msaaSettingsApplied_ = false; // True once saved MSAA setting applied to renderer
|
||||||
|
bool fxaaSettingsApplied_ = false; // True once saved FXAA setting applied to renderer
|
||||||
|
bool waterRefractionApplied_ = false;
|
||||||
|
bool normalMapSettingsApplied_ = false; // True once saved normal map/POM settings applied
|
||||||
|
|
||||||
|
// ---- Mute state: mute bypasses master volume without touching slider values ----
|
||||||
|
bool soundMuted_ = false;
|
||||||
|
float preMuteVolume_ = 1.0f; // AudioEngine master volume before muting
|
||||||
|
|
||||||
|
// ---- Config toggles (read by GameScreen rendering, edited by Interface tab) ----
|
||||||
|
float nameplateScale_ = 1.0f; // Scale multiplier for nameplate bar dimensions
|
||||||
|
bool showFriendlyNameplates_ = true; // Shift+V toggles friendly player nameplates
|
||||||
|
bool showDPSMeter_ = false;
|
||||||
|
bool showCooldownTracker_ = false;
|
||||||
|
bool damageFlashEnabled_ = true;
|
||||||
|
bool lowHealthVignetteEnabled_ = true; // Persistent pulsing red vignette below 20% HP
|
||||||
|
|
||||||
|
// ---- Public methods ----
|
||||||
|
|
||||||
|
/// Render the settings window (call from GameScreen::render)
|
||||||
|
void renderSettingsWindow(InventoryScreen& inventoryScreen, ChatPanel& chatPanel,
|
||||||
|
std::function<void()> saveCallback);
|
||||||
|
|
||||||
|
/// Apply audio volume levels to all renderer sound managers
|
||||||
|
void applyAudioVolumes(rendering::Renderer* renderer);
|
||||||
|
|
||||||
|
/// Return the platform-specific settings file path
|
||||||
|
static std::string getSettingsPath();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Keybinding customization (private — only used in Controls tab)
|
||||||
|
int pendingRebindAction_ = -1; // -1 = not rebinding, otherwise action index
|
||||||
|
bool awaitingKeyPress_ = false;
|
||||||
|
|
||||||
|
// Settings tab rendering
|
||||||
|
void renderSettingsInterfaceTab(std::function<void()> saveCallback);
|
||||||
|
void renderSettingsGameplayTab(InventoryScreen& inventoryScreen,
|
||||||
|
std::function<void()> saveCallback);
|
||||||
|
void renderSettingsControlsTab(std::function<void()> saveCallback);
|
||||||
|
void renderSettingsAudioTab(std::function<void()> saveCallback);
|
||||||
|
void renderSettingsAboutTab();
|
||||||
|
void applyGraphicsPreset(GraphicsPreset preset);
|
||||||
|
void updateGraphicsPresetFromCurrentSettings();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
77
include/ui/social_panel.hpp
Normal file
77
include/ui/social_panel.hpp
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace game { class GameHandler; }
|
||||||
|
namespace pipeline { class AssetManager; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class ChatPanel;
|
||||||
|
class SpellbookScreen;
|
||||||
|
class InventoryScreen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Social panel manager (extracted from GameScreen)
|
||||||
|
*
|
||||||
|
* Owns all social/group-related rendering:
|
||||||
|
* party frames, boss frames, guild roster, social/friends frame,
|
||||||
|
* dungeon finder, who window, inspect window.
|
||||||
|
*/
|
||||||
|
class SocialPanel {
|
||||||
|
public:
|
||||||
|
SocialPanel() = default;
|
||||||
|
|
||||||
|
// ---- Callback type for spell icon lookup (stays in GameScreen) ----
|
||||||
|
using SpellIconFn = std::function<VkDescriptorSet(uint32_t spellId, pipeline::AssetManager*)>;
|
||||||
|
|
||||||
|
// ---- Toggle booleans (written by slash commands / escape handler / keybinds / UI buttons) ----
|
||||||
|
bool showSocialFrame_ = false; // O key toggles social/friends list
|
||||||
|
bool showGuildRoster_ = false;
|
||||||
|
bool showRaidFrames_ = true; // F key toggles raid/party frames
|
||||||
|
bool showWhoWindow_ = false;
|
||||||
|
bool showDungeonFinder_ = false;
|
||||||
|
bool showInspectWindow_ = false;
|
||||||
|
|
||||||
|
// ---- Guild roster state ----
|
||||||
|
std::string selectedGuildMember_;
|
||||||
|
bool showGuildNoteEdit_ = false;
|
||||||
|
bool editingOfficerNote_ = false;
|
||||||
|
char guildNoteEditBuffer_[256] = {0};
|
||||||
|
int guildRosterTab_ = 0; // 0=Roster, 1=Guild Info
|
||||||
|
char guildMotdEditBuffer_[256] = {0};
|
||||||
|
bool showMotdEdit_ = false;
|
||||||
|
char petitionNameBuffer_[64] = {0};
|
||||||
|
char addRankNameBuffer_[64] = {0};
|
||||||
|
bool showAddRankModal_ = false;
|
||||||
|
|
||||||
|
// ---- LFG state ----
|
||||||
|
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
|
||||||
|
uint32_t lfgSelectedDungeon_ = 861; // default: random dungeon (entry 861)
|
||||||
|
|
||||||
|
// ---- Public render methods ----
|
||||||
|
void renderPartyFrames(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel,
|
||||||
|
SpellIconFn getSpellIcon);
|
||||||
|
void renderBossFrames(game::GameHandler& gameHandler,
|
||||||
|
SpellbookScreen& spellbookScreen,
|
||||||
|
SpellIconFn getSpellIcon);
|
||||||
|
void renderGuildRoster(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderSocialFrame(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderDungeonFinderWindow(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderWhoWindow(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderInspectWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
190
include/ui/toast_manager.hpp
Normal file
190
include/ui/toast_manager.hpp
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace game { class GameHandler; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toast / notification overlay manager
|
||||||
|
*
|
||||||
|
* Owns all toast state, callbacks, and rendering:
|
||||||
|
* level-up ding, achievement, area discovery, whisper, quest progress,
|
||||||
|
* player level-up, PvP honor, item loot, reputation, quest complete,
|
||||||
|
* zone entry, area trigger, resurrect flash, and zone text.
|
||||||
|
*/
|
||||||
|
class ToastManager {
|
||||||
|
public:
|
||||||
|
ToastManager() = default;
|
||||||
|
|
||||||
|
/// Register toast-related callbacks on GameHandler (idempotent — safe every frame)
|
||||||
|
void setupCallbacks(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
/// Render "early" toasts (rep, quest-complete, zone, area-trigger) — called before action bars
|
||||||
|
void renderEarlyToasts(float deltaTime, game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
/// Render "late" toasts (ding, achievement, discovery, whisper, quest progress,
|
||||||
|
/// player level-up, PvP honor, item loot, resurrect flash, zone text) — called after escape menu
|
||||||
|
void renderLateToasts(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
/// Fire level-up ding animation + sound
|
||||||
|
void triggerDing(uint32_t newLevel, uint32_t hpDelta = 0, uint32_t manaDelta = 0,
|
||||||
|
uint32_t str = 0, uint32_t agi = 0, uint32_t sta = 0,
|
||||||
|
uint32_t intel = 0, uint32_t spi = 0);
|
||||||
|
|
||||||
|
/// Fire achievement earned toast + sound
|
||||||
|
void triggerAchievementToast(uint32_t achievementId, std::string name = {});
|
||||||
|
|
||||||
|
// --- public state consumed by GameScreen for the golden burst overlay ---
|
||||||
|
float levelUpFlashAlpha = 0.0f;
|
||||||
|
uint32_t levelUpDisplayLevel = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// ---- Ding effect (own level-up) ----
|
||||||
|
static constexpr float DING_DURATION = 4.0f;
|
||||||
|
float dingTimer_ = 0.0f;
|
||||||
|
uint32_t dingLevel_ = 0;
|
||||||
|
uint32_t dingHpDelta_ = 0;
|
||||||
|
uint32_t dingManaDelta_ = 0;
|
||||||
|
uint32_t dingStats_[5] = {};
|
||||||
|
void renderDingEffect();
|
||||||
|
|
||||||
|
// ---- Achievement toast ----
|
||||||
|
static constexpr float ACHIEVEMENT_TOAST_DURATION = 5.0f;
|
||||||
|
float achievementToastTimer_ = 0.0f;
|
||||||
|
uint32_t achievementToastId_ = 0;
|
||||||
|
std::string achievementToastName_;
|
||||||
|
bool achievementCallbackSet_ = false;
|
||||||
|
void renderAchievementToast();
|
||||||
|
|
||||||
|
// ---- Area discovery toast ----
|
||||||
|
static constexpr float DISCOVERY_TOAST_DURATION = 4.0f;
|
||||||
|
float discoveryToastTimer_ = 0.0f;
|
||||||
|
std::string discoveryToastName_;
|
||||||
|
uint32_t discoveryToastXP_ = 0;
|
||||||
|
bool areaDiscoveryCallbackSet_ = false;
|
||||||
|
void renderDiscoveryToast();
|
||||||
|
|
||||||
|
// ---- Whisper toast ----
|
||||||
|
struct WhisperToastEntry {
|
||||||
|
std::string sender;
|
||||||
|
std::string preview;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
static constexpr float WHISPER_TOAST_DURATION = 5.0f;
|
||||||
|
std::vector<WhisperToastEntry> whisperToasts_;
|
||||||
|
size_t whisperSeenCount_ = 0;
|
||||||
|
void renderWhisperToasts();
|
||||||
|
|
||||||
|
// ---- Quest objective progress toast ----
|
||||||
|
struct QuestProgressToastEntry {
|
||||||
|
std::string questTitle;
|
||||||
|
std::string objectiveName;
|
||||||
|
uint32_t current = 0;
|
||||||
|
uint32_t required = 0;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
static constexpr float QUEST_TOAST_DURATION = 4.0f;
|
||||||
|
std::vector<QuestProgressToastEntry> questToasts_;
|
||||||
|
bool questProgressCallbackSet_ = false;
|
||||||
|
void renderQuestProgressToasts();
|
||||||
|
|
||||||
|
// ---- Nearby player level-up toast ----
|
||||||
|
struct PlayerLevelUpToastEntry {
|
||||||
|
uint64_t guid = 0;
|
||||||
|
std::string playerName;
|
||||||
|
uint32_t newLevel = 0;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
static constexpr float PLAYER_LEVELUP_TOAST_DURATION = 4.0f;
|
||||||
|
std::vector<PlayerLevelUpToastEntry> playerLevelUpToasts_;
|
||||||
|
bool otherPlayerLevelUpCallbackSet_ = false;
|
||||||
|
void renderPlayerLevelUpToasts(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
// ---- PvP honor toast ----
|
||||||
|
struct PvpHonorToastEntry {
|
||||||
|
uint32_t honor = 0;
|
||||||
|
uint32_t victimRank = 0;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
static constexpr float PVP_HONOR_TOAST_DURATION = 3.5f;
|
||||||
|
std::vector<PvpHonorToastEntry> pvpHonorToasts_;
|
||||||
|
bool pvpHonorCallbackSet_ = false;
|
||||||
|
void renderPvpHonorToasts();
|
||||||
|
|
||||||
|
// ---- Item loot toast ----
|
||||||
|
struct ItemLootToastEntry {
|
||||||
|
uint32_t itemId = 0;
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t quality = 1;
|
||||||
|
std::string name;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
static constexpr float ITEM_LOOT_TOAST_DURATION = 3.0f;
|
||||||
|
std::vector<ItemLootToastEntry> itemLootToasts_;
|
||||||
|
bool itemLootCallbackSet_ = false;
|
||||||
|
void renderItemLootToasts();
|
||||||
|
|
||||||
|
// ---- Reputation change toast ----
|
||||||
|
struct RepToastEntry {
|
||||||
|
std::string factionName;
|
||||||
|
int32_t delta = 0;
|
||||||
|
int32_t standing = 0;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
std::vector<RepToastEntry> repToasts_;
|
||||||
|
bool repChangeCallbackSet_ = false;
|
||||||
|
static constexpr float kRepToastLifetime = 3.5f;
|
||||||
|
void renderRepToasts(float deltaTime);
|
||||||
|
|
||||||
|
// ---- Quest completion toast ----
|
||||||
|
struct QuestCompleteToastEntry {
|
||||||
|
uint32_t questId = 0;
|
||||||
|
std::string title;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
std::vector<QuestCompleteToastEntry> questCompleteToasts_;
|
||||||
|
bool questCompleteCallbackSet_ = false;
|
||||||
|
static constexpr float kQuestCompleteToastLifetime = 4.0f;
|
||||||
|
void renderQuestCompleteToasts(float deltaTime);
|
||||||
|
|
||||||
|
// ---- Zone entry toast ----
|
||||||
|
struct ZoneToastEntry {
|
||||||
|
std::string zoneName;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
std::vector<ZoneToastEntry> zoneToasts_;
|
||||||
|
std::string lastKnownZone_;
|
||||||
|
static constexpr float kZoneToastLifetime = 3.0f;
|
||||||
|
void renderZoneToasts(float deltaTime);
|
||||||
|
|
||||||
|
// ---- Area trigger message toast ----
|
||||||
|
struct AreaTriggerToast {
|
||||||
|
std::string text;
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
std::vector<AreaTriggerToast> areaTriggerToasts_;
|
||||||
|
void renderAreaTriggerToasts(float deltaTime, game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
// ---- Resurrection flash ----
|
||||||
|
float resurrectFlashTimer_ = 0.0f;
|
||||||
|
static constexpr float kResurrectFlashDuration = 3.0f;
|
||||||
|
bool ghostStateCallbackSet_ = false;
|
||||||
|
void renderResurrectFlash();
|
||||||
|
|
||||||
|
// ---- Zone discovery text ("Entering: <ZoneName>") ----
|
||||||
|
static constexpr float ZONE_TEXT_DURATION = 5.0f;
|
||||||
|
float zoneTextTimer_ = 0.0f;
|
||||||
|
std::string zoneTextName_;
|
||||||
|
std::string lastKnownZoneName_;
|
||||||
|
uint32_t lastKnownWorldStateZoneId_ = 0;
|
||||||
|
void renderZoneText(game::GameHandler& gameHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
182
include/ui/window_manager.hpp
Normal file
182
include/ui/window_manager.hpp
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
// ============================================================
|
||||||
|
// WindowManager — extracted from GameScreen
|
||||||
|
// Owns all NPC interaction windows, popup dialogs, and misc
|
||||||
|
// overlay UI: loot, gossip, quest, vendor, trainer, mail, bank,
|
||||||
|
// auction house, barber, stable, taxi, escape menu, death screen,
|
||||||
|
// instance lockouts, achievements, GM ticket, books, titles,
|
||||||
|
// equipment sets, skills.
|
||||||
|
// ============================================================
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
namespace wowee {
|
||||||
|
namespace game { class GameHandler; }
|
||||||
|
namespace pipeline { class AssetManager; }
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class ChatPanel;
|
||||||
|
class SettingsPanel;
|
||||||
|
class InventoryScreen;
|
||||||
|
class SpellbookScreen;
|
||||||
|
|
||||||
|
class WindowManager {
|
||||||
|
public:
|
||||||
|
// Callback type for resolving spell icons (spellId, assetMgr) → VkDescriptorSet
|
||||||
|
using SpellIconFn = std::function<VkDescriptorSet(uint32_t, pipeline::AssetManager*)>;
|
||||||
|
|
||||||
|
// ---- NPC interaction windows ----
|
||||||
|
void renderLootWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderGossipWindow(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderQuestDetailsWindow(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel,
|
||||||
|
InventoryScreen& inventoryScreen);
|
||||||
|
void renderQuestRequestItemsWindow(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel,
|
||||||
|
InventoryScreen& inventoryScreen);
|
||||||
|
void renderQuestOfferRewardWindow(game::GameHandler& gameHandler,
|
||||||
|
ChatPanel& chatPanel,
|
||||||
|
InventoryScreen& inventoryScreen);
|
||||||
|
void renderVendorWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderTrainerWindow(game::GameHandler& gameHandler,
|
||||||
|
SpellIconFn getSpellIcon);
|
||||||
|
void renderBarberShopWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderStableWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderTaxiWindow(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
// ---- Mail and banking ----
|
||||||
|
void renderMailWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderMailComposeWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen);
|
||||||
|
void renderBankWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderGuildBankWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
void renderAuctionHouseWindow(game::GameHandler& gameHandler,
|
||||||
|
InventoryScreen& inventoryScreen,
|
||||||
|
ChatPanel& chatPanel);
|
||||||
|
|
||||||
|
// ---- Popup / overlay windows ----
|
||||||
|
void renderEscapeMenu(SettingsPanel& settingsPanel);
|
||||||
|
void renderLogoutCountdown(game::GameHandler& gameHandler);
|
||||||
|
void renderDeathScreen(game::GameHandler& gameHandler);
|
||||||
|
void renderReclaimCorpseButton(game::GameHandler& gameHandler);
|
||||||
|
void renderInstanceLockouts(game::GameHandler& gameHandler);
|
||||||
|
void renderAchievementWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderGmTicketWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderBookWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderTitlesWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderEquipSetWindow(game::GameHandler& gameHandler);
|
||||||
|
void renderSkillsWindow(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
// ---- State owned by this manager ----
|
||||||
|
|
||||||
|
// Instance lockouts
|
||||||
|
bool showInstanceLockouts_ = false;
|
||||||
|
|
||||||
|
// Achievements
|
||||||
|
bool showAchievementWindow_ = false;
|
||||||
|
char achievementSearchBuf_[128] = {};
|
||||||
|
|
||||||
|
// Skills / Professions
|
||||||
|
bool showSkillsWindow_ = false;
|
||||||
|
|
||||||
|
// Titles
|
||||||
|
bool showTitlesWindow_ = false;
|
||||||
|
|
||||||
|
// Equipment Sets
|
||||||
|
bool showEquipSetWindow_ = false;
|
||||||
|
|
||||||
|
// GM Ticket
|
||||||
|
bool showGmTicketWindow_ = false;
|
||||||
|
bool gmTicketWindowWasOpen_ = false;
|
||||||
|
char gmTicketBuf_[2048] = {};
|
||||||
|
|
||||||
|
// Book / scroll reader
|
||||||
|
bool showBookWindow_ = false;
|
||||||
|
int bookCurrentPage_ = 0;
|
||||||
|
|
||||||
|
// Death screen
|
||||||
|
float deathElapsed_ = 0.0f;
|
||||||
|
bool deathTimerRunning_ = false;
|
||||||
|
static constexpr float kForcedReleaseSec = 360.0f;
|
||||||
|
|
||||||
|
// Escape menu
|
||||||
|
bool showEscapeMenu = false;
|
||||||
|
|
||||||
|
// Mail compose
|
||||||
|
char mailRecipientBuffer_[256] = "";
|
||||||
|
char mailSubjectBuffer_[256] = "";
|
||||||
|
char mailBodyBuffer_[2048] = "";
|
||||||
|
int mailComposeMoney_[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
// Vendor
|
||||||
|
char vendorSearchFilter_[128] = "";
|
||||||
|
bool vendorConfirmOpen_ = false;
|
||||||
|
uint64_t vendorConfirmGuid_ = 0;
|
||||||
|
uint32_t vendorConfirmItemId_ = 0;
|
||||||
|
uint32_t vendorConfirmSlot_ = 0;
|
||||||
|
uint32_t vendorConfirmQty_ = 1;
|
||||||
|
uint32_t vendorConfirmPrice_ = 0;
|
||||||
|
std::string vendorConfirmItemName_;
|
||||||
|
bool vendorBagsOpened_ = false;
|
||||||
|
|
||||||
|
// Barber shop
|
||||||
|
int barberHairStyle_ = 0;
|
||||||
|
int barberHairColor_ = 0;
|
||||||
|
int barberFacialHair_ = 0;
|
||||||
|
int barberOrigHairStyle_ = 0;
|
||||||
|
int barberOrigHairColor_ = 0;
|
||||||
|
int barberOrigFacialHair_ = 0;
|
||||||
|
bool barberInitialized_ = false;
|
||||||
|
|
||||||
|
// Trainer
|
||||||
|
char trainerSearchFilter_[128] = "";
|
||||||
|
|
||||||
|
// Auction house
|
||||||
|
char auctionSearchName_[256] = "";
|
||||||
|
int auctionLevelMin_ = 0;
|
||||||
|
int auctionLevelMax_ = 0;
|
||||||
|
int auctionQuality_ = 0;
|
||||||
|
int auctionSellDuration_ = 2;
|
||||||
|
int auctionSellBid_[3] = {0, 0, 0};
|
||||||
|
int auctionSellBuyout_[3] = {0, 0, 0};
|
||||||
|
int auctionSelectedItem_ = -1;
|
||||||
|
int auctionSellSlotIndex_ = -1;
|
||||||
|
uint32_t auctionBrowseOffset_ = 0;
|
||||||
|
int auctionItemClass_ = -1;
|
||||||
|
int auctionItemSubClass_ = -1;
|
||||||
|
bool auctionUsableOnly_ = false;
|
||||||
|
|
||||||
|
// Guild bank money input
|
||||||
|
int guildBankMoneyInput_[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
// ItemExtendedCost.dbc cache
|
||||||
|
struct ExtendedCostEntry {
|
||||||
|
uint32_t honorPoints = 0;
|
||||||
|
uint32_t arenaPoints = 0;
|
||||||
|
uint32_t itemId[5] = {};
|
||||||
|
uint32_t itemCount[5] = {};
|
||||||
|
};
|
||||||
|
std::unordered_map<uint32_t, ExtendedCostEntry> extendedCostCache_;
|
||||||
|
bool extendedCostDbLoaded_ = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadExtendedCostDBC();
|
||||||
|
std::string formatExtendedCost(uint32_t extendedCostId, game::GameHandler& gameHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace wowee
|
||||||
|
|
@ -2935,7 +2935,7 @@ void Application::setupUICallbacks() {
|
||||||
// Level-up callback — play sound, cheer emote, and trigger UI ding overlay + 3D effect
|
// Level-up callback — play sound, cheer emote, and trigger UI ding overlay + 3D effect
|
||||||
gameHandler->setLevelUpCallback([this](uint32_t newLevel) {
|
gameHandler->setLevelUpCallback([this](uint32_t newLevel) {
|
||||||
if (uiManager) {
|
if (uiManager) {
|
||||||
uiManager->getGameScreen().triggerDing(newLevel);
|
uiManager->getGameScreen().toastManager().triggerDing(newLevel);
|
||||||
}
|
}
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
renderer->triggerLevelUpEffect(renderer->getCharacterPosition());
|
renderer->triggerLevelUpEffect(renderer->getCharacterPosition());
|
||||||
|
|
@ -2945,7 +2945,7 @@ void Application::setupUICallbacks() {
|
||||||
// Achievement earned callback — show toast banner
|
// Achievement earned callback — show toast banner
|
||||||
gameHandler->setAchievementEarnedCallback([this](uint32_t achievementId, const std::string& name) {
|
gameHandler->setAchievementEarnedCallback([this](uint32_t achievementId, const std::string& name) {
|
||||||
if (uiManager) {
|
if (uiManager) {
|
||||||
uiManager->getGameScreen().triggerAchievementToast(achievementId, name);
|
uiManager->getGameScreen().toastManager().triggerAchievementToast(achievementId, name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1266,14 +1266,14 @@ struct EntityController::GameObjectTypeHandler : EntityController::IObjectTypeHa
|
||||||
struct EntityController::ItemTypeHandler : EntityController::IObjectTypeHandler {
|
struct EntityController::ItemTypeHandler : EntityController::IObjectTypeHandler {
|
||||||
EntityController& ctl_;
|
EntityController& ctl_;
|
||||||
explicit ItemTypeHandler(EntityController& c) : ctl_(c) {}
|
explicit ItemTypeHandler(EntityController& c) : ctl_(c) {}
|
||||||
void onCreate(const UpdateBlock& block, std::shared_ptr<Entity>&, bool& newItemCreated) override { ctl_.onCreateItem(block, newItemCreated); }
|
void onCreate(const UpdateBlock& block, std::shared_ptr<Entity>& /*entity*/, bool& newItemCreated) override { ctl_.onCreateItem(block, newItemCreated); }
|
||||||
void onValuesUpdate(const UpdateBlock& block, std::shared_ptr<Entity>& entity) override { ctl_.onValuesUpdateItem(block, entity); }
|
void onValuesUpdate(const UpdateBlock& block, std::shared_ptr<Entity>& entity) override { ctl_.onValuesUpdateItem(block, entity); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntityController::CorpseTypeHandler : EntityController::IObjectTypeHandler {
|
struct EntityController::CorpseTypeHandler : EntityController::IObjectTypeHandler {
|
||||||
EntityController& ctl_;
|
EntityController& ctl_;
|
||||||
explicit CorpseTypeHandler(EntityController& c) : ctl_(c) {}
|
explicit CorpseTypeHandler(EntityController& c) : ctl_(c) {}
|
||||||
void onCreate(const UpdateBlock& block, std::shared_ptr<Entity>&, bool&) override { ctl_.onCreateCorpse(block); }
|
void onCreate(const UpdateBlock& block, std::shared_ptr<Entity>& /*entity*/, bool&) override { ctl_.onCreateCorpse(block); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
|
||||||
1751
src/ui/action_bar_panel.cpp
Normal file
1751
src/ui/action_bar_panel.cpp
Normal file
File diff suppressed because it is too large
Load diff
4898
src/ui/chat_panel.cpp
Normal file
4898
src/ui/chat_panel.cpp
Normal file
File diff suppressed because it is too large
Load diff
1890
src/ui/combat_ui.cpp
Normal file
1890
src/ui/combat_ui.cpp
Normal file
File diff suppressed because it is too large
Load diff
1115
src/ui/dialog_manager.cpp
Normal file
1115
src/ui/dialog_manager.cpp
Normal file
File diff suppressed because it is too large
Load diff
19216
src/ui/game_screen.cpp
19216
src/ui/game_screen.cpp
File diff suppressed because it is too large
Load diff
1258
src/ui/settings_panel.cpp
Normal file
1258
src/ui/settings_panel.cpp
Normal file
File diff suppressed because it is too large
Load diff
2626
src/ui/social_panel.cpp
Normal file
2626
src/ui/social_panel.cpp
Normal file
File diff suppressed because it is too large
Load diff
1250
src/ui/toast_manager.cpp
Normal file
1250
src/ui/toast_manager.cpp
Normal file
File diff suppressed because it is too large
Load diff
4264
src/ui/window_manager.cpp
Normal file
4264
src/ui/window_manager.cpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue