Commit graph

1020 commits

Author SHA1 Message Date
Kelsi
da49593268 Add 3D level-up effect using LevelUp.m2 spell model
Replace 2D screen-space ding rings with real WoW LevelUp.m2 particle/geometry
effect. Fix FBlock particle color parsing (C3Vector floats, not CImVector bytes)
which was producing blue/red instead of golden yellow. Spell effect models bypass
particle dampeners, glow sprite conversion, Mod→Additive blend override, and all
collision (floor/wall/camera) to prevent camera zoom-in. Other players' level-ups
trigger the 3D effect at their position with group chat notification. F7 hotkey
for testing.
2026-02-19 20:36:25 -08:00
Kelsi
76e1aef62d Improve combat messages: power-type-aware errors, fix chat line breaks, better wording
- getSpellCastResultString now returns "Not enough rage/energy/focus/runic power" based on player power type instead of always "Not enough mana"
- Fix NPC combat messages concatenating onto previous lines by combining prefix+body into single renderTextWithLinks call instead of TextWrapped+SameLine
- Improve generic error strings to be more WoW-authentic (Invalid target, Target not in line of sight, etc.)
2026-02-19 19:33:02 -08:00
Kelsi
20cdff0790 Fix armor stat in character stats panel via UNIT_FIELD_RESISTANCES
The character stats panel was showing Armor: 0 because summing armor
from item query responses is fragile (depends on correct BuyCount/damage
block parsing). Instead, read the server-authoritative total armor
directly from UNIT_FIELD_RESISTANCES (physical resistance, index 0)
in the player entity update fields.

Added UNIT_FIELD_RESISTANCES to the UF enum and all four expansion
JSON files with correct wire indices:
  WotLK 3.3.5a: 99   (NPC_FLAGS=82 + emotestate + stat×5 + posstat×5 + negstat×5)
  TBC 2.4.3:   185   (NPC_FLAGS=168 + same relative layout)
  Classic 1.12: 154  (NPC_FLAGS=147 + emotestate + stat×5, no posstat/negstat)
  Turtle WoW:  154   (same as Classic)

Stats panel uses server armor when > 0, falls back to summed item-query
armor otherwise. Armor rating resets to 0 on world entry and is updated
from both CREATE_OBJECT and VALUES update blocks.
2026-02-19 17:45:09 -08:00
Kelsi
05e2b37894 Show rage/energy bar at same size as mana bar for warriors and rogues
Warriors (rage) and rogues/druids (energy) had no power bar rendered
when maxPower was 0 — the server often omits UNIT_FIELD_MAXPOWER1 for
rage-based classes since rage starts at 0. Rage and energy always cap
at 100, so default maxPower to 100 when the server sends 0 for those
power types. Also unified bar height to 18px (matching health bar) and
added proper power-type colour to the target frame bar (was always blue).
2026-02-19 17:08:53 -08:00
Kelsi
764f2b8edc Fix missing armor in WotLK item tooltips and character stats
SMSG_ITEM_QUERY_SINGLE_RESPONSE in WotLK 3.3.5a sends BuyCount as a
separate field before BuyPrice. The parser was skipping only one of the
two fields, shifting every subsequent read by 4 bytes. This caused
statsCount to be read from ContainerSlots (always 0 for non-bags) so
no stat pairs were parsed, and the armor field was read from the wrong
offset in the damage block — leaving all stat bonuses and armor at 0.

Also moved armor above stat bonuses in the item tooltip to match WoW's
canonical tooltip layout (armor, then green stat lines).
2026-02-19 16:52:04 -08:00
Kelsi
c69457ae3b apply pending protocol, ui, audio, and CodeQL fixes 2026-02-19 16:17:06 -08:00
Kelsi
550366df07 Fix item destroy packet format and wire destroy confirmation UI 2026-02-19 06:34:06 -08:00
Kelsi
3c754801c4 Stabilize buyback flow and single-row buyback UI
- keep vendor buyback as one-item LIFO row in vendor window

- add robust pending buyback tracking with wire slot probing (74..85)

- recover from stale optimistic sell/buyback entries and refresh vendor list

- keep buy packet construction branch-compatible (direct packet build)
2026-02-19 05:48:40 -08:00
Kelsi
871da33942 Clean README mentions and finalize current gameplay/UI fixes 2026-02-19 03:31:49 -08:00
Kelsi
630c877830 Fix CI build: avoid missing GameHandler interaction-cast API 2026-02-19 03:17:10 -08:00
Kelsi
19525067cf Fix quest reward selection index mapping for choose-reward 2026-02-19 03:12:57 -08:00
Kelsi
e778e21f6f Fix minimap mute behavior and shallow-water swim trigger 2026-02-19 02:46:52 -08:00
Kelsi
8d4d9b7169 Fix quest flow regressions, tooltip compare stats, and M2 alpha-key handling 2026-02-19 02:27:01 -08:00
Kelsi
512d60c9be Fix gossip quest flow and questgiver marker state 2026-02-19 02:04:56 -08:00
Kelsi
b3ea6d8e81 Refine bag UI layout and add shift-hover item compare 2026-02-19 01:50:50 -08:00
Kelsi
8efc21115f Fix quest turn-in flow and WoW quest text placeholders 2026-02-19 01:12:14 -08:00
Kelsi
4fcf869e34 Stabilize quest log details loading and turn-in item sync 2026-02-19 00:56:24 -08:00
Kelsi
334d4d3df6 Fix quest log titles and full-row selection behavior 2026-02-19 00:30:21 -08:00
Kelsi
7ab25c63c9 Optimize release builds: LTO, -O3, visibility, micro-perf fixes
- CMakeLists.txt: enable LTO for Release, add -O3 and -fvisibility=hidden
- scene: addMesh uses std::move, removeMesh takes const shared_ptr&
- entity: std::move entity into map instead of copy
- clouds: cosf/sinf instead of cos/sin (float math, avoids double promotion)
- game_screen: reserve trainer spell vector before push_back loop
- warden_module/emulator: replace std::endl (121 stream flushes) with '\n'
2026-02-18 20:10:47 -08:00
Kelsi
eacecddfb0 Fix real bugs found by clang-tidy
- game_handler.cpp: use-after-move on node.id after std::move(node)
  (save nodeId before the move)
- tcp_socket.cpp, world_socket.cpp: virtual call in destructor bypasses
  dispatch; use qualified TCPSocket::disconnect() / WorldSocket::disconnect()
  to make intent explicit
- wmo_renderer.cpp: float loop counters risk precision drift; replace with
  integer step counts and reconstruct float from index
- game_screen.cpp: (float + 0.5) cast to int is incorrect rounding;
  use std::lround instead
2026-02-18 20:02:12 -08:00
Kelsi
9d44d672d2 Fix localtime_r in game_screen.cpp: use localtime_s on Windows 2026-02-18 18:50:27 -08:00
Kelsi
98212a3f91 Fix quest item loot parsing and quest item progress tracking
- add SMSG_QUESTUPDATE_ADD_ITEM logical opcode mapping (0x197)
- handle quest item progress updates in GameHandler
- parse quest-item section in SMSG_LOOT_RESPONSE (regular + quest items)
- add quest item progress storage in quest log entries
- show tracked kill/item progress in Quest Log UI
2026-02-18 04:06:14 -08:00
Kelsi
c00fc34bc2 Fix target circle jumping ahead to spline waypoints
- use interpolated target position (getX/Y/Z) for selection circle placement
- avoids drawing circle at movement destination before creature arrives
- keeps previous target interpolation update guarantees
2026-02-18 03:57:12 -08:00
Kelsi
08c956a6e5 Fix creature chase animation and target-circle tracking
- use movement animation (prefer run, fallback walk) for server-driven creature moves
- synthesize short movement duration for duration-less movement deltas to avoid glide/attack-pose sliding
- return to idle after both walk/run movement states
- drive target circle from entity latest position and always interpolate selected/engaged targets
2026-02-18 03:53:53 -08:00
Kelsi
dd8f04ac99 Add weapon stats to inventory tooltips and fix login camera pitch
- propagate item damage range and delay into ItemDef during inventory rebuild
- show weapon damage, speed, and DPS in inventory/character slot tooltips
- fix online spawn camera pitch sign so third-person camera starts above ground
2026-02-18 03:50:47 -08:00
Kelsi
1de2f4c8a0 Show weapon damage/speed in item tooltips
- parse and cache item class/subclass, damage range, and attack delay from item query responses
- render weapon damage, speed, and DPS in the shared item-link tooltip
- render weapon damage, speed, and DPS in vendor hover tooltips
- keep armor and primary stat lines intact
2026-02-18 03:46:03 -08:00
Kelsi
4ba10e772b Fix vendor window ImGui ID conflicts using loop index
PushID(item.slot) causes conflicting IDs when the server sends items with
duplicate or zero slot values. Use the loop index instead, which is always
unique regardless of what the server puts in the slot field.
2026-02-17 18:55:02 -08:00
Kelsi
68e39a2192 Fix vendor packet parsing and Tokens display
Auto-detect whether SMSG_LIST_INVENTORY has 7 fields (28 bytes/item, no
extendedCost) or 8 fields (32 bytes/item) per item from packet size. Servers
that omit extendedCost caused every item after the first to have garbage prices
due to misaligned field reads.

Also remove the [+Tokens] hybrid indicator; only show [Tokens] on pure
token-purchased items (buyPrice==0 && extendedCost!=0).
2026-02-17 18:08:00 -08:00
Kelsi
60ebb4dc3f Fix vendor: correct CMSG_BUY_ITEM field order (slot before itemId), handle buy failures, show token costs; remove level-up test button (animation triggers on real level-up) 2026-02-17 17:44:48 -08:00
Kelsi
b441452dcb Fix audio volume settings: apply saved values on startup, don't overwrite with audio manager defaults 2026-02-17 17:37:20 -08:00
Kelsi
897867bf7b Add level-up ding animation with cheer emote and test button
- Trigger ding when UNIT_FIELD_LEVEL increases for player: plays LevelUp sound,
  cheer emote animation, and shows screen overlay
- renderDingEffect(): 3 expanding golden rings + "LEVEL X!" / "DING!" text
  drawn via ImDrawList foreground (3s duration, fades out last 0.8s)
- triggerDing() wires sound (UiSoundManager::playLevelUp) + emote + overlay
- LevelUpCallback in GameHandler fires on genuine level increase (newLevel > oldLevel)
- "Test: Level Up" button in escape menu triggers ding at current player level
2026-02-17 17:23:42 -08:00
Kelsi
0e18c8871d Add auto loot setting to gameplay settings
Checkbox in Settings > Gameplay > Loot section. When enabled, all items
are automatically sent CMSG_AUTOSTORE_LOOT_ITEM on loot response (same
as right-click looting each item). Gold always auto-loots regardless.
Setting persists in settings.cfg as auto_loot=0/1.
2026-02-17 16:31:00 -08:00
Kelsi
a55399fad6 Add mute button and original soundtrack toggle
- Mute button: small [M] button alongside minimap zoom controls, turns red when active; directly sets AudioEngine master volume to 0, restores on unmute; persists in settings.cfg
- Original Soundtrack: checkbox in Settings > Audio that controls whether custom original music tracks (file: prefix) are included in zone music rotation; when disabled, only WoW MPQ tracks play; persists in settings.cfg
- ZoneManager.getRandomMusic() now filters file: paths when OST is disabled, falling back to full list if zone has no non-file tracks
2026-02-17 16:26:49 -08:00
Kelsi
f207acc038 Fix $N placeholder and quest required item display
- Handle uppercase \$N in replaceGenderPlaceholders (WoW servers send \$N for player name, we only handled \$n)
- Fix SMSG_QUESTGIVER_REQUEST_ITEMS required item field order: packet sends [displayInfoId, count, itemId] not [itemId, count, displayInfoId], causing wrong items to display (e.g. Ring of Pure Silver instead of Tough Wolf Meat)
2026-02-17 16:16:51 -08:00
Kelsi
55fd692c1a Fix buff bar: opcode merge, isBuff flag, and duration countdown
Root cause: OpcodeTable::loadFromJson() cleared all mappings before
loading the expansion JSON, so any WotLK opcode absent from Turtle WoW's
opcodes.json (including SMSG_AURA_UPDATE and SMSG_AURA_UPDATE_ALL) was
permanently lost. Changed loadFromJson to patch/merge on top of existing
defaults so only explicitly listed opcodes are overridden.

Also fix isBuff border color: was testing flag 0x02 (effect 2 active)
instead of 0x80 (negative/debuff flag).

Add client-side duration countdown: AuraSlot.receivedAtMs is stamped
when the packet arrives; getRemainingMs(nowMs) subtracts elapsed time so
buff tooltips show accurate remaining duration instead of stale snapshot.
2026-02-17 15:49:12 -08:00
Kelsi
df0bfaea4f Fix action bar and buff bar spell tooltips showing 'Spell #xxx'
The action bar's inline Spell.dbc loader had a broken field index lookup:
operator[] on the layout map would silently insert 0 if 'Name' wasn't a
key, causing all names to be read from field 0 (the spell ID). Also the
once-only 'attempted' flag meant if assetMgr wasn't ready, it never retried.

Replace the duplicated broken DBC loading in the action bar and buff bar
with SpellbookScreen::lookupSpellName(), which reuses the spellbook's
already-correct loading (expansion layout + WotLK fallback). Remove the
now-unused actionSpellNames/actionSpellDbAttempted/actionSpellDbLoaded fields.
2026-02-17 15:41:55 -08:00
Kelsi
2cad3b9c2b Fix combat text: separate incoming/outgoing positions and clarify dodge/parry
Outgoing events (player attacks enemy: damage dealt, Dodge/Parry when enemy
evades) now float on the right side of screen (near target) instead of above
the player character. Incoming events (enemy attacks player) remain at
center-left (near player).

Dodge/Parry labels now show direction: "Dodge"/"Parry" when the enemy evades
the player's attack (outgoing, gray), and "You Dodge"/"You Parry" when the
player evades an incoming attack (cyan). Crit damage now has distinct colors
for outgoing (bright yellow) vs incoming (orange).
2026-02-17 15:24:39 -08:00
Kelsi
827679579f Fix WAV decode cache and spell lookup performance
- audio_engine.cpp: cache key was based on vector pointer address, not
  content — cache never hit since each asset load produces a new
  allocation. Replace with FNV-1a over head+tail bytes + size, giving
  correct content-based identity at O(1) cost. Add 256-entry cap with
  eviction to prevent unbounded growth over long sessions.

- game_handler.hpp/cpp, spellbook_screen, game_screen: knownSpells was
  a std::vector with O(n) std::find lookups scattered across packet
  handlers and UI code. Switch to std::unordered_set for O(1) insert,
  erase, and membership checks. Update all push_back/erase-remove/find
  call sites to use set operations.
2026-02-17 15:13:54 -08:00
Kelsi
42e7e1ce7e Fix action bar spell icons missing on Turtle WoW
Turtle/Classic Spell.csv files are garbled (field 0 is a string rather
than a numeric ID) so loadDBC() falls back to the WotLK binary Spell.dbc
(234 fields). getSpellIcon() was still using the Turtle layout (IconID at
field 117) to read the WotLK binary, producing garbage values and no icons.

When the loaded Spell.dbc has >=200 fields it is the WotLK binary; use the
WotLK IconID field (133) directly, matching the same approach already used
in spellbook_screen.cpp.
2026-02-17 14:55:32 -08:00
Kelsi
7cf060a9f6 Handle SMSG_CHARACTER_LOGIN_FAILED (0x041) for AzerothCore/Playerbot compatibility
Previously this opcode was unrecognised and silently dropped, leaving the
client stuck in ENTERING_WORLD with no feedback when the server rejected a
login (duplicate session, world down, disabled race/class, etc.). Now we
decode the LoginFailureReason byte, reset state to CHAR_LIST_RECEIVED so
the player can retry, and surface a red error message on the character screen
via the new CharLoginFailCallback. Also adds isError colour support to
CharacterScreen::setStatus so failures show in red and successes in green.
2026-02-17 13:59:29 -08:00
Kelsi
36fc1df706 Fix Turtle WoW compatibility: NPC spawning, quests, spells, realm display, and music
- Add TurtlePacketParsers with dedicated movement block parser (Classic format + transport timestamp)
- Fix quest giver status: read uint32 and translate vanilla enum values for Classic/Turtle
- Fix quest accept packet: remove trailing uint32 that vanilla servers reject
- Fix quest details parser: auto-detect vanilla vs WotLK format (informUnit field)
- Fix spellbook and action bar icons: fallback to WotLK DBC field indices when expansion layout fails
- Fix spell cast failure messages: translate vanilla SpellCastResult codes (+1 offset)
- Fix realm list: correct type values (6=RP, 8=RP-PvP) and population thresholds
- Fix music: disable looping for zone music, auto-advance to next random track when finished
- Add music anti-repeat: avoid playing the same track back-to-back
- Make TBC update block parsing resilient (keep parsed blocks on failure instead of aborting)
- Add right-click attack on hostile mobs
- Add name query diagnostic logging
2026-02-17 05:27:03 -08:00
Kelsi
99723abfac Improve UI layout, spell casting, and realm selection screen
- Fix action bar, bag bar, chat window to track window resize (Always pos)
- Show spell names in cast bar instead of spell IDs
- Play precast/cast-complete sounds via SpellSoundManager
- Fix hearthstone to use CMSG_CAST_SPELL directly (avoids slot sync issues)
- Show map name instead of coordinates in hearthstone tooltip
- Show cooldown time remaining in action bar tooltips
- Search equipped slots and bags for action bar item icons
- Redesign realm screen: back button, larger table/buttons, auto-select
  realm with characters, double-click to enter, proportional columns
2026-02-17 03:50:36 -08:00
Kelsi
d153bcb62c Enable equipment slot drag-and-drop via server swap packets
Replace the "not supported" error message with actual pickup from
equipment slots. Placing equipment items into backpack or bag slots
sends CMSG_SWAP_ITEM to the server.
2026-02-17 01:18:52 -08:00
Kelsi
a1457ee801 Fix NPC textures, bag item interactions, and Classic item query parsing
Rebuild creature display lookups after expansion-specific DBC layout loads
(was using WotLK defaults before turtle layout was available). Add full
drag-and-drop support for bag items with server-side CMSG_SWAP_ITEM packets.
Add Classic-specific SMSG_ITEM_QUERY_SINGLE_RESPONSE parser for Vanilla
format differences (fewer damage types, no scaling stats, no Flags2).
2026-02-17 01:00:04 -08:00
Kelsi
44d1431b60 Suppress login bind point message and auto-join Local channel
Only show "Your home has been set" when the player actively changes their
bind point (via innkeeper), not on the initial login sync from the server.
Add "Local" to the auto-join channel list for Turtle WoW compatibility,
with a settings checkbox and persistence.
2026-02-16 21:16:25 -08:00
Kelsi
381d896348 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
Kelsi
0d4a9c38f7 Add guild features, fix channel joining, and improve whisper reply
Guild: add disband, leader transfer, public/officer note commands with
roster context menu showing rank names and officer notes column. Auto-refresh
roster after guild events.

Channels: fix city/region channels not working by accepting SMSG_CHANNEL_NOTIFY
during ENTERING_WORLD state (server auto-joins before VERIFY_WORLD) and handling
PLAYER_ALREADY_MEMBER notification.

Whisper: /r now switches to whisper tab and sets target to last sender,
matching WoW behavior.

Camera: extend WMO collision raycasting to work outside WMOs too.
2026-02-16 20:16:14 -08:00
Kelsi
1cfe186c62 Implement mailbox interaction and expansion-aware mail system
Fix mailbox right-click (transposed CMSG_GAMEOBJECT_USE opcode, missing
mail opcodes in Turtle WoW JSON, decorative GO type filtering). Add
expansion-aware mail packet handling via PacketParsers: Classic format
(single item, no msgSize prefix, Vanilla field order) vs WotLK format
(attachment arrays, enchant slots). Fix CMSG_MAIL_TAKE_ITEM and
CMSG_MAIL_DELETE for Vanilla (no trailing fields). Add pulsing "New
Mail" indicator below minimap, SMSG_RECEIVED_MAIL and
MSG_QUERY_NEXT_MAIL_TIME handlers, and async sender name backfill.
2026-02-16 18:46:44 -08:00
Kelsi
d87a86e35c Remove debug logging and add negative texture cache to fix lag spikes
Remove PPM composite dumps, MODEL1_BOUNDS vertex analysis, TEX_REGION
logging, FOUNTAIN_PARTICLES debug output, and verbose chat/warden gate
logging. Add negative cache for failed texture loads to prevent repeated
file I/O for missing textures like deathknighteyeglow.blp.
2026-02-16 00:45:47 -08:00
Kelsi
ed6b305158 Fix character geoset mapping and texture corruption on equipment change
Corrected CharGeosets group assignments verified via vertex bounding boxes:
- Group 4 (401+) = gloves/forearms, Group 5 (501+) = boots/shins,
  Group 8 (801+) = sleeves (chest-controlled), Group 9 = kneepads,
  Group 13 (1301+) = pants/trousers, Group 20 (2002) = bare feet
- Changed bare shin default from 501 to 502 for better width match
  with thigh mesh (0.39 vs 0.32, thighs are 0.42)
- Added clearCompositeCache() to prevent stale composite textures
  from being reused across equipment changes
- Fixed character preview geoset defaults to match corrected mapping
2026-02-15 20:53:01 -08:00