Commit graph

337 commits

Author SHA1 Message Date
Kelsi
3c0e58bff4 Show item icon and quality color in buyback table 2026-03-11 20:52:42 -07:00
Kelsi
647967cccb Show item icons in vendor window item list 2026-03-11 20:49:25 -07:00
Kelsi
764cf86e38 Show spell icons in trainer window with dimming for unavailable spells 2026-03-11 20:48:03 -07:00
Kelsi
d9a58115f9 Show item icons and rich tooltips in trade window slots 2026-03-11 20:42:26 -07:00
Kelsi
4ceb313fb2 Show item icons in quest turn-in required items list 2026-03-11 20:41:02 -07:00
Kelsi
1e8c85d850 Show item icons in mail read-view attachment list 2026-03-11 20:39:15 -07:00
Kelsi
26fab2d5d0 Show item icons in guild bank window
Replace text-only buttons with icon+draw-list rendering that matches
the style of the regular bank, loot, and vendor windows. Item icons are
looked up via inventoryScreen.getItemIcon(info->displayInfoId); falls
back to a coloured bordered square with two-letter abbreviation when
the texture is not yet cached. Stack count is overlaid in the
bottom-right corner. Withdraw still fires on left-click.
2026-03-11 20:33:46 -07:00
Kelsi
8c2f69ca0e Rate-limit icon GPU uploads in spellbook, action bar, and inventory screens
Opening the spellbook on a new tab, logging in with many auras/action slots, or
opening a full bag all triggered synchronous BLP-decode + GPU uploads for every
uncached icon in one frame, causing a visible stall. Apply the same 4-per-frame
upload cap that was added to talent_screen, so icons load progressively.
2026-03-11 20:17:41 -07:00
Kelsi
711cb966ef Fix chest interaction and measure server RTT for latency meter
Chests (and lockboxes, coffers, etc.) failed to open because CMSG_LOOT
was only sent on Classic/Turtle expansions, and only when GO type was
already cached as type 3.  Fix: always send CMSG_LOOT after
CMSG_GAMEOBJ_USE (server silently ignores it for non-lootable objects).
Also broaden CMSG_GAMEOBJ_REPORT_USE to all non-mailbox WotLK GOs.

Latency meter: record pingTimestamp_ in sendPing() and compute RTT in
handlePong(); add toggleable "Show Latency Meter" checkbox in Interface
settings (saved to settings.cfg).
2026-03-11 19:45:03 -07:00
Kelsi
14f672ab6a Pre-query vendor item information to avoid placeholder display
Proactively call ensureItemInfo() for both vendor items and buyback items
during rendering. This ensures item names and stats are available before
display, eliminating "Item <id>" placeholders and providing instant tooltip
info, matching the pattern used for quest rewards and action bar items.
2026-03-11 19:29:10 -07:00
Kelsi
9b9d56543c Re-query player names during rendering to resolve pending queries
When a player nameplate is about to render with an empty name (showing
"Player (level)" placeholder), actively re-request the name query. Since
queryPlayerName() is idempotent (won't duplicate pending queries), this
ensures that slow network responses don't cause players to permanently
display as "Player (67)" even after the response arrives. Rendering code
now triggers name queries to completion before falling back to placeholders.
2026-03-11 18:53:23 -07:00
Kelsi
f7c752a316 Hide nameplates/health bars for corpses except when selected
Corpses no longer display nameplates or health bars unless they are the current
target (selected for loot or skinning). When selected, corpses show a minimal
grey nameplate with no health fill.
2026-03-11 16:54:30 -07:00
Kelsi
6f7c57d975 feat: add graphics quality presets system
Implement quick-access quality presets (Low, Medium, High, Ultra) that adjust multiple graphics settings at once for better user experience. Each preset configures:
- Shadow rendering and distance
- Anti-aliasing (MSAA) level
- Normal mapping and parallax mapping
- Ground clutter density

The system automatically detects when settings deviate from a preset and marks them as "Custom". Presets are persisted to settings.cfg for consistency across sessions. Users can quickly switch between performance and quality modes or tweak individual settings as needed.
2026-03-11 15:21:48 -07:00
Kelsi
1808d98978 feat: implement TOGGLE_MINIMAP and TOGGLE_RAID_FRAMES keybindings
- Add showMinimap_ and showRaidFrames_ visibility flags to GameScreen
- Wire up TOGGLE_MINIMAP (M key) to toggle minimap visibility
- Wire up TOGGLE_RAID_FRAMES (F key) to toggle party/raid frame visibility
- Conditional rendering of minimap markers and party frames
- Completes keybinding manager integration for all 15 customizable actions
2026-03-11 09:24:37 -07:00
Kelsi
1aa404d670 refactor: use keybinding manager for Escape (settings) and Enter (chat) keys
- Replace hardcoded SDL_SCANCODE_ESCAPE with TOGGLE_SETTINGS keybinding
- Replace hardcoded SDL_SCANCODE_RETURN with TOGGLE_CHAT keybinding
- Allows customization of these keys through Settings UI
2026-03-11 09:08:15 -07:00
Kelsi
f3415c2aff feat: implement TOGGLE_INVENTORY keybinding for I key in game_screen
- Add inventory window toggle on I key press
- Integrates with keybinding manager system for customizable inventory key
2026-03-11 09:05:17 -07:00
Kelsi
a3e0d36a72 feat: add World Map visibility toggle with keybinding support
Implement showWorldMap_ state variable and TOGGLE_WORLD_MAP keybinding
integration to allow players to customize the W key binding for opening/
closing the World Map, consistent with other window toggles like Nameplates
(V key) and Guild Roster (O key).
2026-03-11 07:38:08 -07:00
Kelsi
0d9404c704 feat: expand keybinding system with 4 new customizable actions
- Add World Map (W), Nameplates (V), Raid Frames (R), Quest Log (Q) to
  KeybindingManager enum with customizable default bindings
- Replace hard-coded V key check for nameplate toggle with
  KeybindingManager::isActionPressed() to support customization
- Update config file persistence to handle new bindings
- Infrastructure in place for implementing visibility toggles on other
  windows (World Map, Raid Frames, Quest Log) with future UI refactoring
2026-03-11 07:19:54 -07:00
Kelsi
f7a79b436e feat: integrate keybinding customization UI into Settings window
- Extended KeybindingManager enum with TOGGLE_GUILD_ROSTER (O) and
  TOGGLE_DUNGEON_FINDER (J) to replace hard-coded key checks
- Added Controls tab in Settings UI for rebinding all 10 customizable actions
- Implemented real-time key capture and binding with visual feedback
- Integrated keybinding persistence with main settings.cfg file
- Replaced hard-coded O key (Guild Roster) and I key (Dungeon Finder) checks
  with KeybindingManager::isActionPressed() calls
- Added Reset to Defaults button for restoring original keybindings
2026-03-11 06:51:48 -07:00
Kelsi
79c8d93c45 fix: use expansion-aware field indices for spell icon loading
The spell icon loader was incorrectly assuming WotLK field 133 (IconID)
for any DBC with >= 200 fields. This breaks Classic/TBC where IconID
is at different fields:
- Classic: field 117
- TBC: field 124
- WotLK: field 133

Now always uses expansion-aware layout (spellL) when available, falling
back to hardcoded field 133 only if the layout is missing.

Fixes missing spell icons on Classic and TBC expansions.
2026-03-11 05:26:38 -07:00
Kelsi
fb01361837 feat: show blocked amount and reduced damage on VICTIMSTATE_BLOCKS
When an attack is partially blocked, the server sends the remaining
damage in totalDamage and the blocked amount in data.blocked. Show
both: the damage taken and a 'Block N' entry. When block amount is
zero (full block with no damage), just show 'Block'.
2026-03-11 03:36:45 -07:00
Kelsi
d2ae4d8215 feat: show partial absorb/resist amounts in spell combat text
handleSpellDamageLog now emits ABSORB/RESIST entries when data.absorbed
or data.resisted are nonzero, so players see 'Absorbed 123' alongside
damage numbers (e.g. vs. Power Word: Shield or Ice Barrier).
handleSpellHealLog does the same for heal absorbs (e.g. Vampiric Embrace
counter-absorbs). renderCombatText now formats amount when nonzero.
2026-03-11 03:28:19 -07:00
Kelsi
e902375763 feat: add ABSORB and RESIST combat text types for spell misses
Adds dedicated CombatTextEntry::Type entries for ABSORB (miss type 7)
and RESIST (miss type 8), replacing the generic MISS display. Updates
missTypes arrays in SMSG_SPELLLOGMISS and SMSG_SPELL_GO, and adds
light-blue "Absorb" and grey "Resist" rendering in the combat text overlay.
2026-03-11 03:23:01 -07:00
Kelsi
f462db6bfa fix: terrain descriptor pool leak, minimap quest markers, and item comparison UI
- terrain_renderer: add FREE_DESCRIPTOR_SET_BIT flag and vkFreeDescriptorSets
  in destroyChunkGPU so material descriptor sets are returned to the pool;
  prevents GPU device lost from pool exhaustion near populated areas
- game_screen: fix projectToMinimap to use the exact inverse of the minimap
  shader transform so quest objective markers appear at the correct position
  and orientation regardless of camera bearing
- inventory_screen: fix item comparison tooltip to not compare equipped items
  against themselves (character screen); add item level diff line; show (=)
  indicator when stats are equal rather than bare value which looked identical
  to the item's own tooltip
2026-03-11 01:29:56 -07:00
Kelsi
568c566e1a fix: correct quest offer reward parser and trade slot trail size
- QuestOfferRewardParser: replace 4-variant heuristic with 0..16 byte
  prefix scan × fixed/variable arrays (34 candidates total).  AzerothCore
  WotLK 3.3.5a sends uint32 autoFinish + uint32 suggestedPlayers = 8 bytes
  before emoteCount; old uint8 read caused 3-byte misalignment, producing
  wrong item IDs and missing icons on quest reward windows.  Scoring now
  strongly favours the 8-byte prefix and exact byte consumption.
- Quest reward tooltip: delegate to InventoryScreen::renderItemTooltip()
  for full stats (armor, DPS, stats, bind type, etc.); show "Loading…"
  while item data is still fetching instead of showing nothing.
- SMSG_TRADE_STATUS_EXTENDED: fix SLOT_TRAIL 49→52 bytes.  AC 3.3.5a
  sends giftCreatorGuid(8) + 6 enchant slots(24) + randPropId(4) +
  suffixFactor(4) + durability(4) + maxDurability(4) + createPlayedTime(4)
  = 52 bytes after isWrapped; wrong skip misaligned all subsequent slots.
2026-03-11 01:00:08 -07:00
Kelsi
06facc0060 feat: implement trade window UI with item slots and gold offering
Previously trade only showed an accept/decline popup with no way to
actually offer items or gold. This commit adds the complete trade flow:

Packets:
- CMSG_SET_TRADE_ITEM (tradeSlot, bag, bagSlot) — add item to slot
- CMSG_CLEAR_TRADE_ITEM (tradeSlot) — remove item from slot
- CMSG_SET_TRADE_GOLD (uint64 copper) — set gold offered
- CMSG_UNACCEPT_TRADE — unaccept without cancelling
- SMSG_TRADE_STATUS_EXTENDED parser — updates trade slot/gold state

State:
- TradeSlot struct: itemId, displayId, stackCount, bag, bagSlot
- myTradeSlots_/peerTradeSlots_ arrays (6 slots each)
- myTradeGold_/peerTradeGold_ (copper)
- resetTradeState() helper clears all state on cancel/complete/close

UI (renderTradeWindow):
- Two-column layout: my offer | peer offer
- Each column shows 6 item slots with item names
- Double-click own slot to remove; right-click empty slot to open
  backpack picker popup
- Gold input field (copper, Enter to set)
- Accept Trade / Cancel buttons
- Window close button triggers cancel trade
2026-03-11 00:44:07 -07:00
Kelsi
77ce54833a feat: add quest kill objective indicator (⚔) to unit nameplates
Yellow crossed-swords icon appears to the right of the unit name when
the creature's entry is an incomplete kill objective in a tracked quest.
Updated icon is suppressed once the kill count is satisfied.

Uses unit->getEntry() (Unit subclass method) rather than the base
Entity pointer, matching how questKillEntries keys are stored.
2026-03-11 00:29:35 -07:00
Kelsi
12aa5e01b6 fix: correct game-object quest objective handling and item count fallback
- SMSG_QUESTUPDATE_ADD_KILL: use absolute value of npcOrGoId when looking
  up required count from killObjectives (negative values = game objects)
- applyPackedKillCountsFromFields: same fix — use abs(npcOrGoId) as map key
  so GO objective counts are stored with the correct entry key
- SMSG_QUESTUPDATE_ADD_ITEM: also match quests via itemObjectives when
  requiredItemCounts is not yet populated (race at quest accept time)
- Quest log and minimap sidebar: fall back to GO name cache for entries
  that return empty from getCachedCreatureName (interact/loot objectives)
2026-03-11 00:13:09 -07:00
Kelsi
8f2974b17c feat: add standalone LFG group-found popup (renderLfgProposalPopup)
Shows a centered modal when LfgState::Proposal is active regardless of
whether the Dungeon Finder window is open, matching WoW behaviour where
the accept/decline prompt always appears over the game world.
Mirrors the BG invite popup pattern; buttons call lfgAcceptProposal().
2026-03-10 21:40:21 -07:00
Kelsi
b4469b1577 fix: correct buff bar and quest tracker vertical positions
- Buff bar was at Y=140 which overlaps the minimap (Y=10 to Y=210);
  moved to Y=215 (just below minimap bottom edge) with 8 icons per row
- Quest tracker moved from Y=200 (inside minimap area) to Y=320 to
  leave space for up to 3 rows of buffs between minimap and tracker
- Both are right-anchored and no longer conflict with the minimap or
  each other in typical usage (up to ~20 active auras)
2026-03-10 21:32:58 -07:00
Kelsi
a7474b96cf fix: move buff bar to top-right, split buffs/debuffs, raise aura cap to 40
- Relocates buff bar from top-left Y=145 (overlapping party frames) to
  top-right (screenW - barW - 10, 140) where it doesn't conflict with
  party/raid frames anchored on the left side
- Increases max shown auras from 16 to 40 (WotLK supports 48 slots)
- Two-pass rendering: buffs shown first, debuffs below with a spacing gap
  between them; both still use green/red borders for visual distinction
- Widens row to 12 icons for better horizontal use of screen space
2026-03-10 21:29:47 -07:00
Kelsi
5fbeb7938c feat: right-click context menu for party member frames
Right-clicking a party member name in the 5-man party frame opens
a context menu with: Target, Set Focus, Whisper, Trade, Inspect.
- Whisper switches chat type to WHISPER and pre-fills the target name
- Trade calls GameHandler::initiateTrade(guid)
- Inspect sets target then calls GameHandler::inspectTarget()
- Uses BeginPopupContextItem tied to the Selectable widget
2026-03-10 21:27:26 -07:00
Kelsi
bc18fb7c3e feat: leader crown and LFG role indicators in party/raid frames
- Party frames: gold star prefix and gold name color for group leader;
  LFG role badges [T]/[H]/[D] shown inline after member name
- Raid frames: leader name rendered in gold with a corner star marker;
  role letter (T/H/D) drawn in bottom-right corner of each compact cell;
  uses partyData.leaderGuid already present in the function scope
- Minimap party dots already use gold for leader (unchanged)
2026-03-10 21:24:40 -07:00
Kelsi
4a445081d8 feat: latency indicator, BG queue status, and ToT improvements
- Add latency indicator below minimap (color-coded: green/yellow/orange/red)
  using the lastLatency value measured via CMSG_PING/SMSG_PONG
- Add BG queue status indicator below minimap when in WAIT_QUEUE
  (abbreviated name: AV/WSG/AB/EotS etc.)
- Target-of-Target frame: add level display and click-to-target support
- Expose getLatencyMs() accessor on GameHandler
2026-03-10 21:19:42 -07:00
Kelsi
8ab83987f1 feat: focus target frame with health/power bars and cast bar
Add a compact focus target frame on the right side of the screen
when the player has a focus target set via /focus.

- Shows [Focus] label, name (colored by hostility/level diff), level
- HP bar with green→yellow→red coloring; power bar with type colors
- Cast bar showing spell name and remaining time when focus is casting
- Clicking the frame targets the focus entity
- Clears automatically when focus is lost (/clearfocus)
2026-03-10 21:15:24 -07:00
Kelsi
a7a559cdcc feat: battleground invitation popup with countdown timer
Replace the text-only "/join to enter" message with an interactive
popup that shows the BG name, a live countdown progress bar, and
Enter/Leave Queue buttons.

- Parse STATUS_WAIT_JOIN timeout from SMSG_BATTLEFIELD_STATUS
- Store inviteReceivedTime (steady_clock) on the queue slot
- BgQueueSlot moved to public section so UI can read invite details
- Add declineBattlefield() that sends CMSG_BATTLEFIELD_PORT(action=0)
- acceptBattlefield() optimistically sets statusId=3 to dismiss popup
- renderBgInvitePopup: colored countdown bar (green→yellow→red),
  named BG (Alterac Valley, Warsong Gulch, etc.), auto-dismisses on expiry
2026-03-10 21:12:28 -07:00
Kelsi
4986308581 feat: rich item tooltips in vendor and loot-roll windows
- Vendor window: replace manual stat-only tooltip with full renderItemTooltip
  (now shows bind type, slot, weapon stats, armor, extra stats, spell effects,
  flavor text, and sell price — consistent with inventory)
- Loot-roll popup: add item icon and hover tooltip via renderItemTooltip
- Loot-roll: pre-fetch item info via queryItemInfo when roll prompt appears
2026-03-10 20:59:02 -07:00
Kelsi
6275a45ec0 feat: achievement name in toast, parse earned achievements, loot item tooltips
- Parse SMSG_ALL_ACHIEVEMENT_DATA on login to populate earnedAchievements_ set
- Pass achievement name through callback so toast shows name instead of ID
- Add renderItemTooltip(ItemQueryResponseData) overload for loot/non-inventory contexts
- Loot window now shows full item tooltip on hover (stats, sell price, bind type, etc.)
2026-03-10 20:53:21 -07:00
Kelsi
28550dbc99 fix: reduce GO fallback hit radius to prevent invisible chair click-lock
Fallback sphere for GameObjects without a loaded renderer instance was 2.5f,
causing invisible/unloaded chairs in Goldshire Inn to be accidentally targeted
during camera right-drag. This sent CMSG_GAMEOBJ_USE which set server stand
state to SIT, trapping the player until a stand-up packet was sent.

Reduce fallback radius to 1.2f and height offset to 1.0f so only deliberate
close-range direct clicks register on unloaded GO geometry.
2026-03-10 19:59:23 -07:00
Kelsi
564a286282 fix: stand-up-on-move and nameplate position tracking
Camera controller / sitting:
- Any movement key (WASD/QE/Space) pressed while sitting now clears the
  sitting flag immediately, matching WoW's sit-to-stand-on-move behaviour
- Added StandUpCallback: when the player stands up via local input the
  callback fires setStandState(0) → CMSG_STAND_STATE_CHANGE(STAND) so
  the server releases the sit lock and restores normal movement
- Fixes character getting stuck in sit state after accidentally
  right-clicking a chair GO in Goldshire Inn (or similar)

Nameplates:
- Use getRenderPositionForGuid() (renderer visual position) as primary
  source for nameplate anchor, falling back to entity X/Y/Z only when
  no render instance exists yet; keeps health bars in sync with the
  rendered model instead of the parallel entity interpolator
2026-03-10 19:49:33 -07:00
Kelsi
34bab8edd6 feat: use rich spell tooltip for buff/debuff frame icons
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
Player buff bar and target debuff bar icons now show full spell tooltip
(school, cost, cast time, range, description) on hover, matching the
action bar and spellbook. Falls back to plain spell name if DBC is not
loaded. Remaining aura duration is shown below the spell body.
2026-03-10 19:33:25 -07:00
Kelsi
caf0d18393 feat: show rich spell tooltip on action bar hover
Expose SpellbookScreen::renderSpellInfoTooltip() as a public method,
then use it in the action bar slot tooltip. Action bar spell tooltips
now show the same full tooltip as the spellbook: spell school (colored),
mana/rage/energy cost, cast time, range, cooldown, and description.

Falls back to a plain spell name if DBC data is not yet loaded.
Hearthstone location note is appended after the rich body.
Cooldown text moved inside each branch for consistent styling.
2026-03-10 19:31:46 -07:00
Kelsi
7bbf2c7769 refactor: improve quest offer reward item display
- Use getQualityColor() for consistent quality coloring (choice+fixed)
- Show item icons for fixed rewards (previously text-only)
- Replace useless "Reward option" tooltip with real item name+description
- Render icon before selectable label (not after) for choice rewards
- Call ensureItemInfo for all reward items to trigger async fetch
- Use structured bindings (C++17) to unify icon+color resolution
2026-03-10 19:25:26 -07:00
Kelsi
458a95ae8e refactor: use quality colors and hover tooltips for quest reward items
Replace flat white coloring with item quality colors and add hover tooltips
showing item name (quality-colored) and description for quest acceptance window.
Extract renderQuestRewardItem lambda to eliminate code duplication between
choice and fixed reward item rendering.
2026-03-10 19:12:43 -07:00
Kelsi
1ff48259cc feat: display quest reward items in quest details acceptance window
Parse and store reward items (choice and fixed) from SMSG_QUESTGIVER_QUEST_DETAILS
in both WotLK (QuestDetailsParser) and TBC/Classic (TbcPacketParsers) parsers.
Show item icons, names, and counts in the quest acceptance dialog alongside XP/money.
Move QuestRewardItem before QuestDetailsData in header to fix forward-reference.
2026-03-10 19:05:34 -07:00
Kelsi
373dbbf95d fix: use authoritative autocast state for pet action bar and correct tooltip labels
- Use isPetSpellAutocast() instead of parsing the slot value high byte for
  autocast detection; the authoritative source is the SMSG_PET_SPELLS spell
  list activeFlags, not the action bar slot value.
- Fix tooltip mapping: actionId==2 maps to "Follow", actionId==5 to "Attack",
  others to "Stay" (removed erroneous duplicate Follow case for actionId==4).
- Update spellbook comment: TBC Spell.dbc has ~220+ fields (not ~167).
2026-03-10 18:37:05 -07:00
Kelsi
2e38a9af65 feat: add pet action bar to pet frame UI
Show the 10 SMSG_PET_SPELLS action slots as clickable icon/text buttons
in the pet frame. Spell slots with icons render as ImageButtons; built-in
commands (Attack/Follow/Stay) render as text buttons. Autocast-on slots
are tinted green. Clicking a spell slot sends CMSG_PET_ACTION with the
current target GUID; built-in commands send without a target. Tooltips
show the spell name on hover.
2026-03-10 18:26:02 -07:00
Kelsi
0afa41e908 feat: implement item durability tracking and vendor repair
- Add ITEM_FIELD_DURABILITY (60) and ITEM_FIELD_MAXDURABILITY (61) to
  update_field_table.hpp enum and wotlk/update_fields.json
- Add curDurability/maxDurability to OnlineItemInfo and ItemDef structs
- Parse durability fields in OBJECT_CREATE and OBJECT_VALUES handlers;
  preserve existing values on partial updates (fixes stale durability
  being reset to 0 on stack-count-only updates)
- Propagate durability to ItemDef in all 5 rebuildOnlineInventory() paths
- Implement GameHandler::repairItem() and repairAll() via CMSG_REPAIR_ITEM
  (itemGuid=0 repairs all equipped items per WotLK protocol)
- Add canRepair flag to ListInventoryData; set it when player selects
  GOSSIP_OPTION_ARMORER in gossip window
- Show "Repair All" button in vendor window header when canRepair=true
- Display color-coded durability in item tooltip (green >50%, yellow
  >25%, red <=25%)
2026-03-10 16:21:09 -07:00
Kelsi
094ef88e57 fix: NPC animation/position sync for distant creatures and restore WoW ding overlay
- application.cpp creature sync loop: use entity->isEntityMoving() alongside
  planarDist to detect movement; entities > 150u have stale getX/Y/Z (distance
  culled in GameHandler::update) but isEntityMoving() correctly reflects active
  startMoveTo paths from SMSG_MONSTER_MOVE. Fixes distant NPCs playing Stand
  while creatureMoveCallback drives their renderer to Run.
- Switch sync loop to getLatestX/Y/Z (server-authoritative destination) for
  both the distance check and renderPos so creature positions are never stale
  from cull lag, and don't call moveInstanceTo when only entityIsMoving (no
  planarDist): the renderer's spline-driven move from creatureMoveCallback is
  already correct and shouldn't be cancelled by the per-frame sync.
- game_screen.cpp: replace scratch-built ring-burst level-up overlay with a
  simple "You have reached level X!" centered text (WoW style). The actual 3D
  visual is already handled by Renderer::triggerLevelUpEffect (LevelUp.m2).
2026-03-10 16:08:24 -07:00
Kelsi
bee4dde9b7 ui: add side action bars, fix resize positioning, and fix player nameplates
Action bars:
- Expand from 2 bars (24 slots) to 4 bars (48 slots)
- Bar 2: right-edge vertical bar (slots 24-35), off by default
- Bar 3: left-edge vertical bar (slots 36-47), off by default
- New "Interface" settings tab with toggles and offset sliders for all bars
- XP bar Y position now tracks bar 2 visibility and vertical offset

HUD resize fix:
- All HUD elements (action bars, bag bar, XP bar, cast bar, mirror timers)
  now use ImGui::GetIO().DisplaySize instead of window->getWidth/Height()
- DisplaySize is always in sync with the current frame — eliminates the
  one-frame lag that caused bars to misalign after window resize

Player nameplates:
- Show player name only on nameplate (no level number clutter)
- Fall back to "Player (level)" while name query is pending
- NPC nameplates unchanged (still show "level Name")
2026-03-10 15:56:41 -07:00