Commit graph

574 commits

Author SHA1 Message Date
Kelsi
3215832fed refactor: extract updateTaxiAndMountState() from update()
Move 131 lines of taxi flight detection, mount reconciliation, taxi
activation timeout, and flight recovery into a dedicated method.
update() is now ~277 lines (61% reduction from original 704).
2026-03-25 15:32:51 -07:00
Kelsi
123a19ce1c refactor: extract updateEntityInterpolation() from update()
Move entity movement interpolation loop (distance-culled per-entity
update) into its own method. update() is now ~406 lines (down from
original 704, a 42% reduction across 3 extractions).
2026-03-25 15:27:31 -07:00
Kelsi
6343ceb151 refactor: extract updateTimers() from GameHandler::update()
Move 164 lines of timer/pending-state logic into updateTimers():
auction delay, quest accept timeouts, money delta, GO loot retries,
name query resync, loot money notifications, auto-inspect throttling.
update() is now ~430 lines (down from original 704).
2026-03-25 15:23:31 -07:00
Kelsi
7066062136 refactor: extract updateNetworking() from GameHandler::update()
Move socket update, packet processing, Warden async drain, RX silence
detection, disconnect handling, and Warden gate logging into a separate
updateNetworking() method. Reduces update() from ~704 to ~591 lines.
2026-03-25 15:19:03 -07:00
Kelsi
b2e2ad12c6 refactor: add registerWorldHandler() for state-guarded dispatch entries
Add registerWorldHandler() that wraps handler calls with an IN_WORLD
state check. Replaces 8 state-guarded lambda dispatch entries with
concise one-line registrations.
2026-03-25 15:11:15 -07:00
Kelsi
6694a0aa66 refactor: add registerHandler() to replace 120 lambda dispatch wrappers
Add registerHandler() using member function pointers, replacing 120
single-line lambda dispatch entries of the form
[this](Packet& p) { handleFoo(p); } with concise
registerHandler(Opcode::X, &GameHandler::handleFoo) calls.
2026-03-25 15:08:22 -07:00
Kelsi
313a1877d5 refactor: add registerSkipHandler/registerErrorHandler for dispatch table
Add helpers for common dispatch table patterns: registerSkipHandler()
for opcodes that just discard data (14 sites), registerErrorHandler()
for opcodes that show an error message (3 sites). Reduces boilerplate
in registerOpcodeHandlers().
2026-03-25 14:50:18 -07:00
Kelsi
e4194b1fc0 refactor: add isInWorld() and replace 119 inline state+socket checks
Add GameHandler::isInWorld() helper that encapsulates the repeated
'state == IN_WORLD && socket' guard. Replace 99 negative checks and
20 positive checks across game_handler.cpp, plus fix 2 remaining
C-style casts.
2026-03-25 14:21:19 -07:00
Kelsi
43caf7b5e6 refactor: add Packet::writePackedGuid, remove redundant static methods
Add writePackedGuid() to Packet class for read/write symmetry. Remove
now-redundant UpdateObjectParser::readPackedGuid and
MovementPacket::writePackedGuid static methods. Replace 6 internal
readPackedGuid calls, 9 writePackedGuid calls, and 1 inline 14-line
transport GUID write with Packet method calls.
2026-03-25 14:06:42 -07:00
Kelsi
ea15740e17 refactor: add withSoundManager() template to reduce renderer boilerplate
Add GameHandler::withSoundManager() that encapsulates the repeated
getInstance()->getRenderer()->getSoundManager() null-check chain.
Replace 6 call sites, with helper available for future consolidation
of remaining 25 sites.
2026-03-25 13:35:29 -07:00
Kelsi
f02fa10126 refactor: make DBC name caches mutable to eliminate 13 const_cast hacks
Mark spellNameCache_, titleNameCache_, factionNameCache_, areaNameCache_,
mapNameCache_, lfgDungeonNameCache_ and their loaded flags as mutable.
Update 6 lazy-load methods to const. Removes all 13 const_cast<GameHandler*>
calls, allowing const getters to lazily populate caches without UB.
2026-03-25 13:21:02 -07:00
Kelsi
fe043b5da8 refactor: extract getUnitByGuid() to replace 10 entity lookup + dynamic_cast patterns
Add GameHandler::getUnitByGuid() that combines entityManager.getEntity()
with dynamic_cast<Unit*>. Replaces 10 two-line lookup+cast blocks with
single-line calls.
2026-03-25 13:12:51 -07:00
Kelsi
d646a0451d refactor: add fireAddonEvent() helper to eliminate 170+ null checks
Add inline fireAddonEvent() that wraps the addonEventCallback_ null
check. Replace ~120 direct addonEventCallback_ calls with fireAddonEvent,
eliminating redundant null checks at each callsite and reducing
boilerplate by ~30 lines.
2026-03-25 11:34:22 -07:00
Kelsi
98b9e502c5 refactor: extract guidToUnitId/getQuestTitle helpers and misc cleanup
- Extract guidToUnitId(), getQuestTitle(), findQuestLogEntry() helpers
  to replace 14 duplicated GUID-to-unitId patterns and 7 quest log
  search patterns in game_handler.cpp
- Remove duplicate #include in renderer.cpp
- Remove commented-out model cleanup code in terrain_manager.cpp
- Replace C-style casts with static_cast in auth and transport code
2026-03-25 11:25:44 -07:00
Paul
15f12d86b3 split mega switch 2026-03-25 07:26:38 +03:00
Kelsi
c18720f0f0 feat: server-synced bag sort, fix world map continent bounds, update docs
Inventory sort: clicking "Sort Bags" now generates CMSG_SWAP_ITEM packets
to move items server-side (one swap per frame to avoid race conditions).
Client-side sort runs immediately for visual preview; server swaps follow.
New Inventory::computeSortSwaps() computes minimal swap sequence using
selection-sort permutation on quality→itemId→stackCount comparator.

World map: fix continent bounds derivation that used intersection (max/min)
instead of union (min/max) of child zone bounds, causing continent views
to display zoomed-in/clipped.

Update README.md and docs/status.md with current features, release info,
and known gaps (v1.8.2-preview, 664 opcode handlers, NPC voices, bag
independence, CharSections auto-detect, quest GO server limitation).
2026-03-24 09:24:09 -07:00
Kelsi
11ecc475c8 feat: resolve spell \$d duration to real seconds from SpellDuration.dbc
Spell descriptions now substitute \$d with actual duration values:
  Before: "X damage over X sec"
  After:  "30 damage over 18 sec"

Implementation:
- DurationIndex field (40) added to all expansion Spell.dbc layouts
- SpellDuration.dbc loaded during cache build: maps index → base ms
- cleanSpellDescription substitutes \$d with resolved seconds/minutes
- getSpellDuration() accessor on GameHandler

Combined with \$s1/\$s2/\$s3 from the previous commit, most common
spell description templates are now fully resolved with real values.
2026-03-23 01:00:18 -07:00
Kelsi
a5aa1faf7a feat: resolve spell \$s1/\$s2/\$s3 to real DBC damage/heal values
Spell descriptions now substitute \$s1/\$s2/\$s3 template variables
with actual effect base points from Spell.dbc (field 80/81/82).
For example: "causes \$s1 Fire Damage" → "causes 562 Fire Damage".

Implementation:
- Added EffectBasePoints0/1/2 to all 4 expansion DBC layouts
- SpellNameEntry now stores effectBasePoints[3]
- loadSpellNameCache reads base points during DBC iteration
- cleanSpellDescription substitutes \$s1→abs(base)+1 when available
- getSpellEffectBasePoints() accessor on GameHandler

Values are DBC base points (before spell power scaling). Still uses
"X" placeholder for unresolved variables (\$d, \$o1, etc.).
2026-03-23 00:51:19 -07:00
Kelsi
587c0ef60d feat: track shapeshift form and fire UPDATE_SHAPESHIFT_FORM events
Add UNIT_FIELD_BYTES_1 to all expansion update field tables (Classic=133,
TBC/WotLK=137). Byte 3 of this field contains the shapeshift form ID
(Bear=1, Cat=3, Travel=4, Moonkin=31, Tree=36, Battle Stance=17, etc.).

Track form changes in the VALUES update handler and fire
UPDATE_SHAPESHIFT_FORM + UPDATE_SHAPESHIFT_FORMS events when the
form changes. This enables stance bar addons and druid form tracking.

New Lua functions:
- GetShapeshiftForm() — returns current form ID (0 = no form)
- GetNumShapeshiftForms() — returns form count by class (Warrior=3,
  Druid=6, DK=3, Rogue=1, Priest=1, Paladin=3)
2026-03-22 22:12:17 -07:00
Kelsi
b9a1b0244b feat: add GetEnchantInfo for enchantment name resolution
GetEnchantInfo(enchantId) looks up the enchantment name from
SpellItemEnchantment.dbc (field 14). Returns the display name
like "Crusader", "+22 Intellect", or "Mongoose" for a given
enchant ID.

Used by equipment comparison addons and tooltip addons to display
enchantment names on equipped gear. The enchant ID comes from the
item's ITEM_FIELD_ENCHANTMENT update field.

Also adds getEnchantName() to GameHandler for C++ access.
2026-03-22 21:53:58 -07:00
Kelsi
3b4909a140 fix: populate item subclass names for TBC expansion
The TBC item query parser left subclassName empty, so TBC items showed
no weapon/armor type in tooltips or the character sheet (e.g., "Sword",
"Plate", "Shield" were all blank). The Classic and WotLK parsers
correctly map subClass IDs to names.

Fix: call getItemSubclassName() in the TBC parser, same as WotLK.
Expose getItemSubclassName() in the header (was static, now shared
across parser files).
2026-03-22 20:30:08 -07:00
Kelsi
e4da47b0d7 feat: add UI_ERROR_MESSAGE events and quest removal notifications
Fire UI_ERROR_MESSAGE from addUIError() so Lua addons can react to
error messages like "Not enough mana" or "Target is too far away".
Previously only the C++ overlay callback was notified. Also add
addUIInfoMessage() helper for informational system messages.

Fire QUEST_REMOVED and QUEST_LOG_UPDATE when quests are removed from
the quest log — both via server-driven removal (SMSG_QUEST_UPDATE_FAILED
etc.) and player-initiated abandon (CMSG_QUESTLOG_REMOVE_QUEST). Quest
tracking addons like Questie register for these events to update their
map markers and objective displays.
2026-03-22 16:53:35 -07:00
Kelsi
5086520354 feat: add spell book tab API for SpellBookFrame addon compatibility
Implement GetNumSpellTabs, GetSpellTabInfo, GetSpellBookItemInfo, and
GetSpellBookItemName — the core functions SpellBookFrame.lua needs to
organize known spells into class skill line tabs.

Tabs are built lazily from knownSpells grouped by SkillLineAbility.dbc
mappings (category 7 = class). A "General" tab collects spells not in
any class skill line. Tabs auto-rebuild when the spell count changes.

Also adds SpellBookTab struct and getSpellBookTabs() to GameHandler.
2026-03-22 15:40:40 -07:00
Kelsi
f29ebbdd71 feat: add quest watch/tracking and selection Lua API for WatchFrame
Implement the quest tracking functions needed by WatchFrame.lua:
- SelectQuestLogEntry/GetQuestLogSelection — quest log selection state
- GetNumQuestWatches — count of tracked quests
- GetQuestIndexForWatch(watchIdx) — map Nth watched quest to log index
- AddQuestWatch/RemoveQuestWatch — toggle quest tracking by log index
- IsQuestWatched — check if a quest log entry is tracked
- GetQuestLink — generate colored quest link string

Backed by existing trackedQuestIds_ set and questLog_ vector.
Adds selectedQuestLogIndex_ state to GameHandler for quest selection.
2026-03-22 15:36:25 -07:00
Kelsi
ce4f93dfcb feat: add UnitCastingInfo/UnitChannelInfo Lua API and fix SMSG_CAST_FAILED events
Expose cast/channel state to Lua addons via UnitCastingInfo(unit) and
UnitChannelInfo(unit), matching the WoW API signature (name, text, texture,
startTime, endTime, isTradeSkill, castID, notInterruptible). Works for
player, target, focus, and pet units using existing UnitCastState tracking.

Also fix handleCastFailed (SMSG_CAST_FAILED, Classic/TBC path) to fire
UNIT_SPELLCAST_FAILED and UNIT_SPELLCAST_STOP events — previously only
the WotLK SMSG_CAST_RESULT path fired these, leaving Classic/TBC addons
unaware of cast failures.

Adds isChannel field to UnitCastState and getCastTimeTotal() accessor.
2026-03-22 15:05:29 -07:00
Paul
027640189a make start on ubuntu intel video cards 2026-03-22 21:47:12 +03:00
Kelsi
2da0883544 feat: fire BARBER_SHOP_OPEN and BARBER_SHOP_CLOSE events
Fire BARBER_SHOP_OPEN when the barber shop UI is enabled
(SMSG_ENABLE_BARBER_SHOP). Fire BARBER_SHOP_CLOSE when the barber
shop completes or is dismissed. Used by UI customization addons.
2026-03-21 07:54:30 -07:00
Kelsi
91794f421e feat: add spell power cost to SpellDataResolver; fix IsUsableSpell mana check
Extend SpellDataInfo with manaCost and powerType fields, extracted from
Spell.dbc ManaCost and PowerType columns. This enables IsUsableSpell()
to properly check if the player has enough mana/rage/energy to cast.

Previously IsUsableSpell always returned notEnoughMana=false since cost
data wasn't available. Now it compares the spell's DBC mana cost against
the player's current power, returning accurate usability and mana state.

This fixes action bar addons showing abilities as usable when the player
lacks sufficient power, and enables OmniCC-style cooldown text to
properly dim insufficient-power abilities.
2026-03-21 04:20:58 -07:00
Kelsi
c7e16646fc feat: resolve spell cast time and range from DBC for GetSpellInfo
Add SpellDataResolver that lazily loads Spell.dbc, SpellCastTimes.dbc,
and SpellRange.dbc to provide cast time and range data. GetSpellInfo()
now returns real castTime (ms), minRange, and maxRange instead of
hardcoded 0 values.

This enables spell tooltip addons, cast bar addons (Quartz), and range
check addons to display accurate spell information. The DBC chain is:
  Spell.dbc[CastingTimeIndex] → SpellCastTimes.dbc[Base ms]
  Spell.dbc[RangeIndex] → SpellRange.dbc[MinRange, MaxRange]

Follows the same lazy-loading pattern as SpellIconPathResolver and
ItemIconPathResolver.
2026-03-21 04:16:12 -07:00
Kelsi
cfb9e09e1d feat: cache player class/race from name queries for UnitClass/UnitRace
Add playerClassRaceCache_ that stores classId and raceId from
SMSG_NAME_QUERY_RESPONSE. This enables UnitClass and UnitRace to return
correct data for players who were previously seen but are now out of
UPDATE_OBJECT range.

Fallback chain for UnitClass/UnitRace is now:
1. Entity update fields (UNIT_FIELD_BYTES_0) — for nearby entities
2. Name query cache — for previously queried players
3. getPlayerClass/Race() — for the local player

This improves class-colored names in chat, unit frames, and nameplates
for players who move out of view range.
2026-03-21 04:11:48 -07:00
Kelsi
7105672f06 feat: resolve item icon paths from ItemDisplayInfo.dbc for Lua API
Add ItemIconPathResolver that lazily loads ItemDisplayInfo.dbc to map
displayInfoId → icon texture path. This fixes three Lua API functions
that previously returned nil for item icons:

- GetItemInfo() field 10 (texture) now returns the icon path
- GetActionTexture() for item-type action bar slots now returns icons
- GetLootSlotInfo() field 1 (texture) now returns proper item icons
  instead of incorrectly using the spell icon resolver

Follows the same lazy-loading pattern as SpellIconPathResolver. The DBC
is loaded once on first query and cached for all subsequent lookups.
2026-03-21 02:53:07 -07:00
Kelsi
32a51aa93d feat: add mouseover unit ID support and fire UPDATE_MOUSEOVER_UNIT/PLAYER_FOCUS_CHANGED events
Add "mouseover" as a valid unit ID in resolveUnitGuid so Lua API functions
like UnitName("mouseover"), UnitHealth("mouseover") etc. work for addons.
Fire UPDATE_MOUSEOVER_UNIT event when the mouseover target changes, and
PLAYER_FOCUS_CHANGED event when focus is set or cleared.
2026-03-21 01:26:37 -07:00
Kelsi
4b3e377add feat: resolve random property/suffix names for item display
Load ItemRandomProperties.dbc and ItemRandomSuffix.dbc lazily to resolve
suffix names like "of the Eagle", "of the Monkey" etc. Add
getRandomPropertyName(id) callback on GameHandler wired through Application.
Append suffix to item names in SMSG_ITEM_PUSH_RESULT loot notifications
so items display as "Leggings of the Eagle" instead of just "Leggings".
2026-03-20 19:18:30 -07:00
Kelsi
14007c81df feat: add /cancelqueuedspell command to clear spell queue
Add cancelQueuedSpell() method that clears queuedSpellId_ and
queuedSpellTarget_. Wire /cancelqueuedspell and /stopspellqueue
slash commands. Useful for combat macros that need to prevent
queued spells from firing after a current cast.
2026-03-20 17:24:16 -07:00
Kelsi
23ebfc7e85 feat: add LFG role check confirmation popup with CMSG_LFG_SET_ROLES
When the dungeon finder initiates a role check (SMSG_LFG_ROLE_CHECK_UPDATE
state=2), show a centered popup with Tank/Healer/DPS checkboxes and
Accept/Leave Queue buttons. Accept sends CMSG_LFG_SET_ROLES with the
selected role mask. Previously only showed passive "Role check in progress"
text with no way to respond.
2026-03-20 16:10:29 -07:00
Kelsi
ae627193f8 feat: fire combat, spell, and cooldown events for Lua addon system
Add PLAYER_REGEN_DISABLED/ENABLED (combat enter/leave) via per-frame
edge detection, LEARNED_SPELL_IN_TAB/SPELLS_CHANGED on spell learn/remove,
SPELL_UPDATE_COOLDOWN/ACTIONBAR_UPDATE_COOLDOWN on cooldown finish, and
PLAYER_XP_UPDATE on XP field changes. Total addon events now at 34.
2026-03-20 14:27:46 -07:00
Kelsi
22b0cc8a3c feat: add GetSpellInfo, GetSpellTexture, GetItemInfo and more Lua API functions
Add spell icon path resolution via SpellIcon.dbc + Spell.dbc lazy loading,
wired through GameHandler callback. Fix UnitBuff/UnitDebuff to return icon
texture paths instead of nil. Add GetLocale, GetBuildInfo, GetCurrentMapAreaID.
2026-03-20 13:58:54 -07:00
Kelsi
269d9e2d40 feat: fire PLAYER_TARGET_CHANGED and PLAYER_LEVEL_UP addon events
Add a generic AddonEventCallback to GameHandler for firing named events
with string arguments directly from game logic. Wire it to the addon
system in Application.

New events fired:
- PLAYER_TARGET_CHANGED — when target is set or cleared
- PLAYER_LEVEL_UP(newLevel) — on level up

The generic callback pattern makes it easy to add more events from
game_handler.cpp without touching Application/AddonManager code.
Total addon events: 16 (2 world + 12 chat + 2 gameplay).
2026-03-20 11:51:46 -07:00
Kelsi
0a0ddbfd9f feat: fire CHAT_MSG_* events to Lua addons for all chat types
Wire chat messages to the addon event system via AddonChatCallback.
Every chat message now fires the corresponding WoW event:

- CHAT_MSG_SAY, CHAT_MSG_YELL, CHAT_MSG_WHISPER
- CHAT_MSG_PARTY, CHAT_MSG_GUILD, CHAT_MSG_OFFICER
- CHAT_MSG_RAID, CHAT_MSG_RAID_WARNING, CHAT_MSG_BATTLEGROUND
- CHAT_MSG_SYSTEM, CHAT_MSG_CHANNEL, CHAT_MSG_EMOTE

Event handlers receive (eventName, message, senderName) arguments.
Addons can now filter, react to, or log chat messages in real-time.
2026-03-20 11:29:53 -07:00
Kelsi
503115292b fix: save character config when quest tracking changes
setQuestTracked() modified trackedQuestIds_ but didn't call
saveCharacterConfig(), so tracked quests were only persisted if
another action (like editing a macro or rearranging the action bar)
happened to trigger a save before logout. Now saves immediately
when quests are tracked or untracked.
2026-03-20 09:48:27 -07:00
Kelsi
6bd950e817 feat: support /use macros for action bar icon and indicators
Macros with /use ItemName (e.g. /use Healthstone, /use Engineering
trinket) had no icon, cooldown, or tooltip on the action bar because
only /cast and /castsequence were recognized. Now the spell resolution
also handles /use by looking up the item name in the item info cache
and finding its on-use spell ID. Added getItemInfoCache() accessor.
2026-03-20 09:08:49 -07:00
Kelsi
595ea466c2 fix: update local equipment set GUID on save confirmation and auto-request played time on login
SMSG_EQUIPMENT_SET_SAVED now updates the local set's GUID from the
server response, preventing duplicate set creation when clicking
"Update" on a newly-saved set. New sets are also added to the local
list immediately so the UI reflects them without a relog.

Additionally, CMSG_PLAYED_TIME is now auto-sent on initial world entry
(with sendToChat=false) so the character Stats tab shows total and
level time immediately without requiring /played.
2026-03-20 05:17:27 -07:00
Kelsi
e68a1fa2ec fix: guard equipment set packets against unsupported expansions
Classic and TBC lack equipment set opcodes, so sending save/use/delete
packets would transmit wire opcode 0xFFFF and potentially disconnect the
client. Now all three methods check wireOpcode != 0xFFFF before sending,
and the Outfits tab is only shown when the expansion supports equipment
sets (via supportsEquipmentSets() check).
2026-03-20 05:12:24 -07:00
Kelsi
f4d705738b fix: send CMSG_SET_WATCHED_FACTION when tracking a reputation
setWatchedFactionId() previously only stored the faction locally.
Now it also sends CMSG_SET_WATCHED_FACTION with the correct repListId
to the server, so the tracked faction persists across sessions.
2026-03-20 04:50:49 -07:00
Kelsi
ae56f2eb80 feat: implement equipment set save, update, and delete
Add saveEquipmentSet() and deleteEquipmentSet() methods that send
CMSG_EQUIPMENT_SET_SAVE and CMSG_DELETEEQUIPMENT_SET packets. The save
packet captures all 19 equipment slot GUIDs via packed GUID encoding.
The Outfits tab now always shows (not just when sets exist), with an
input field to create new sets and Update/Delete buttons per set.
2026-03-20 04:43:46 -07:00
Kelsi
f88d90ee88 feat: track and display honor/arena points from update fields
Add PLAYER_FIELD_HONOR_CURRENCY and PLAYER_FIELD_ARENA_CURRENCY to the
update field system for WotLK (indices 1422/1423) and TBC (1505/1506).
Parse values from both CREATE_OBJECT and VALUES update paths, and show
them in the character Stats tab under a PvP Currency section.
2026-03-20 04:36:30 -07:00
Kelsi
d149255c58 feat: implement petition signing flow for guild charter creation
Parse SMSG_PETITION_QUERY_RESPONSE, SMSG_PETITION_SHOW_SIGNATURES,
and SMSG_PETITION_SIGN_RESULTS. Add UI to view signatures, sign
petitions, and turn in completed charters. Send CMSG_PETITION_SIGN
and CMSG_TURN_IN_PETITION packets.
2026-03-18 12:31:48 -07:00
Kelsi
41e15349c5 feat: improve arena team UI with names, types, and roster requests
Store team name and type (2v2/3v3/5v5) from SMSG_ARENA_TEAM_QUERY_RESPONSE.
Display proper team labels instead of raw IDs. Add Load/Refresh roster
buttons and CMSG_ARENA_TEAM_ROSTER request support.
2026-03-18 12:26:23 -07:00
Kelsi
aed8c94544 feat: add instance difficulty indicator on minimap
Show Normal/Heroic/25-Man difficulty badge below zone name when inside
a dungeon or raid instance. Orange-highlighted for heroic modes.
2026-03-18 12:21:41 -07:00
Kelsi
801f29f043 fix: sync player appearance after barber shop or polymorph
PLAYER_BYTES and PLAYER_BYTES_2 changes in SMSG_UPDATE_OBJECT now
update the Character struct's appearanceBytes and facialFeatures,
and fire an appearance-changed callback that resets the inventory
screen preview so it reloads with the new hair/face values.
2026-03-18 12:17:00 -07:00