Commit graph

943 commits

Author SHA1 Message Date
Kelsi
4ce6fdb5f3 feat: color player cast bar by spell school from Spell.dbc
The player's own cast bar now uses spell-school-based colors for quick
identification: Fire=orange-red, Frost=icy blue, Shadow=purple,
Arcane=violet, Nature=green, Holy=golden, Physical=gold. Channels
remain blue regardless of school. Adds getSpellSchoolMask() using the
already-loaded Spell.dbc cache (schoolMask field, covering all
expansions including Classic SchoolEnum→bitmask conversion).
2026-03-17 19:56:52 -07:00
Kelsi
d0df6eed2c feat: show corpse skull marker on world map when player is a ghost
When the player dies and releases spirit, the world map now renders a
bone-white X cross at the corpse's location (matching the existing
minimap skull marker). The marker appears only when the player is a
ghost with an unclaimed corpse on the same map, and shows a "Your
corpse" tooltip on hover. Implemented via setCorpsePos() on WorldMap,
called from renderWorldMap() using getCorpseCanonicalPos().
2026-03-17 19:52:17 -07:00
Kelsi
279b4de09a feat: color cast bars green/red by spell interruptibility from Spell.dbc
Load AttributesEx from Spell.dbc for all expansions (Classic/TBC/WotLK/
Turtle). Check SPELL_ATTR_EX_NOT_INTERRUPTIBLE (bit 4 = 0x10) to classify
each cast as interruptible or not when SMSG_SPELL_START arrives.

Target frame and nameplate cast bars now use:
- Green: spell can be interrupted by Kick/Counterspell/Pummel etc.
- Red: spell is immune to interrupt (boss abilities, instant-cast effects)
Both colors pulse faster at >80% completion to signal the closing window.

Adds GameHandler::isSpellInterruptible() and UnitCastState::interruptible.
2026-03-17 19:43:19 -07:00
Kelsi
f9947300da feat: show zone entry text on every zone crossing via SMSG_INIT_WORLD_STATES
Previously the "Entering: [Zone]" overlay only triggered when the terrain
renderer loaded a new map. Now it also fires whenever worldStateZoneId_
changes (sent by the server via SMSG_INIT_WORLD_STATES on each zone
crossing), giving correct "Entering: Ironforge", "Entering: Wailing
Caverns" etc. display for sub-zones and dungeon entries without requiring
a full map reload.

- Added lastKnownWorldStateZoneId_ to track server-reported zone changes
- renderZoneText() now takes GameHandler& to access getWorldStateZoneId()
  and getWhoAreaName() for name lookup via WorldMapArea.dbc cache
- Renderer zone name still checked as a fallback for map-level transitions
- Both sources de-duplicate to avoid triggering the same text twice
2026-03-17 19:14:17 -07:00
Kelsi
d60d296b77 feat: show discovered taxi nodes as markers on the world map
Add gold diamond markers for every flight master the player has already
discovered (knownTaxiMask_), read from TaxiNodes.dbc and filtered to the
current continent/map being displayed:
- WorldMapTaxiNode struct carries canonical WoW coords + known flag
- WorldMap::setTaxiNodes() accepts the per-frame list from game_screen
- renderImGuiOverlay() projects each known node to UV, draws a gold
  diamond (AddQuadFilled) with a dark outline, and shows the node name
  as a tooltip on hover
- GameHandler::isKnownTaxiNode(id) checks knownTaxiMask_[] efficiently
- Markers update live — newly discovered nodes appear without reopening
  the map
2026-03-17 19:01:03 -07:00
Kelsi
488ec945b6 feat: display glancing and crushing blows in combat text and log
Add GLANCING (hitInfo 0x800) and CRUSHING (hitInfo 0x1000) as distinct
combat text types so players see mechanics feedback they expect from
Classic/TBC content:
- Glancing: shown as "~{amount}" in muted yellow/red; "glances for N" in
  the combat log
- Crushing: shown as "{amount}!" in bright orange/red; "crushes for N!"
  in the combat log
Both types are counted toward DPS meter accumulation. AttackerStateUpdateData
gains isGlancing()/isCrushing() helpers alongside the existing isCrit()/isMiss().
2026-03-17 18:51:48 -07:00
Kelsi
36fed15d43 feat: separate cast/impact kit paths in spell visual DBC lookup
loadSpellVisualDbc() now builds two distinct maps:
  spellVisualCastPath_  — visualId → M2 via SpellVisual.CastKit chain
  spellVisualImpactPath_ — visualId → M2 via SpellVisual.ImpactKit chain

playSpellVisual() accepts useImpactKit=false (default, cast) / true (impact).
SMSG_PLAY_SPELL_IMPACT passes useImpactKit=true so impact effects (explosions,
debuff indicators) use the ImpactKit model instead of the CastKit model.
Added ImpactKit field to all four dbc_layouts.json files.
2026-03-17 18:30:11 -07:00
Kelsi
315adfbe93 feat: implement SMSG_PLAY_SPELL_VISUAL with SpellVisual DBC chain lookup
Parse SMSG_PLAY_SPELL_VISUAL (casterGuid + visualId) and spawn a
transient M2 spell effect at the caster's world position.

DBC chain: SpellVisual.dbc → SpellVisualKit.dbc → SpellVisualEffectName.dbc
Lookup priority: CastKit.SpecialEffect0, fallback to MissileModel.
Models are lazy-loaded and cached by path; instances auto-expire after 3.5s.
DBC layouts added to all four expansion layout files (Classic/TBC/WotLK/Turtle).
2026-03-17 18:23:05 -07:00
Kelsi
973db16658 feat: add screen-space weather particle overlay (rain/snow/storm)
Weather type and intensity are already tracked from SMSG_WEATHER, but
only an icon was shown next to the zone name.  This adds a fullscreen
ImDrawList overlay that renders:
- Rain (type 1): diagonal rain streaks proportional to intensity
- Snow (type 2): gently swaying snowflakes with two-tone highlight
- Storm (type 3): heavy rain + dark fog-vignette on screen edges

Particles wrap at screen boundaries and are re-seeded on type or
resolution change.  Delta time is capped at 50 ms to prevent teleporting
after focus loss.  No heap allocations at runtime (static local arrays).
2026-03-17 16:34:39 -07:00
Kelsi
6d83027226 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
Kelsi
8b57e6fa45 feat: add HONOR_GAIN floating combat text for PvP honor gains
Show '+X Honor' floating text in gold when SMSG_PVP_CREDIT is received,
matching WoW's native behavior. Also add HONOR_GAIN to the combat log
panel for a complete record. Previously only a chat message was added.
2026-03-17 14:38:57 -07:00
Kelsi
8b9d626aec feat: show directional arrow on world map player marker
Replace the static filled circle with a red triangle arrow that
rotates to match the character's current facing direction.
Uses the same render-space yaw convention as the 3D scene so
the arrow matches in-world orientation.
2026-03-17 14:10:56 -07:00
Kelsi
5031351736 fix: add free-list to WardenEmulator heap allocator to prevent exhaustion
The bump-pointer allocator never reused freed blocks, causing the 16 MB
emulated heap to exhaust in long sessions even when blocks were freed.

- First-fit reuse from a free-list before advancing the bump pointer
- Coalesce adjacent free blocks to limit fragmentation
- Roll back the bump pointer when the top free block reaches it
- Reset allocator state on initialize() so re-runs start clean
2026-03-17 13:55:37 -07:00
Kelsi
a43a43ed8e fix: evict oldest minimap tile textures when cache exceeds 128 entries
Prevents unbounded GPU memory growth in long play sessions where the player
visits many zones. Tiles are inserted into a FIFO deque; when the count of
successfully-loaded tiles exceeds MAX_TILE_CACHE (128), the oldest entry is
destroyed and removed from both the cache map and the deque.

At 256×256×4 bytes per tile this caps minimap GPU usage at ~32 MB.
2026-03-17 13:38:18 -07:00
Kelsi
ef5532cf15 fix: add TBC chat message parser to prevent 12-byte misalignment
TBC 2.4.3 SMSG_MESSAGECHAT has no senderGuid(u64) or unknown(u32)
prefix before type-specific data. The WotLK base parser reads these
12 bytes unconditionally, causing complete misalignment of all chat
message fields — every chat message on a TBC server would parse
garbage for sender, channel, and message content.
2026-03-17 11:23:37 -07:00
Kelsi
e1be8667ed fix: add TBC game object query parser for correct string count
TBC 2.4.3 SMSG_GAMEOBJECT_QUERY_RESPONSE has 2 extra strings after
name[4] (iconName + castBarCaption). WotLK has 3 (adds unk1). Without
this override, the WotLK parser's third readString() consumed bytes
from the data[24] fields, corrupting game object type-specific data
and breaking interactions with doors, chests, mailboxes, and
transports on TBC servers.
2026-03-17 11:20:50 -07:00
Kelsi
1b86f76d31 fix: add TBC overrides for quest giver status and channel packets
TBC 2.4.3 sends quest giver status as uint32 (like Classic), not uint8
(WotLK). Without this override, reading uint8 consumed only 1 of 4
bytes, misaligning all subsequent packet data and breaking quest
markers on NPCs.

TBC channel join/leave packets use Classic format (name+password only).
The WotLK base prepends channelId/hasVoice/joinedByZone, causing
servers to reject the malformed packets and breaking channel features.
2026-03-17 11:16:02 -07:00
Kelsi
dc8619464a fix: add TBC guild roster parser to avoid gender byte misalignment
TBC 2.4.3 SMSG_GUILD_ROSTER has the same rank structure as WotLK
(variable rankCount + goldLimit + bank tab permissions), but does NOT
include a gender byte per member (WotLK added it). Without this
override, TBC fell through to the WotLK parser which read a spurious
gender byte, causing every subsequent field in each member entry to
misalign.
2026-03-17 11:10:54 -07:00
Kelsi
2d53ff0c07 feat: show environmental damage type in combat text and log
Fall, lava, drowning, fatigue, slime, and fire damage now display their
specific type instead of generic "Environmental damage" in both floating
combat text and the combat log window. The envType byte from
SMSG_ENVIRONMENTAL_DAMAGE_LOG is propagated via the powerType field to
the display layer. Added powerType to CombatLogEntry for consistent
access in the persistent combat log.
2026-03-17 10:54:07 -07:00
Kelsi
1152a70201 fix: handle transport data in other player movement packets
Other players on transports (boats, zeppelins, trams) were not properly
tracked because handleOtherPlayerMovement() did not read transport data
from MSG_MOVE_* packets. This caused entities to slide off transports
between movement updates since no transport attachment was established.

Now reads the transport GUID and local offset from the packet using
expansion-aware wire flags (0x200 for WotLK/TBC, 0x02000000 for
Classic/Turtle), registers a transport attachment so the entity follows
the transport smoothly via updateAttachedTransportChildren(), and clears
the attachment when the player disembarks.
2026-03-17 10:40:35 -07:00
Kelsi
7b03d5363b feat: profession crafting improvements and combat sound fixes
- Suppress spell sounds for profession/tradeskill spells (crafting is silent)
- Add craft quantity UI to profession trainer: recipe selector, quantity
  input, Create button, and Stop button for active queue
- Known recipes show Create button to cast directly from trainer window
- Craft queue auto-recasts on CREATE_ITEM completion, cancels on failure
- Fix missing combat sounds: player spell impacts on enemies, enemy spell
  cast sounds targeting player, instant melee ability weapon sounds
2026-03-17 10:12:49 -07:00
Kelsi
192c6175b8 feat: add brightness slider to Video settings
Black overlay dims below 50%, white overlay brightens above 50%.
Persisted in settings.cfg, with restore-defaults support.
2026-03-17 09:04:53 -07:00
Kelsi
3667ff4998 fix: use uniform 22-byte loot item size for Classic/TBC/Turtle
SMSG_LOOT_RESPONSE items include randomSuffix and randomPropertyId
fields across all expansions, not just WotLK. Using 14-byte size for
Classic/TBC caused item data to be read at wrong offsets.
2026-03-17 09:04:40 -07:00
Kelsi
203514abc7 fix: correct minimap orientation and arrow direction, compact key ring UI
Remove stray X-flip in minimap display shader that mirrored the map
horizontally (West on right instead of East). Fix arrow rotation
fallback path (missing negation) and add character-facing-relative
arrow in rotateWithCamera mode.

Compact key ring: 24px slots in 8-column grid, only show rows with
items, hide when empty. Add Show Key Ring toggle in Settings with
persistence.
2026-03-17 08:18:46 -07:00
Kelsi
8378eb9232 fix: correct sync Warden MODULE check returning 0x01 instead of 0x00
The sync path's MODULE handler was returning 0x01 (module found) for
unwanted cheat DLLs (WPESPY, TAMIA, PRXDRVPE, etc.) instead of 0x00
(not found). Since VMaNGOS compares the result as a boolean, returning
any non-zero value for a cheat module tells the server "this cheat DLL
is loaded," triggering Warden penalties that accumulate into a kick
after ~3-5 minutes.

Also adds ±4KB hint window search to searchCodePattern for faster
PAGE_A resolution without full brute-force, and restores the turtle
PAGE_A fallback (confirmed patterns are runtime-patched offsets not
present in the on-disk PE).
2026-03-17 07:19:37 -07:00
Kelsi
e3c2269b16 fix: increase descriptor pool sizes to prevent Vulkan crash
Terrain pool 16384→65536, WMO pool 8192→32768. The previous sizes
were too small for the load/unload radii, causing pool exhaustion
and a hard crash when streaming terrain on large maps.
2026-03-16 17:46:32 -07:00
Kelsi
6fd32ecdc6 fix: skip Warden HASH_RESULT on strict servers when no CR match
Sending a wrong hash to AzerothCore/WotLK servers triggers an
account ban. When no pre-computed challenge-response entry matches
the server seed, skip the response entirely so the server times out
with a kick (recoverable) instead of verifying a bad hash and
banning (unrecoverable). Turtle/Classic servers remain unchanged
as they only log Warden failures.

Also adds RX silence detection and fixes Turtle isTurtle flag
propagation in MEM_CHECK path.
2026-03-16 17:38:25 -07:00
Kelsi
a3279ea1ad fix: async Warden PAGE_A/PAGE_B checks to prevent main-loop stalls
Move 5-second brute-force HMAC-SHA1 code pattern searches to a
background thread via std::async. The main loop now detects PAGE_A/B
checks, launches the response builder async, and drains the result
in update() — encrypting and sending on the main thread to keep
wardenCrypto_ RC4 state thread-safe.

Also adds Turtle WoW PE binary support (isTurtle flag, dedicated exe
search, runtime patches), searchCodePattern with result caching,
writeLE32 public API, and Warden scan entry verification.
2026-03-16 16:46:29 -07:00
Kelsi
f0a515ff9c fix: stabilize classic/turtle world session handling
Some checks failed
Build / Build (arm64) (push) Has been cancelled
Build / Build (x86-64) (push) Has been cancelled
Build / Build (macOS arm64) (push) Has been cancelled
Build / Build (windows-arm64) (push) Has been cancelled
Build / Build (windows-x86-64) (push) Has been cancelled
Security / CodeQL (C/C++) (push) Has been cancelled
Security / Semgrep (push) Has been cancelled
Security / Sanitizer Build (ASan/UBSan) (push) Has been cancelled
2026-03-15 06:13:36 -07:00
Kelsi
6ede9a2968 refactor: derive turtle opcodes from classic 2026-03-15 02:55:05 -07:00
Kelsi
0b6265bc55 fix: align turtle protocol compatibility 2026-03-15 01:47:36 -07:00
Kelsi
b0fafe5efa fix: stabilize turtle world entry session handling 2026-03-15 01:21:23 -07:00
Kelsi
eea3784976 fix: harden turtle movement parsing and warden fallback 2026-03-14 22:18:28 -07:00
Kelsi
075b4c1772 fix(gameplay): tighten TB elevator bounds and reset stale combat visuals
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
2026-03-14 09:19:16 -07:00
Kelsi
2c32b72f95 feat(ui): show keyring in inventory 2026-03-14 08:42:25 -07:00
Kelsi
800862c50a fix(ui): cache ghost opacity updates to state changes 2026-03-14 08:31:08 -07:00
Kelsi
cebca9a882 fix(gameplay): stabilize run animation and clean ghost/death visuals 2026-03-14 08:27:32 -07:00
Kelsi
9cd52c4dd7 fix(loot): gate auto-loot sends per loot session 2026-03-14 07:31:15 -07:00
Kelsi
c1baffadf0 fix(input): release mouse on stalls and clean quest keybind duplication 2026-03-14 07:29:39 -07:00
Kelsi
5fa5020af5 fix(mail): use attachment item guid for WotLK take item 2026-03-14 07:11:18 -07:00
Kelsi
5b195781ad fix(death): restore corpse reclaim and enforce ghost grayscale 2026-03-14 06:43:49 -07:00
Kelsi
6cfb439fd6 fix(vulkan): defer resource frees until frame fence 2026-03-14 03:32:31 -07:00
Kelsi
64483a31d5 fix(combattext): show power drain separately from damage 2026-03-13 23:56:44 -07:00
Kelsi
57265bfa4f fix(combattext): render evade results explicitly 2026-03-13 23:32:57 -07:00
Kelsi
3f1083e9b5 fix(combatlog): consume reflect payload in spell-go miss entries 2026-03-13 23:15:56 -07:00
Kelsi
77d53baa09 fix(combattext): render deflect and reflect miss events 2026-03-13 23:08:49 -07:00
Kelsi
3ef5b546fb fix(combatlog): render instakill events explicitly 2026-03-13 22:22:00 -07:00
Kelsi
91dc45d19e fix(combatlog): dedupe duplicate spellsteal aura logs 2026-03-13 20:23:24 -07:00
Kelsi
c45951b368 fix(combatlog): distinguish spellsteal from dispel 2026-03-13 19:58:37 -07:00
Kelsi
e51b215f85 feat: add DISPEL and INTERRUPT combat log entries for dispel/spellsteal/interrupt events
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
2026-03-13 12:03:07 -07:00