2026-02-02 12:24:50 -08:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include "game/game_handler.hpp"
|
|
|
|
|
|
#include "game/inventory.hpp"
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// WorldMap is now owned by Renderer, accessed via getWorldMap()
|
2026-02-06 14:24:38 -08:00
|
|
|
|
#include "rendering/character_preview.hpp"
|
2026-02-02 12:24:50 -08:00
|
|
|
|
#include "ui/inventory_screen.hpp"
|
2026-02-06 13:47:03 -08:00
|
|
|
|
#include "ui/quest_log_screen.hpp"
|
2026-02-04 11:31:08 -08:00
|
|
|
|
#include "ui/spellbook_screen.hpp"
|
2026-02-06 16:04:25 -08:00
|
|
|
|
#include "ui/talent_screen.hpp"
|
2026-03-11 06:51:48 -07:00
|
|
|
|
#include "ui/keybinding_manager.hpp"
|
2026-02-22 03:32:08 -08:00
|
|
|
|
#include <vulkan/vulkan.h>
|
2026-02-02 12:24:50 -08:00
|
|
|
|
#include <imgui.h>
|
|
|
|
|
|
#include <string>
|
2026-02-05 15:07:13 -08:00
|
|
|
|
#include <unordered_map>
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-06 14:30:54 -08:00
|
|
|
|
namespace wowee {
|
|
|
|
|
|
namespace pipeline { class AssetManager; }
|
|
|
|
|
|
namespace ui {
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* In-game screen UI
|
|
|
|
|
|
*
|
|
|
|
|
|
* Displays player info, entity list, chat, and game controls
|
|
|
|
|
|
*/
|
|
|
|
|
|
class GameScreen {
|
|
|
|
|
|
public:
|
|
|
|
|
|
GameScreen();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Render the UI
|
|
|
|
|
|
* @param gameHandler Reference to game handler
|
|
|
|
|
|
*/
|
|
|
|
|
|
void render(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Check if chat input is active
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool isChatInputActive() const { return chatInputActive; }
|
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
|
void saveSettings();
|
|
|
|
|
|
void loadSettings();
|
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
private:
|
|
|
|
|
|
// Chat state
|
|
|
|
|
|
char chatInputBuffer[512] = "";
|
2026-02-07 12:30:36 -08:00
|
|
|
|
char whisperTargetBuffer[256] = "";
|
2026-02-02 12:24:50 -08:00
|
|
|
|
bool chatInputActive = false;
|
2026-03-12 11:16:42 -07:00
|
|
|
|
int selectedChatType = 0; // 0=SAY, 1=YELL, 2=PARTY, 3=GUILD, 4=WHISPER, ..., 10=CHANNEL
|
2026-02-07 12:30:36 -08:00
|
|
|
|
int lastChatType = 0; // Track chat type changes
|
2026-03-12 11:16:42 -07:00
|
|
|
|
int selectedChannelIdx = 0; // Index into joinedChannels_ when selectedChatType==10
|
2026-02-06 18:34:45 -08:00
|
|
|
|
bool chatInputMoveCursorToEnd = false;
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-03-11 23:06:24 -07:00
|
|
|
|
// Chat sent-message history (Up/Down arrow recall)
|
|
|
|
|
|
std::vector<std::string> chatSentHistory_;
|
|
|
|
|
|
int chatHistoryIdx_ = -1; // -1 = not browsing history
|
|
|
|
|
|
|
2026-03-18 04:14:44 -07:00
|
|
|
|
// Set to true by /stopmacro; checked in executeMacroText to halt remaining commands.
|
|
|
|
|
|
bool macroStopped_ = false;
|
|
|
|
|
|
|
2026-03-12 06:38:10 -07:00
|
|
|
|
// Tab-completion state for slash commands
|
|
|
|
|
|
std::string chatTabPrefix_; // prefix captured on first Tab press
|
|
|
|
|
|
std::vector<std::string> chatTabMatches_; // matching command list
|
|
|
|
|
|
int chatTabMatchIdx_ = -1; // active match index (-1 = inactive)
|
|
|
|
|
|
|
2026-03-12 06:45:27 -07:00
|
|
|
|
// Mention notification: plays a sound when the player's name appears in chat
|
|
|
|
|
|
size_t chatMentionSeenCount_ = 0; // how many messages have been scanned for mentions
|
|
|
|
|
|
|
2026-02-14 14:30:09 -08:00
|
|
|
|
// Chat tabs
|
|
|
|
|
|
int activeChatTab_ = 0;
|
|
|
|
|
|
struct ChatTab {
|
|
|
|
|
|
std::string name;
|
2026-03-12 08:54:29 -07:00
|
|
|
|
uint64_t typeMask; // bitmask of ChatType values to show (64-bit: types go up to 84)
|
2026-02-14 14:30:09 -08:00
|
|
|
|
};
|
|
|
|
|
|
std::vector<ChatTab> chatTabs_;
|
2026-03-12 11:23:01 -07:00
|
|
|
|
std::vector<int> chatTabUnread_; // unread message count per tab (0 = none)
|
|
|
|
|
|
size_t chatTabSeenCount_ = 0; // how many history messages have been processed
|
2026-02-14 14:30:09 -08:00
|
|
|
|
void initChatTabs();
|
|
|
|
|
|
bool shouldShowMessage(const game::MessageChatData& msg, int tabIndex) const;
|
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
// UI state
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
bool showEntityWindow = false;
|
2026-02-02 12:24:50 -08:00
|
|
|
|
bool showChatWindow = true;
|
2026-03-11 09:24:37 -07:00
|
|
|
|
bool showMinimap_ = true; // M key toggles minimap
|
2026-03-09 17:03:06 -07:00
|
|
|
|
bool showNameplates_ = true; // V key toggles nameplates
|
2026-03-11 22:49:54 -07:00
|
|
|
|
float nameplateScale_ = 1.0f; // Scale multiplier for nameplate bar dimensions
|
2026-03-12 00:26:47 -07:00
|
|
|
|
uint64_t nameplateCtxGuid_ = 0; // GUID of nameplate right-clicked (0 = none)
|
|
|
|
|
|
ImVec2 nameplateCtxPos_{}; // Screen position of nameplate right-click
|
2026-03-11 22:57:04 -07:00
|
|
|
|
uint32_t lastPlayerHp_ = 0; // Previous frame HP for damage flash detection
|
|
|
|
|
|
float damageFlashAlpha_ = 0.0f; // Screen edge flash intensity (fades to 0)
|
2026-03-12 03:21:49 -07:00
|
|
|
|
bool damageFlashEnabled_ = true;
|
2026-03-12 07:15:08 -07:00
|
|
|
|
bool lowHealthVignetteEnabled_ = true; // Persistent pulsing red vignette below 20% HP
|
2026-03-11 23:10:21 -07:00
|
|
|
|
float levelUpFlashAlpha_ = 0.0f; // Golden level-up burst effect (fades to 0)
|
|
|
|
|
|
uint32_t levelUpDisplayLevel_ = 0; // Level shown in level-up text
|
2026-03-12 01:15:11 -07:00
|
|
|
|
|
2026-03-12 03:52:54 -07:00
|
|
|
|
// 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
|
|
|
|
|
|
|
2026-03-12 01:15:11 -07:00
|
|
|
|
// UIErrorsFrame: WoW-style center-bottom error messages (spell fails, out of range, etc.)
|
|
|
|
|
|
struct UIErrorEntry { std::string text; float age = 0.0f; };
|
|
|
|
|
|
std::vector<UIErrorEntry> uiErrors_;
|
|
|
|
|
|
bool uiErrorCallbackSet_ = false;
|
|
|
|
|
|
static constexpr float kUIErrorLifetime = 2.5f;
|
2026-03-12 01:51:18 -07:00
|
|
|
|
|
|
|
|
|
|
// 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;
|
2026-03-12 04:53:03 -07:00
|
|
|
|
|
|
|
|
|
|
// 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;
|
2026-03-12 05:44:25 -07:00
|
|
|
|
|
|
|
|
|
|
// Zone entry toast: brief banner when entering a new zone
|
|
|
|
|
|
struct ZoneToastEntry { std::string zoneName; float age = 0.0f; };
|
|
|
|
|
|
std::vector<ZoneToastEntry> zoneToasts_;
|
2026-03-12 11:06:40 -07:00
|
|
|
|
|
|
|
|
|
|
struct AreaTriggerToast { std::string text; float age = 0.0f; };
|
|
|
|
|
|
std::vector<AreaTriggerToast> areaTriggerToasts_;
|
|
|
|
|
|
void renderAreaTriggerToasts(float deltaTime, game::GameHandler& gameHandler);
|
2026-03-12 05:44:25 -07:00
|
|
|
|
std::string lastKnownZone_;
|
|
|
|
|
|
static constexpr float kZoneToastLifetime = 3.0f;
|
2026-03-12 06:14:18 -07:00
|
|
|
|
|
|
|
|
|
|
// 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;
|
2026-03-12 05:44:25 -07:00
|
|
|
|
void renderZoneToasts(float deltaTime);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
bool showPlayerInfo = false;
|
2026-03-10 05:46:03 -07:00
|
|
|
|
bool showSocialFrame_ = false; // O key toggles social/friends list
|
2026-02-13 21:39:48 -08:00
|
|
|
|
bool showGuildRoster_ = false;
|
2026-03-11 09:24:37 -07:00
|
|
|
|
bool showRaidFrames_ = true; // F key toggles raid/party frames
|
2026-03-11 07:38:08 -07:00
|
|
|
|
bool showWorldMap_ = false; // W key toggles world map
|
2026-02-16 20:16:14 -08:00
|
|
|
|
std::string selectedGuildMember_;
|
|
|
|
|
|
bool showGuildNoteEdit_ = false;
|
|
|
|
|
|
bool editingOfficerNote_ = false;
|
|
|
|
|
|
char guildNoteEditBuffer_[256] = {0};
|
2026-02-25 14:44:44 -08:00
|
|
|
|
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;
|
2026-02-02 12:24:50 -08:00
|
|
|
|
bool refocusChatInput = false;
|
2026-02-19 22:34:22 -08:00
|
|
|
|
bool vendorBagsOpened_ = false; // Track if bags were auto-opened for current vendor session
|
2026-03-11 23:24:27 -07:00
|
|
|
|
bool chatScrolledUp_ = false; // true when user has scrolled above the latest messages
|
|
|
|
|
|
bool chatForceScrollToBottom_ = false; // set to true to jump to bottom next frame
|
2026-02-06 18:34:45 -08:00
|
|
|
|
bool chatWindowLocked = true;
|
|
|
|
|
|
ImVec2 chatWindowPos_ = ImVec2(0.0f, 0.0f);
|
|
|
|
|
|
bool chatWindowPosInit_ = false;
|
2026-03-12 16:47:42 -07:00
|
|
|
|
ImVec2 questTrackerPos_ = ImVec2(-1.0f, -1.0f); // <0 = use default
|
2026-03-13 04:04:29 -07:00
|
|
|
|
ImVec2 questTrackerSize_ = ImVec2(220.0f, 200.0f); // saved size
|
|
|
|
|
|
float questTrackerRightOffset_ = -1.0f; // pixels from right edge; <0 = use default
|
2026-03-12 16:47:42 -07:00
|
|
|
|
bool questTrackerPosInit_ = false;
|
2026-02-05 16:01:38 -08:00
|
|
|
|
bool showEscapeMenu = false;
|
|
|
|
|
|
bool showEscapeSettingsNotice = false;
|
2026-02-05 16:11:00 -08:00
|
|
|
|
bool showSettingsWindow = false;
|
|
|
|
|
|
bool settingsInit = false;
|
|
|
|
|
|
bool pendingFullscreen = false;
|
|
|
|
|
|
bool pendingVsync = false;
|
|
|
|
|
|
int pendingResIndex = 0;
|
2026-02-23 08:40:16 -08:00
|
|
|
|
bool pendingShadows = true;
|
2026-03-07 22:29:06 -08:00
|
|
|
|
float pendingShadowDistance = 300.0f;
|
2026-03-06 19:15:34 -08:00
|
|
|
|
bool pendingWaterRefraction = false;
|
2026-03-17 09:04:53 -07:00
|
|
|
|
int pendingBrightness = 50; // 0-100, maps to 0.0-2.0 (50 = 1.0 default)
|
Implement comprehensive audio control panel with tabbed settings interface
Adds complete audio volume controls for all 11 audio systems with master volume. Reorganizes settings window into Video, Audio, and Gameplay tabs for better UX.
Audio Features:
- Master volume control affecting all audio systems
- Individual volume sliders for: Music, Ambient, UI, Combat, Spell, Movement, Footsteps, NPC Voices, Mounts, Activity sounds
- Real-time volume adjustment with master volume multiplier
- Restore defaults button per tab
Technical Changes:
- Added getVolumeScale() getters to all audio managers
- Integrated all 10 audio managers into renderer (UI, Combat, Spell, Movement added)
- Expanded game_screen.hpp with 11 pending volume variables
- Reorganized settings window using ImGui tab bars (Video/Audio/Gameplay)
- Audio settings uses scrollable child window for 11 volume controls
- Settings window expanded to 520x720px to accommodate comprehensive controls
2026-02-09 17:07:22 -08:00
|
|
|
|
int pendingMasterVolume = 100;
|
2026-02-05 17:32:21 -08:00
|
|
|
|
int pendingMusicVolume = 30;
|
Implement comprehensive audio control panel with tabbed settings interface
Adds complete audio volume controls for all 11 audio systems with master volume. Reorganizes settings window into Video, Audio, and Gameplay tabs for better UX.
Audio Features:
- Master volume control affecting all audio systems
- Individual volume sliders for: Music, Ambient, UI, Combat, Spell, Movement, Footsteps, NPC Voices, Mounts, Activity sounds
- Real-time volume adjustment with master volume multiplier
- Restore defaults button per tab
Technical Changes:
- Added getVolumeScale() getters to all audio managers
- Integrated all 10 audio managers into renderer (UI, Combat, Spell, Movement added)
- Expanded game_screen.hpp with 11 pending volume variables
- Reorganized settings window using ImGui tab bars (Video/Audio/Gameplay)
- Audio settings uses scrollable child window for 11 volume controls
- Settings window expanded to 520x720px to accommodate comprehensive controls
2026-02-09 17:07:22 -08:00
|
|
|
|
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;
|
2026-02-05 17:51:14 -08:00
|
|
|
|
float pendingMouseSensitivity = 0.2f;
|
|
|
|
|
|
bool pendingInvertMouse = false;
|
2026-02-23 08:09:27 -08:00
|
|
|
|
bool pendingExtendedZoom = false;
|
2026-03-11 22:13:22 -07:00
|
|
|
|
float pendingFov = 70.0f; // degrees, default matches WoW's ~70° horizontal FOV
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
|
int pendingUiOpacity = 65;
|
2026-02-09 01:13:56 -08:00
|
|
|
|
bool pendingMinimapRotate = false;
|
2026-02-09 17:39:21 -08:00
|
|
|
|
bool pendingMinimapSquare = false;
|
2026-02-20 16:40:22 -08:00
|
|
|
|
bool pendingMinimapNpcDots = false;
|
2026-03-11 19:45:03 -07:00
|
|
|
|
bool pendingShowLatencyMeter = true;
|
2026-02-13 22:51:49 -08:00
|
|
|
|
bool pendingSeparateBags = true;
|
2026-03-17 08:18:46 -07:00
|
|
|
|
bool pendingShowKeyring = true;
|
2026-02-17 16:31:00 -08:00
|
|
|
|
bool pendingAutoLoot = false;
|
2026-03-17 20:21:06 -07:00
|
|
|
|
bool pendingAutoSellGrey = false;
|
2026-03-17 20:27:45 -07:00
|
|
|
|
bool pendingAutoRepair = false;
|
2026-03-11 06:51:48 -07:00
|
|
|
|
|
|
|
|
|
|
// Keybinding customization
|
|
|
|
|
|
int pendingRebindAction = -1; // -1 = not rebinding, otherwise action index
|
|
|
|
|
|
bool awaitingKeyPress = false;
|
2026-03-18 02:07:59 -07:00
|
|
|
|
// Macro editor popup state
|
|
|
|
|
|
uint32_t macroEditorId_ = 0; // macro index being edited
|
|
|
|
|
|
bool macroEditorOpen_ = false; // deferred OpenPopup flag
|
|
|
|
|
|
char macroEditorBuf_[256] = {}; // edit buffer
|
2026-02-17 16:26:49 -08:00
|
|
|
|
bool pendingUseOriginalSoundtrack = true;
|
2026-03-10 15:45:35 -07:00
|
|
|
|
bool pendingShowActionBar2 = true; // Show second action bar above main bar
|
2026-03-11 22:39:59 -07:00
|
|
|
|
float pendingActionBarScale = 1.0f; // Multiplier for action bar slot size (0.5–1.5)
|
2026-03-10 15:45:35 -07:00
|
|
|
|
float pendingActionBar2OffsetX = 0.0f; // Horizontal offset from default center position
|
|
|
|
|
|
float pendingActionBar2OffsetY = 0.0f; // Vertical offset from default (above bar 1)
|
2026-03-10 15:56:41 -07:00
|
|
|
|
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
|
2026-02-21 01:26:16 -08:00
|
|
|
|
int pendingGroundClutterDensity = 100;
|
2026-02-22 02:59:24 -08:00
|
|
|
|
int pendingAntiAliasing = 0; // 0=Off, 1=2x, 2=4x, 3=8x
|
2026-03-12 16:43:48 -07:00
|
|
|
|
bool pendingFXAA = false; // FXAA post-process (combinable with MSAA)
|
2026-02-23 01:10:58 -08:00
|
|
|
|
bool pendingNormalMapping = true; // on by default
|
2026-02-23 01:21:58 -08:00
|
|
|
|
float pendingNormalMapStrength = 0.8f; // 0.0-2.0
|
2026-02-23 01:23:24 -08:00
|
|
|
|
bool pendingPOM = true; // on by default
|
2026-02-23 01:10:58 -08:00
|
|
|
|
int pendingPOMQuality = 1; // 0=Low(16), 1=Medium(32), 2=High(64)
|
2026-03-07 22:03:28 -08:00
|
|
|
|
bool pendingFSR = false;
|
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer
generic ffxCreateContext/ffxDispatch API; selects whichever the loaded
runtime library exports (GenericApi takes priority fallback)
- Generic API path implements full upscale + frame-generation context
creation, configure, dispatch, and destroy lifecycle
- dlopen error captured and surfaced in lastError_ on Linux so runtime
initialization failures are actionable
- FSR3 runtime init failure log now includes path kind, error string,
and loaded library path for easier debugging
- tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps
missing VK permutation headers; DXC auto-downloaded on Linux/Windows
MSYS2; macOS reads from PATH (CI installs via brew dxc)
- CMakeLists: add upscalers/include to probe include dirs, invoke
permutation script before SDK build, scope FFX pragma/ODR warning
suppressions to affected TUs, add runtime-copy dependency on wowee
- UI labels updated from "FSR2" → "FSR3" in settings, tuning panel,
performance HUD, and combo boxes
- CI macOS job now installs dxc via Homebrew for permutation codegen
2026-03-09 12:51:59 -07:00
|
|
|
|
int pendingUpscalingMode = 0; // 0=Off, 1=FSR1, 2=FSR3
|
2026-03-08 21:34:31 -07:00
|
|
|
|
int pendingFSRQuality = 3; // 0=UltraQuality, 1=Quality, 2=Balanced, 3=Native(100%)
|
|
|
|
|
|
float pendingFSRSharpness = 1.6f;
|
|
|
|
|
|
float pendingFSR2JitterSign = 0.38f;
|
2026-03-08 20:56:22 -07:00
|
|
|
|
float pendingFSR2MotionVecScaleX = 1.0f;
|
|
|
|
|
|
float pendingFSR2MotionVecScaleY = 1.0f;
|
2026-03-08 22:53:21 -07:00
|
|
|
|
bool pendingAMDFramegen = false;
|
2026-03-07 22:03:28 -08:00
|
|
|
|
bool fsrSettingsApplied_ = false;
|
2026-02-06 20:19:39 -08:00
|
|
|
|
|
2026-03-11 15:21:48 -07:00
|
|
|
|
// 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;
|
|
|
|
|
|
|
2026-02-06 20:19:39 -08:00
|
|
|
|
// UI element transparency (0.0 = fully transparent, 1.0 = fully opaque)
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
|
float uiOpacity_ = 0.65f;
|
2026-02-09 01:13:56 -08:00
|
|
|
|
bool minimapRotate_ = false;
|
2026-02-09 17:39:21 -08:00
|
|
|
|
bool minimapSquare_ = false;
|
2026-02-20 16:40:22 -08:00
|
|
|
|
bool minimapNpcDots_ = false;
|
2026-03-11 19:45:03 -07:00
|
|
|
|
bool showLatencyMeter_ = true; // Show server latency indicator
|
2026-02-09 17:39:21 -08:00
|
|
|
|
bool minimapSettingsApplied_ = false;
|
2026-02-17 17:37:20 -08:00
|
|
|
|
bool volumeSettingsApplied_ = false; // True once saved volume settings applied to audio managers
|
2026-02-22 02:59:24 -08:00
|
|
|
|
bool msaaSettingsApplied_ = false; // True once saved MSAA setting applied to renderer
|
2026-03-12 16:43:48 -07:00
|
|
|
|
bool fxaaSettingsApplied_ = false; // True once saved FXAA setting applied to renderer
|
2026-03-06 19:15:34 -08:00
|
|
|
|
bool waterRefractionApplied_ = false;
|
2026-02-23 01:10:58 -08:00
|
|
|
|
bool normalMapSettingsApplied_ = false; // True once saved normal map/POM settings applied
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-17 16:26:49 -08:00
|
|
|
|
// Mute state: mute bypasses master volume without touching slider values
|
|
|
|
|
|
bool soundMuted_ = false;
|
|
|
|
|
|
float preMuteVolume_ = 1.0f; // AudioEngine master volume before muting
|
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Render player info window
|
|
|
|
|
|
*/
|
|
|
|
|
|
void renderPlayerInfo(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Render entity list window
|
|
|
|
|
|
*/
|
|
|
|
|
|
void renderEntityList(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Render chat window
|
|
|
|
|
|
*/
|
|
|
|
|
|
void renderChatWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Send chat message
|
|
|
|
|
|
*/
|
|
|
|
|
|
void sendChatMessage(game::GameHandler& gameHandler);
|
2026-03-18 02:44:28 -07:00
|
|
|
|
void executeMacroText(game::GameHandler& gameHandler, const std::string& macroText);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 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)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void renderPlayerFrame(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Render target frame
|
|
|
|
|
|
*/
|
|
|
|
|
|
void renderTargetFrame(game::GameHandler& gameHandler);
|
2026-03-10 21:15:24 -07:00
|
|
|
|
void renderFocusFrame(game::GameHandler& gameHandler);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-03-09 17:23:28 -07:00
|
|
|
|
/**
|
|
|
|
|
|
* Render pet frame (below player frame when player has an active pet)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void renderPetFrame(game::GameHandler& gameHandler);
|
2026-03-12 10:14:44 -07:00
|
|
|
|
void renderTotemFrame(game::GameHandler& gameHandler);
|
2026-03-09 17:23:28 -07:00
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Process targeting input (Tab, Escape, click)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void processTargetInput(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Rebuild character geosets from current equipment state
|
|
|
|
|
|
*/
|
|
|
|
|
|
void updateCharacterGeosets(game::Inventory& inventory);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Re-composite character skin texture from current equipment
|
|
|
|
|
|
*/
|
|
|
|
|
|
void updateCharacterTextures(game::Inventory& inventory);
|
|
|
|
|
|
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
// ---- New UI renders ----
|
|
|
|
|
|
void renderActionBar(game::GameHandler& gameHandler);
|
feat: add stance/form/presence bar for Warriors, Druids, Death Knights, Rogues, Priests
Renders a stance bar to the left of the main action bar showing the
player's known stance spells filtered to only those they have learned:
- Warrior: Battle Stance, Defensive Stance, Berserker Stance
- Death Knight: Blood Presence, Frost Presence, Unholy Presence
- Druid: Bear/Dire Bear, Cat, Travel, Aquatic, Moonkin, Tree, Flight forms
- Rogue: Stealth
- Priest: Shadowform
Active form detected from permanent player auras (maxDurationMs == -1).
Clicking an inactive stance casts the corresponding spell. Active stance
shown with green border/tint; inactive stances are slightly dimmed.
Spell name tooltips shown on hover using existing SpellbookScreen lookup.
2026-03-17 15:12:58 -07:00
|
|
|
|
void renderStanceBar(game::GameHandler& gameHandler);
|
Implement complete talent system with dual spec support
Network Protocol:
- Add SMSG_TALENTS_INFO (0x4C0) packet parsing for talent data
- Add CMSG_LEARN_TALENT (0x251) to request learning talents
- Add MSG_TALENT_WIPE_CONFIRM (0x2AB) opcode for spec switching
- Parse talent spec, unspent points, and learned talent ranks
DBC Parsing:
- Load Talent.dbc: talent grid positions, ranks, prerequisites, spell IDs
- Load TalentTab.dbc: talent tree definitions with correct field indices
- Fix localized string field handling (17 fields per string)
- Load Spell.dbc and SpellIcon.dbc for talent icons and tooltips
- Class mask filtering using bitwise operations (1 << (class - 1))
UI Implementation:
- Complete talent tree UI with tabbed interface for specs
- Display talent icons from spell data with proper tinting/borders
- Enhanced tooltips: spell name, rank, current/next descriptions, prereqs
- Visual states: green (maxed), yellow (partial), white (available), gray (locked)
- Tier unlock system (5 points per tier requirement)
- Rank overlay on icons with shadow text
- Click to learn talents with validation
Dual Spec Support:
- Store unspent points and learned talents per spec (0 and 1)
- Track active spec and display its talents
- Spec switching UI with buttons for Spec 1/Spec 2
- Handle both SMSG_TALENTS_INFO packets from server at login
- Display unspent points for both specs in header
- Independent talent trees for each specialization
2026-02-10 02:00:13 -08:00
|
|
|
|
void renderBagBar(game::GameHandler& gameHandler);
|
2026-02-05 12:07:58 -08:00
|
|
|
|
void renderXpBar(game::GameHandler& gameHandler);
|
2026-03-12 05:03:03 -07:00
|
|
|
|
void renderRepBar(game::GameHandler& gameHandler);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
void renderCastBar(game::GameHandler& gameHandler);
|
2026-03-09 14:30:48 -07:00
|
|
|
|
void renderMirrorTimers(game::GameHandler& gameHandler);
|
2026-03-12 15:25:07 -07:00
|
|
|
|
void renderCooldownTracker(game::GameHandler& gameHandler);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
void renderCombatText(game::GameHandler& gameHandler);
|
2026-03-12 03:52:54 -07:00
|
|
|
|
void renderRaidWarningOverlay(game::GameHandler& gameHandler);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
void renderPartyFrames(game::GameHandler& gameHandler);
|
2026-03-09 20:05:09 -07:00
|
|
|
|
void renderBossFrames(game::GameHandler& gameHandler);
|
2026-03-12 01:15:11 -07:00
|
|
|
|
void renderUIErrors(game::GameHandler& gameHandler, float deltaTime);
|
2026-03-12 01:51:18 -07:00
|
|
|
|
void renderRepToasts(float deltaTime);
|
2026-03-12 04:53:03 -07:00
|
|
|
|
void renderQuestCompleteToasts(float deltaTime);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
void renderGroupInvitePopup(game::GameHandler& gameHandler);
|
2026-03-09 13:58:02 -07:00
|
|
|
|
void renderDuelRequestPopup(game::GameHandler& gameHandler);
|
2026-03-12 05:06:14 -07:00
|
|
|
|
void renderDuelCountdown(game::GameHandler& gameHandler);
|
2026-03-09 14:01:27 -07:00
|
|
|
|
void renderLootRollPopup(game::GameHandler& gameHandler);
|
Implement basic trade request/accept/decline flow
- Parse SMSG_TRADE_STATUS for all 20+ status codes: incoming request,
open/cancel/complete/accept notifications, error conditions (too far,
wrong faction, stunned, dead, trial account, etc.)
- SMSG_TRADE_STATUS_EXTENDED consumed via shared handler (no full item
window yet; state tracking sufficient for accept/decline flow)
- Add acceptTradeRequest() (CMSG_BEGIN_TRADE), declineTradeRequest(),
acceptTrade() (CMSG_ACCEPT_TRADE), cancelTrade() (CMSG_CANCEL_TRADE)
- Add BeginTradePacket, CancelTradePacket, AcceptTradePacket builders
- Add renderTradeRequestPopup(): shows "X wants to trade" with
Accept/Decline buttons when tradeStatus_ == PendingIncoming
- TradeStatus enum tracks None/PendingIncoming/Open/Accepted/Complete
2026-03-09 14:05:42 -07:00
|
|
|
|
void renderTradeRequestPopup(game::GameHandler& gameHandler);
|
2026-03-11 00:44:07 -07:00
|
|
|
|
void renderTradeWindow(game::GameHandler& gameHandler);
|
2026-03-09 14:07:50 -07:00
|
|
|
|
void renderSummonRequestPopup(game::GameHandler& gameHandler);
|
2026-03-09 14:14:15 -07:00
|
|
|
|
void renderSharedQuestPopup(game::GameHandler& gameHandler);
|
2026-03-09 14:15:59 -07:00
|
|
|
|
void renderItemTextWindow(game::GameHandler& gameHandler);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
void renderBuffBar(game::GameHandler& gameHandler);
|
2026-03-10 05:46:03 -07:00
|
|
|
|
void renderSocialFrame(game::GameHandler& gameHandler);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
void renderLootWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
void renderGossipWindow(game::GameHandler& gameHandler);
|
2026-02-06 11:59:51 -08:00
|
|
|
|
void renderQuestDetailsWindow(game::GameHandler& gameHandler);
|
2026-02-06 21:50:15 -08:00
|
|
|
|
void renderQuestRequestItemsWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
void renderQuestOfferRewardWindow(game::GameHandler& gameHandler);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
void renderVendorWindow(game::GameHandler& gameHandler);
|
2026-02-08 14:33:39 -08:00
|
|
|
|
void renderTrainerWindow(game::GameHandler& gameHandler);
|
feat: implement pet stable system (MSG_LIST_STABLED_PETS, CMSG_STABLE_PET, CMSG_UNSTABLE_PET)
- Parse MSG_LIST_STABLED_PETS (SMSG): populate StabledPet list with
petNumber, entry, level, name, displayId, and active status
- Detect stable master via gossip option text/keyword matching and
auto-send MSG_LIST_STABLED_PETS request to open the stable UI
- Refresh list automatically after SMSG_STABLE_RESULT to reflect state
- New packet builders: ListStabledPetsPacket, StablePetPacket, UnstablePetPacket
- New public API: requestStabledPetList(), stablePet(slot), unstablePet(petNumber)
- Stable window UI: shows active/stabled pets with store/retrieve buttons,
slot count, refresh, and close; opens when server sends pet list
- Clear stable state on world logout/disconnect
2026-03-12 19:15:52 -07:00
|
|
|
|
void renderStableWindow(game::GameHandler& gameHandler);
|
2026-02-07 16:59:20 -08:00
|
|
|
|
void renderTaxiWindow(game::GameHandler& gameHandler);
|
2026-03-13 10:13:54 -07:00
|
|
|
|
void renderLogoutCountdown(game::GameHandler& gameHandler);
|
2026-02-06 17:27:20 -08:00
|
|
|
|
void renderDeathScreen(game::GameHandler& gameHandler);
|
2026-03-09 22:31:56 -07:00
|
|
|
|
void renderReclaimCorpseButton(game::GameHandler& gameHandler);
|
2026-02-07 23:12:24 -08:00
|
|
|
|
void renderResurrectDialog(game::GameHandler& gameHandler);
|
2026-03-10 12:53:05 -07:00
|
|
|
|
void renderTalentWipeConfirmDialog(game::GameHandler& gameHandler);
|
2026-03-17 21:13:27 -07:00
|
|
|
|
void renderPetUnlearnConfirmDialog(game::GameHandler& gameHandler);
|
2026-02-05 16:01:38 -08:00
|
|
|
|
void renderEscapeMenu();
|
2026-02-05 16:11:00 -08:00
|
|
|
|
void renderSettingsWindow();
|
2026-03-11 15:21:48 -07:00
|
|
|
|
void applyGraphicsPreset(GraphicsPreset preset);
|
|
|
|
|
|
void updateGraphicsPresetFromCurrentSettings();
|
2026-02-06 20:10:10 -08:00
|
|
|
|
void renderQuestMarkers(game::GameHandler& gameHandler);
|
|
|
|
|
|
void renderMinimapMarkers(game::GameHandler& gameHandler);
|
2026-03-09 15:05:38 -07:00
|
|
|
|
void renderQuestObjectiveTracker(game::GameHandler& gameHandler);
|
2026-02-13 21:39:48 -08:00
|
|
|
|
void renderGuildRoster(game::GameHandler& gameHandler);
|
|
|
|
|
|
void renderGuildInvitePopup(game::GameHandler& gameHandler);
|
2026-03-09 14:48:30 -07:00
|
|
|
|
void renderReadyCheckPopup(game::GameHandler& gameHandler);
|
2026-03-10 21:12:28 -07:00
|
|
|
|
void renderBgInvitePopup(game::GameHandler& gameHandler);
|
2026-03-12 22:25:46 -07:00
|
|
|
|
void renderBfMgrInvitePopup(game::GameHandler& gameHandler);
|
2026-03-10 21:40:21 -07:00
|
|
|
|
void renderLfgProposalPopup(game::GameHandler& gameHandler);
|
2026-02-14 14:30:09 -08:00
|
|
|
|
void renderChatBubbles(game::GameHandler& gameHandler);
|
2026-02-15 14:00:41 -08:00
|
|
|
|
void renderMailWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
void renderMailComposeWindow(game::GameHandler& gameHandler);
|
Implement bank, guild bank, and auction house systems
Add 27 new opcodes, packet builders/parsers, handler methods, inventory
extension with 28 bank slots + 7 bank bags, and UI windows for personal
bank, guild bank (6 tabs x 98 slots), and auction house (browse/sell/bid).
Fix Classic gossip parser to omit boxMoney/boxText fields not present in
Vanilla protocol, fix gossip icon labels with text-based NPC type detection,
and add Turtle WoW opcode mappings for bank and auction interactions.
2026-02-16 21:11:18 -08:00
|
|
|
|
void renderBankWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
void renderGuildBankWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
void renderAuctionHouseWindow(game::GameHandler& gameHandler);
|
2026-03-09 13:47:07 -07:00
|
|
|
|
void renderDungeonFinderWindow(game::GameHandler& gameHandler);
|
2026-03-09 15:52:58 -07:00
|
|
|
|
void renderInstanceLockouts(game::GameHandler& gameHandler);
|
2026-03-09 17:01:38 -07:00
|
|
|
|
void renderNameplates(game::GameHandler& gameHandler);
|
2026-03-09 22:42:44 -07:00
|
|
|
|
void renderBattlegroundScore(game::GameHandler& gameHandler);
|
2026-03-12 04:04:27 -07:00
|
|
|
|
void renderDPSMeter(game::GameHandler& gameHandler);
|
2026-03-12 14:25:37 -07:00
|
|
|
|
void renderDurabilityWarning(game::GameHandler& gameHandler);
|
Add gameplay systems: combat, spells, groups, loot, vendors, and UI
Implement ~70 new protocol opcodes across 5 phases while maintaining
full 3.3.5a private server compatibility:
- Phase 1: Server-aware targeting (CMSG_SET_SELECTION), player/creature
name queries, CMSG_SET_ACTIVE_MOVER after login
- Phase 2: Auto-attack, melee/spell damage parsing, health/mana/power
tracking from UPDATE_OBJECT fields, floating combat text
- Phase 3: Spell casting, action bar (12 slots, keys 1-=), cast bar,
cooldown tracking, aura/buff system with cancellation
- Phase 4: Group invite/accept/decline/leave, party frames UI,
/invite chat command
- Phase 5: Loot window, NPC gossip dialog, vendor buy/sell interface
Also: disable debug HUD/panels by default, gate 3D rendering to
IN_GAME state only, fix window resize not updating UI positions.
2026-02-04 10:30:52 -08:00
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
/**
|
|
|
|
|
|
* Inventory screen
|
|
|
|
|
|
*/
|
2026-02-04 22:27:45 -08:00
|
|
|
|
void renderWorldMap(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
InventoryScreen inventoryScreen;
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
|
uint64_t inventoryScreenCharGuid_ = 0; // GUID of character inventory screen was initialized for
|
2026-02-06 13:47:03 -08:00
|
|
|
|
QuestLogScreen questLogScreen;
|
2026-02-04 11:31:08 -08:00
|
|
|
|
SpellbookScreen spellbookScreen;
|
2026-02-06 16:04:25 -08:00
|
|
|
|
TalentScreen talentScreen;
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// WorldMap is now owned by Renderer (accessed via renderer->getWorldMap())
|
2026-02-05 15:07:13 -08:00
|
|
|
|
|
2026-02-06 14:30:54 -08:00
|
|
|
|
// Spell icon cache: spellId -> GL texture ID
|
2026-02-22 03:32:08 -08:00
|
|
|
|
std::unordered_map<uint32_t, VkDescriptorSet> spellIconCache_;
|
2026-02-06 14:30:54 -08:00
|
|
|
|
// SpellIconID -> icon path (from SpellIcon.dbc)
|
|
|
|
|
|
std::unordered_map<uint32_t, std::string> spellIconPaths_;
|
|
|
|
|
|
// SpellID -> SpellIconID (from Spell.dbc field 133)
|
|
|
|
|
|
std::unordered_map<uint32_t, uint32_t> spellIconIds_;
|
|
|
|
|
|
bool spellIconDbLoaded_ = false;
|
2026-02-22 03:32:08 -08:00
|
|
|
|
VkDescriptorSet getSpellIcon(uint32_t spellId, pipeline::AssetManager* am);
|
2026-02-06 19:24:44 -08:00
|
|
|
|
|
2026-03-09 18:28:03 -07:00
|
|
|
|
// 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};
|
|
|
|
|
|
|
2026-02-06 19:24:44 -08:00
|
|
|
|
// Action bar drag state (-1 = not dragging)
|
|
|
|
|
|
int actionBarDragSlot_ = -1;
|
2026-02-22 03:32:08 -08:00
|
|
|
|
VkDescriptorSet actionBarDragIcon_ = VK_NULL_HANDLE;
|
2026-02-07 13:53:03 -08:00
|
|
|
|
|
2026-02-19 22:34:22 -08:00
|
|
|
|
// Bag bar state
|
2026-02-22 03:32:08 -08:00
|
|
|
|
VkDescriptorSet backpackIconTexture_ = VK_NULL_HANDLE;
|
|
|
|
|
|
VkDescriptorSet emptyBagSlotTexture_ = VK_NULL_HANDLE;
|
2026-02-19 22:34:22 -08:00
|
|
|
|
int bagBarPickedSlot_ = -1; // Visual drag in progress (-1 = none)
|
|
|
|
|
|
int bagBarDragSource_ = -1; // Mouse pressed on this slot, waiting for drag or click (-1 = none)
|
Implement complete talent system with dual spec support
Network Protocol:
- Add SMSG_TALENTS_INFO (0x4C0) packet parsing for talent data
- Add CMSG_LEARN_TALENT (0x251) to request learning talents
- Add MSG_TALENT_WIPE_CONFIRM (0x2AB) opcode for spec switching
- Parse talent spec, unspent points, and learned talent ranks
DBC Parsing:
- Load Talent.dbc: talent grid positions, ranks, prerequisites, spell IDs
- Load TalentTab.dbc: talent tree definitions with correct field indices
- Fix localized string field handling (17 fields per string)
- Load Spell.dbc and SpellIcon.dbc for talent icons and tooltips
- Class mask filtering using bitwise operations (1 << (class - 1))
UI Implementation:
- Complete talent tree UI with tabbed interface for specs
- Display talent icons from spell data with proper tinting/borders
- Enhanced tooltips: spell name, rank, current/next descriptions, prereqs
- Visual states: green (maxed), yellow (partial), white (available), gray (locked)
- Tier unlock system (5 points per tier requirement)
- Rank overlay on icons with shadow text
- Click to learn talents with validation
Dual Spec Support:
- Store unspent points and learned talents per spec (0 and 1)
- Track active spec and display its talents
- Spec switching UI with buttons for Spec 1/Spec 2
- Handle both SMSG_TALENTS_INFO packets from server at login
- Display unspent points for both specs in header
- Independent talent trees for each specialization
2026-02-10 02:00:13 -08:00
|
|
|
|
|
2026-03-12 10:41:18 -07:00
|
|
|
|
// Who Results window
|
|
|
|
|
|
bool showWhoWindow_ = false;
|
|
|
|
|
|
void renderWhoWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
feat: add persistent combat log window (/combatlog or /cl)
Stores up to 500 combat events in a rolling deque alongside the existing
floating combat text. Events are populated via the existing addCombatText()
call site, resolving attacker/target names from the entity manager and
player name cache at event time.
- CombatLogEntry struct in spell_defines.hpp (type, amount, spellId,
isPlayerSource, timestamp, sourceName, targetName)
- getCombatLog() / clearCombatLog() accessors on GameHandler
- renderCombatLog() in GameScreen: scrollable two-column table (Time +
Event), color-coded by event category, with Damage/Healing/Misc filter
checkboxes, auto-scroll toggle, and Clear button
- /combatlog (/cl) chat command toggles the window
2026-03-12 11:00:10 -07:00
|
|
|
|
// Combat Log window
|
|
|
|
|
|
bool showCombatLog_ = false;
|
|
|
|
|
|
void renderCombatLog(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
2026-03-09 15:52:58 -07:00
|
|
|
|
// Instance Lockouts window
|
|
|
|
|
|
bool showInstanceLockouts_ = false;
|
|
|
|
|
|
|
2026-03-09 13:47:07 -07:00
|
|
|
|
// Dungeon Finder state
|
|
|
|
|
|
bool showDungeonFinder_ = false;
|
2026-03-12 02:09:35 -07:00
|
|
|
|
|
|
|
|
|
|
// Achievements window
|
|
|
|
|
|
bool showAchievementWindow_ = false;
|
|
|
|
|
|
char achievementSearchBuf_[128] = {};
|
|
|
|
|
|
void renderAchievementWindow(game::GameHandler& gameHandler);
|
2026-03-12 02:31:12 -07:00
|
|
|
|
|
2026-03-17 20:46:41 -07:00
|
|
|
|
// Skills / Professions window (K key)
|
|
|
|
|
|
bool showSkillsWindow_ = false;
|
|
|
|
|
|
void renderSkillsWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
2026-03-12 20:23:36 -07:00
|
|
|
|
// Titles window
|
|
|
|
|
|
bool showTitlesWindow_ = false;
|
|
|
|
|
|
void renderTitlesWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
2026-03-12 20:28:03 -07:00
|
|
|
|
// Equipment Set Manager window
|
|
|
|
|
|
bool showEquipSetWindow_ = false;
|
|
|
|
|
|
void renderEquipSetWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
2026-03-12 02:31:12 -07:00
|
|
|
|
// GM Ticket window
|
feat: parse SMSG_GMTICKET_GETTICKET/SYSTEMSTATUS and SMSG_SPELLINSTAKILLLOG
Previously SMSG_GMTICKET_GETTICKET and SMSG_GMTICKET_SYSTEMSTATUS were
silently consumed. Now both are fully parsed:
- SMSG_GMTICKET_GETTICKET decodes all four status codes (no ticket,
open ticket, closed, suspended), extracts ticket text, age and
server-estimated wait time, and stores them on GameHandler.
- SMSG_GMTICKET_SYSTEMSTATUS shows a chat message when GM support
goes offline/online.
- Added requestGmTicket() (sends CMSG_GMTICKET_GETTICKET) called
automatically when the GM Ticket UI window is opened, so the player
sees their existing open ticket text and wait time on first open.
- GM Ticket UI window now shows current-ticket status bar, estimated
wait time, and hides the Delete button when no ticket is active.
Also implements SMSG_SPELLINSTAKILLLOG (previously silently consumed):
parses caster/victim/spellId for all expansions and emits combat text
when the local player is involved in an instant-kill spell event (e.g.
Execute, Obliterate).
2026-03-12 22:14:46 -07:00
|
|
|
|
bool showGmTicketWindow_ = false;
|
|
|
|
|
|
bool gmTicketWindowWasOpen_ = false; ///< Previous frame state; used to fire one-shot query
|
2026-03-12 02:31:12 -07:00
|
|
|
|
char gmTicketBuf_[2048] = {};
|
|
|
|
|
|
void renderGmTicketWindow(game::GameHandler& gameHandler);
|
2026-03-12 02:52:40 -07:00
|
|
|
|
|
2026-03-12 19:42:31 -07:00
|
|
|
|
// Pet rename modal (triggered from pet frame context menu)
|
|
|
|
|
|
bool petRenameOpen_ = false;
|
|
|
|
|
|
char petRenameBuf_[16] = {};
|
|
|
|
|
|
|
2026-03-12 02:52:40 -07:00
|
|
|
|
// Inspect window
|
|
|
|
|
|
bool showInspectWindow_ = false;
|
|
|
|
|
|
void renderInspectWindow(game::GameHandler& gameHandler);
|
2026-03-12 02:59:09 -07:00
|
|
|
|
|
2026-03-12 18:21:50 -07:00
|
|
|
|
// Readable text window (books / scrolls / notes)
|
|
|
|
|
|
bool showBookWindow_ = false;
|
|
|
|
|
|
int bookCurrentPage_ = 0;
|
|
|
|
|
|
void renderBookWindow(game::GameHandler& gameHandler);
|
|
|
|
|
|
|
2026-03-12 02:59:09 -07:00
|
|
|
|
// Threat window
|
|
|
|
|
|
bool showThreatWindow_ = false;
|
|
|
|
|
|
void renderThreatWindow(game::GameHandler& gameHandler);
|
2026-03-12 12:02:59 -07:00
|
|
|
|
|
|
|
|
|
|
// BG scoreboard window
|
|
|
|
|
|
bool showBgScoreboard_ = false;
|
|
|
|
|
|
void renderBgScoreboard(game::GameHandler& gameHandler);
|
2026-03-09 13:47:07 -07:00
|
|
|
|
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
|
|
|
|
|
|
uint32_t lfgSelectedDungeon_ = 861; // default: random dungeon (entry 861 = Random Dungeon WotLK)
|
|
|
|
|
|
|
2026-02-14 18:27:59 -08:00
|
|
|
|
// 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;
|
2026-02-16 21:16:25 -08:00
|
|
|
|
bool chatAutoJoinLocal_ = true;
|
2026-02-14 18:27:59 -08:00
|
|
|
|
|
|
|
|
|
|
// Join channel input buffer
|
|
|
|
|
|
char joinChannelBuffer_[128] = "";
|
|
|
|
|
|
|
Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
2026-02-07 15:29:19 -08:00
|
|
|
|
static std::string getSettingsPath();
|
|
|
|
|
|
|
2026-02-09 17:39:21 -08:00
|
|
|
|
// Gender placeholder replacement
|
|
|
|
|
|
std::string replaceGenderPlaceholders(const std::string& text, game::GameHandler& gameHandler);
|
|
|
|
|
|
|
2026-02-14 14:30:09 -08:00
|
|
|
|
// 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;
|
2026-03-11 23:10:21 -07:00
|
|
|
|
bool levelUpCallbackSet_ = false;
|
2026-03-12 00:56:31 -07:00
|
|
|
|
bool achievementCallbackSet_ = false;
|
2026-02-14 14:30:09 -08:00
|
|
|
|
|
2026-02-15 14:00:41 -08:00
|
|
|
|
// Mail compose state
|
|
|
|
|
|
char mailRecipientBuffer_[256] = "";
|
|
|
|
|
|
char mailSubjectBuffer_[256] = "";
|
|
|
|
|
|
char mailBodyBuffer_[2048] = "";
|
|
|
|
|
|
int mailComposeMoney_[3] = {0, 0, 0}; // gold, silver, copper
|
|
|
|
|
|
|
2026-03-11 21:19:47 -07:00
|
|
|
|
// Vendor search filter
|
|
|
|
|
|
char vendorSearchFilter_[128] = "";
|
|
|
|
|
|
|
2026-03-11 21:21:14 -07:00
|
|
|
|
// Trainer search filter
|
|
|
|
|
|
char trainerSearchFilter_[128] = "";
|
|
|
|
|
|
|
Implement bank, guild bank, and auction house systems
Add 27 new opcodes, packet builders/parsers, handler methods, inventory
extension with 28 bank slots + 7 bank bags, and UI windows for personal
bank, guild bank (6 tabs x 98 slots), and auction house (browse/sell/bid).
Fix Classic gossip parser to omit boxMoney/boxText fields not present in
Vanilla protocol, fix gossip icon labels with text-based NPC type detection,
and add Turtle WoW opcode mappings for bank and auction interactions.
2026-02-16 21:11:18 -08:00
|
|
|
|
// 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;
|
2026-02-25 14:44:44 -08:00
|
|
|
|
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)
|
Implement bank, guild bank, and auction house systems
Add 27 new opcodes, packet builders/parsers, handler methods, inventory
extension with 28 bank slots + 7 bank bags, and UI windows for personal
bank, guild bank (6 tabs x 98 slots), and auction house (browse/sell/bid).
Fix Classic gossip parser to omit boxMoney/boxText fields not present in
Vanilla protocol, fix gossip icon labels with text-based NPC type detection,
and add Turtle WoW opcode mappings for bank and auction interactions.
2026-02-16 21:11:18 -08:00
|
|
|
|
|
|
|
|
|
|
// Guild bank money input
|
|
|
|
|
|
int guildBankMoneyInput_[3] = {0, 0, 0}; // gold, silver, copper
|
|
|
|
|
|
|
2026-02-07 13:53:03 -08:00
|
|
|
|
// Left-click targeting: distinguish click from camera drag
|
|
|
|
|
|
glm::vec2 leftClickPressPos_ = glm::vec2(0.0f);
|
|
|
|
|
|
bool leftClickWasPress_ = false;
|
2026-02-17 17:23:42 -08:00
|
|
|
|
|
|
|
|
|
|
// Level-up ding animation
|
2026-03-12 17:54:49 -07:00
|
|
|
|
static constexpr float DING_DURATION = 4.0f;
|
2026-02-17 17:23:42 -08:00
|
|
|
|
float dingTimer_ = 0.0f;
|
|
|
|
|
|
uint32_t dingLevel_ = 0;
|
2026-03-12 17:54:49 -07:00
|
|
|
|
uint32_t dingHpDelta_ = 0;
|
|
|
|
|
|
uint32_t dingManaDelta_ = 0;
|
|
|
|
|
|
uint32_t dingStats_[5] = {}; // str/agi/sta/int/spi deltas
|
2026-02-17 17:23:42 -08:00
|
|
|
|
void renderDingEffect();
|
|
|
|
|
|
|
2026-03-09 13:53:42 -07:00
|
|
|
|
// Achievement toast banner
|
|
|
|
|
|
static constexpr float ACHIEVEMENT_TOAST_DURATION = 5.0f;
|
|
|
|
|
|
float achievementToastTimer_ = 0.0f;
|
|
|
|
|
|
uint32_t achievementToastId_ = 0;
|
2026-03-10 20:53:21 -07:00
|
|
|
|
std::string achievementToastName_;
|
2026-03-09 13:53:42 -07:00
|
|
|
|
void renderAchievementToast();
|
|
|
|
|
|
|
2026-03-12 15:42:55 -07:00
|
|
|
|
// 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();
|
|
|
|
|
|
|
2026-03-12 15:53:45 -07:00
|
|
|
|
// 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();
|
|
|
|
|
|
|
2026-03-12 15:57:09 -07:00
|
|
|
|
// 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();
|
|
|
|
|
|
|
2026-03-12 16:12:21 -07:00
|
|
|
|
// 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);
|
|
|
|
|
|
|
2026-03-12 16:19:25 -07:00
|
|
|
|
// 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();
|
|
|
|
|
|
|
2026-03-12 16:24:11 -07:00
|
|
|
|
// 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();
|
|
|
|
|
|
|
2026-03-12 16:33:08 -07:00
|
|
|
|
// 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;
|
2026-03-14 08:31:08 -07:00
|
|
|
|
bool ghostOpacityStateKnown_ = false;
|
|
|
|
|
|
bool ghostOpacityLastState_ = false;
|
|
|
|
|
|
uint32_t ghostOpacityLastInstanceId_ = 0;
|
2026-03-12 16:33:08 -07:00
|
|
|
|
void renderResurrectFlash();
|
|
|
|
|
|
|
2026-03-09 17:06:12 -07:00
|
|
|
|
// Zone discovery text ("Entering: <ZoneName>")
|
|
|
|
|
|
static constexpr float ZONE_TEXT_DURATION = 5.0f;
|
|
|
|
|
|
float zoneTextTimer_ = 0.0f;
|
|
|
|
|
|
std::string zoneTextName_;
|
|
|
|
|
|
std::string lastKnownZoneName_;
|
2026-03-17 19:14:17 -07:00
|
|
|
|
uint32_t lastKnownWorldStateZoneId_ = 0;
|
|
|
|
|
|
void renderZoneText(game::GameHandler& gameHandler);
|
2026-03-17 16:34:39 -07:00
|
|
|
|
void renderWeatherOverlay(game::GameHandler& gameHandler);
|
2026-03-09 17:06:12 -07:00
|
|
|
|
|
2026-03-12 15:25:07 -07:00
|
|
|
|
// Cooldown tracker
|
|
|
|
|
|
bool showCooldownTracker_ = false;
|
|
|
|
|
|
|
2026-03-12 04:04:27 -07:00
|
|
|
|
// DPS / HPS meter
|
|
|
|
|
|
bool showDPSMeter_ = false;
|
|
|
|
|
|
float dpsCombatAge_ = 0.0f; // seconds in current combat (for accurate early-combat DPS)
|
|
|
|
|
|
bool dpsWasInCombat_ = false;
|
2026-03-12 11:40:31 -07:00
|
|
|
|
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
|
2026-03-12 04:04:27 -07:00
|
|
|
|
|
2026-02-17 17:23:42 -08:00
|
|
|
|
public:
|
2026-03-12 17:54:49 -07:00
|
|
|
|
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);
|
2026-03-10 20:53:21 -07:00
|
|
|
|
void triggerAchievementToast(uint32_t achievementId, std::string name = {});
|
2026-03-12 21:24:42 -07:00
|
|
|
|
void openDungeonFinder() { showDungeonFinder_ = true; }
|
2026-02-02 12:24:50 -08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-02-06 14:30:54 -08:00
|
|
|
|
} // namespace ui
|
|
|
|
|
|
} // namespace wowee
|