Commit graph

116 commits

Author SHA1 Message Date
Paul
027640189a make start on ubuntu intel video cards 2026-03-22 21:47:12 +03:00
Kelsi
64fd7eddf8 feat: implement barber shop UI with hair/facial customization
Adds a functional barber shop window triggered by SMSG_ENABLE_BARBER_SHOP.
Players can adjust hair style, hair color, and facial features using
sliders bounded by race/gender max values. Sends CMSG_ALTER_APPEARANCE
on confirm; server result closes the window on success. Escape key
also closes the barber shop.
2026-03-18 11:58:01 -07:00
Kelsi
9b32a328c3 feat: add item stack splitting via Shift+right-click
Implements CMSG_SPLIT_ITEM (0x10E) with a slider popup for choosing
split count. Auto-finds empty destination slot across backpack and bags.
Shift+right-click on stackable items (count > 1) opens split dialog;
non-stackable items still get the destroy confirmation.
2026-03-18 11:07:27 -07:00
Kelsi
25138b5648 fix: use CMSG_OPEN_ITEM for locked containers (lockboxes)
Right-clicking a locked container (e.g. Dead-Tooth's Strong Box) was
sending CMSG_USE_ITEM with spellId=0, which the server rejects. Locked
containers (itemClass==1, inventoryType==0) now send CMSG_OPEN_ITEM
instead, letting the server auto-check the keyring for the required key.
2026-03-18 06:06:29 -07:00
Kelsi
6f936f258f fix: consume all SpellCastTargets bytes in WotLK SpellGoParser
Applied the same SpellCastTargets fix from SpellStartParser (dd64724)
to SpellGoParser: after parsing hit/miss target lists, now reads the
full target section (UNIT/UNIT_MINIPET/CORPSE/GAMEOBJECT packed GUID,
ITEM/TRADE_ITEM packed GUID, SOURCE/DEST PackedGuid+3floats, null-
terminated STRING). Also adds targetGuid field to SpellGoData so
callers can read the primary target. Prevents stream misalignment on
ground-targeted AoE spells (e.g. Blizzard, Rain of Fire).
2026-03-17 22:26:05 -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
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
0b6265bc55 fix: align turtle protocol compatibility 2026-03-15 01:47:36 -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
3f1083e9b5 fix(combatlog): consume reflect payload in spell-go miss entries 2026-03-13 23:15:56 -07:00
Kelsi
ef7494700e feat: parse and display Heroic/Unique/Unique-Equipped item flags in tooltips 2026-03-13 11:32:32 -07:00
Kelsi
03f8642fad feat: parse and display elemental resistances and race restrictions in item tooltips
- Store holyRes/fireRes/natureRes/frostRes/shadowRes/arcaneRes in ItemQueryResponseData
- Parse resistance fields in WotLK, TBC, and Classic parsers (previously discarded)
- Display non-zero resistances (e.g. "+40 Fire Resistance") in both tooltip paths
- Add getPlayerRace() accessor to GameHandler
- Show race restriction line (e.g. "Races: Blood Elf, Draenei") in both tooltip paths,
  highlighted red when player's race is not allowed
- Useful for fire/nature/frost resist gear (Onyxia, AQ40, Naxx encounters)
2026-03-13 11:23:55 -07:00
Kelsi
b0b47c354a feat: parse and display item skill/reputation requirements in tooltips
- Store requiredSkill, requiredSkillRank, allowableClass, allowableRace,
  requiredReputationFaction, and requiredReputationRank from
  SMSG_ITEM_QUERY_SINGLE_RESPONSE in ItemQueryResponseData (was discarded)
- Show "Requires <Skill> (<rank>)" in item tooltip, highlighted red when
  the player doesn't have sufficient skill level
- Show "Requires <Rank> with <Faction>" for reputation-gated items
- Skill names resolved from SkillLine.dbc; faction names from Faction.dbc
- Also fix loot window tooltip suppressing items with names starting with 'I'
2026-03-13 11:11:33 -07:00
Kelsi
4272491d56 feat: send CMSG_SET_ACTION_BUTTON to server when action bar slot changes
Action bar changes (dragging spells/items) were only saved locally.
Now notifies the server via CMSG_SET_ACTION_BUTTON so the layout
persists across relogs. Supports Classic (5-byte) and TBC/WotLK
(packed uint32) wire formats.
2026-03-13 04:25:05 -07:00
Kelsi
1d9dc6dcae feat: parse SMSG_RESPOND_INSPECT_ACHIEVEMENTS and request on inspect
When the player inspects another player on WotLK 3.3.5a, also send
CMSG_QUERY_INSPECT_ACHIEVEMENTS so the server responds with
SMSG_RESPOND_INSPECT_ACHIEVEMENTS.  The new handler parses the
achievement-id/date sentinel-terminated block (same layout as
SMSG_ALL_ACHIEVEMENT_DATA but prefixed with a packed guid) and stores
the earned achievement IDs keyed by GUID in
inspectedPlayerAchievements_.  The new public getter
getInspectedPlayerAchievements(guid) exposes this data for the inspect
UI.  The cache is cleared on world entry to prevent stale data.
QueryInspectAchievementsPacket::build() handles the CMSG wire format
(uint64 guid + uint8 unk=0).
2026-03-12 23:23:02 -07:00
Kelsi
1bf4c2442a feat: add title selection window with CMSG_SET_TITLE support
Track player titles from SMSG_TITLE_EARNED into knownTitleBits_ set,
read active title from PLAYER_CHOSEN_TITLE update field (WotLK index
1349), expose via getFormattedTitle()/sendSetTitle() on GameHandler.

Add SetTitlePacket builder (CMSG_SET_TITLE: int32 titleBit, -1=clear).

Titles window (H key) lists all earned titles from CharTitles.dbc,
highlights the active one in gold, and lets the player click to equip
or unequip a title with a single server round-trip.
2026-03-12 20:23:36 -07:00
Kelsi
bba2f20588 feat: implement CMSG_PET_RENAME with rename dialog in pet frame
- Add PetRenamePacket::build(petGuid, name, isDeclined) builder
- Add GameHandler::renamePet(newName) — sends packet via petGuid_
- Add 'Rename Pet' to pet frame context menu (right-click pet name)
- Modal input dialog with 12-char limit matches server validation
2026-03-12 19:42:31 -07:00
Kelsi
284b98d93a 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
Kelsi
48f12d9ca8 feat: parse item set ID and display set name in item tooltip via ItemSet.dbc 2026-03-12 12:35:56 -07:00
Kelsi
0a2cd213dc feat: display gem socket slots and socket bonus in item tooltips 2026-03-12 12:15:08 -07:00
Kelsi
ed48a3c425 fix: replace fragile heuristic in SMSG_INITIAL_SPELLS with explicit Classic format flag
Classic 1.12 uses uint16 spellId + uint16 slot (4 bytes/spell); TBC and WotLK
use uint32 spellId + uint16 unknown (6 bytes/spell). The old size-based heuristic
could misdetect TBC packets that happened to fit both layouts. Add a vanillaFormat
parameter to InitialSpellsParser::parse and override parseInitialSpells in
ClassicPacketParsers to always pass true, eliminating the ambiguity.
2026-03-11 04:38:30 -07:00
Kelsi
750b270502 fix: use expansion-aware item size in LootResponseParser for Classic/TBC
The previous per-iteration heuristic (remaining >= 22 → 22 bytes, >= 14 → 14 bytes)
incorrectly parsed Classic/TBC multi-item loots: 2+ items × 14 bytes would
trigger the 22-byte WotLK path for the first item, corrupting subsequent items.

Classic 1.12 and TBC 2.4.3 use 14 bytes/item (slot+itemId+count+displayInfo+slotType).
WotLK 3.3.5a uses 22 bytes/item (adds randomSuffix+randomPropertyId).

Add isWotlkFormat bool parameter to LootResponseParser::parse and pass
isActiveExpansion('wotlk') from handleLootResponse.
2026-03-11 04:01:07 -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
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
62b7622f75 feat: parse and display StartQuest field from item query response
Items that begin a quest (like quest starter drop items) now show
"Begins a Quest" in the tooltip.

All three expansion parsers (WotLK/TBC/Classic) now read the
PageText/LanguageID/PageMaterial/StartQuest fields after Description.
startQuestId is propagated through all 5 inventory rebuild paths and
stored in ItemDef.
2026-03-10 17:05:04 -07:00
Kelsi
321aaeae54 feat: capture and display all item stat types in tooltips
Previously only the 5 primary stats (Str/Agi/Sta/Int/Spi) were stored,
discarding hit rating, crit, haste, attack power, spell power, resilience,
expertise, armor penetration, MP5, and many others.

Changes:
- Add ItemDef::ExtraStat and ItemQueryResponseData::ExtraStat arrays
- All three expansion parsers (WotLK/TBC/Classic) now capture non-primary
  stat type/value pairs into extraStats instead of silently dropping them
- All 5 rebuildOnlineInventory paths propagate extraStats to ItemDef
- Tooltip now renders each extra stat on its own line with a name lookup
  covering all common WotLK stat types (hit, crit, haste, AP, SP, etc.)
- Also fix Classic/TBC bag-content and bank-bag paths that were missing
  bindType, description propagation from previous commits
2026-03-10 17:00:24 -07:00
Kelsi
76bd6b409e feat: enhance item tooltips with binding, description, speed, and spell effects
- Parse Bonding and Description fields from SMSG_ITEM_QUERY_SINGLE_RESPONSE
  (read after the 5 spell slots: bindType uint32, then description cstring)
- Add bindType and description to ItemQueryResponseData and ItemDef
- Propagate bindType and description through all 5 rebuildOnlineInventory paths
- Tooltip now shows: "Binds when picked up/equipped/used/quest item"
- Tooltip now shows weapon damage range ("X - Y Damage") and speed ("Speed 2.60")
  on same line, plus DPS in parentheses below
- Tooltip now shows spell effects ("Use: <SpellName>", "Equip: <SpellName>",
  "Chance on Hit: ...") using existing getSpellName() lookup
- Tooltip now shows item flavor/lore description in italic-style yellow text
2026-03-10 16:47:55 -07:00
Kelsi
1793549550 feat: parse and display item level and required level in tooltips
- Add itemLevel/requiredLevel fields to ItemQueryResponseData (parsed
  from SMSG_ITEM_QUERY_SINGLE_RESPONSE) and ItemDef
- Propagate through all 5 rebuildOnlineInventory() paths
- Show "Item Level N" and "Requires Level N" in item tooltip in
  standard WoW order (below item name, above required level/stats)
2026-03-10 16:26:20 -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
1a370fef76 fix: chat prefix, hostile faction display, and game object looting
- Add BG_SYSTEM_NEUTRAL/ALLIANCE/HORDE chat types (0x52-0x54) and reclassify
  them as SYSTEM in the parser — prevents bogus [Say] prefix on arena/BG
  system messages
- Remove fallback [TypeName] bracket for sender-less SAY/YELL/WHISPER messages;
  only group-channel types (Party/Guild/Raid/BG) show brackets without a sender
- Remove factionTemplate != 0 guard — units with FT=0 now get setHostile() like
  any other unit (defaulting to hostile from the map default), fixing NPCs that
  appeared friendly due to unset faction template
- Enable CMSG_LOOT for WotLK type=3 (chest) game objects in addition to
  CMSG_GAMEOBJ_USE — fixes Milly's Harvest and other quest gather objects on
  AzerothCore WotLK servers
2026-03-10 15:32:04 -07:00
Kelsi
1853e8aa56 physics: implement Water Walk movement state tracking and surface clamping
SMSG_MOVE_WATER_WALK / SMSG_MOVE_LAND_WALK now correctly set/clear
WATER_WALK (0x00008000) in movementInfo.flags, ensuring the flag is
included in movement ACKs sent to the server.

In CameraController, when waterWalkActive_ is set and the player is
at or above the water surface (within 0.5 units), clamp them to the
water surface and mark as grounded — preventing water entry and allowing
them to walk across the water surface as the spell intends.
2026-03-10 13:18:04 -07:00
Kelsi
0b99cbafb2 physics: implement feather fall and water walk movement flag tracking
Feather Fall (SMSG_MOVE_FEATHER_FALL / SMSG_MOVE_NORMAL_FALL):
- Add FEATHER_FALL = 0x00004000 to MovementFlags enum
- Fix handlers to set/clear the flag instead of passing flag=0
- Cap downward terminal velocity at -2.0 m/s in CameraController when
  feather fall is active (Slow Fall, Parachute, etc.)

All three handlers now correctly propagate server movement state flags
that were previously acknowledged without updating any local state.
2026-03-10 13:14:52 -07:00
Kelsi
863ea742f6 net/game: initialise entity swim/walk state from spawn packet and SPLINE_MOVE opcodes
UpdateBlock now stores moveFlags from the LIVING movement block so the
cold-join problem is fixed: entities already swimming or walking when the
client joins get their animation state correctly initialised from the
SMSG_UPDATE_OBJECT CREATE_OBJECT packet rather than waiting for the next
MSG_MOVE_* heartbeat.

Additionally, SMSG_SPLINE_MOVE_START_SWIM, SMSG_SPLINE_MOVE_STOP_SWIM,
SMSG_SPLINE_MOVE_SET_WALK_MODE, SMSG_SPLINE_MOVE_SET_RUN_MODE, and
SMSG_SPLINE_MOVE_SET_FLYING now fire unitMoveFlagsCallback_ with
synthesised flags so explicit server-driven mode transitions update
animation state immediately without waiting for a heartbeat.
2026-03-10 11:14:58 -07:00
Kelsi
528b796dff game: fix Classic 1.12 SMSG_AUCTION_LIST_RESULT enchant slot count
Classic 1.12 auction entries contain only 1 enchant slot (3 uint32s),
while TBC and WotLK expanded this to 3 enchant slots (9 uint32s). Parsing
Classic auction results with the WotLK parser consumed 24 extra bytes per
entry (two extra enchant slots), corrupting randomPropertyId, stackCount,
ownerGuid, pricing and expiry data for every auction item.

- AuctionListResultParser::parse() gains a numEnchantSlots parameter (default 3)
- Classic path reads 1 enchant slot; TBC/WotLK read 3
- handleAuctionListResult/OwnerList/BidderList pass isClassicLikeExpansion()?1:3
2026-03-10 01:25:27 -07:00
Kelsi
8dd4bc80ec game: fix Classic 1.12 SMSG_TRAINER_LIST per-spell field layout
Classic 1.12 trainer list entries lack the profDialog and profButton
uint32 fields (8 bytes) that TBC/WotLK added before reqLevel. Instead,
reqLevel immediately follows spellCost, and a trailing unk uint32 appears
at the end of each entry. Parsing the WotLK format for Classic caused
misalignment from the third field onward, corrupting state, cost, level,
skill, and chain data for all trainer spells.

- TrainerListParser::parse() gains a isClassic bool parameter (default false)
- Classic path: cost(4) → reqLevel(1) → reqSkill... → chainNode3 → unk(4)
- WotLK/TBC path: cost(4) → profDialog(4) → profButton(4) → reqLevel(1) → reqSkill...
- handleTrainerList() passes isClassicLikeExpansion() as the flag
2026-03-10 01:20:41 -07:00
Kelsi
c19edd407a game: fix Classic/TBC SMSG_TEXT_EMOTE field order
Classic 1.12 and TBC 2.4.3 send SMSG_TEXT_EMOTE with the field order:
  textEmoteId(u32) + emoteNum(u32) + senderGuid(u64) + nameLen(u32) + name

WotLK 3.3.5a swapped senderGuid to the front:
  senderGuid(u64) + textEmoteId(u32) + emoteNum(u32) + nameLen(u32) + name

The previous TextEmoteParser always used the WotLK order, causing senderGuid
to be read as a mashup of textEmoteId+emoteNum for Classic/TBC. Emote
animations and chat entries were associated with wrong GUIDs.

TextEmoteParser::parse now takes a legacyFormat parameter; handleTextEmote
passes it based on expansion detection.
2026-03-10 01:05:23 -07:00
Kelsi
a0979b9cd8 game: fix Classic/TBC SMSG_GROUP_LIST parsing - missing roles byte
WotLK 3.3.5a added a group-level and per-member roles byte (tank/healer/dps)
for the Dungeon Finder system. Classic 1.12 and TBC 2.4.3 do not send this byte.

The previous GroupListParser always read the roles byte, causing a one-byte
misalignment in Classic/TBC group lists that corrupted member GUID reads and
all subsequent fields (loot method, leader GUID, etc.).

GroupListParser::parse now takes a hasRoles parameter (default true for
backward compatibility). handleGroupList passes hasRoles=isActiveExpansion("wotlk").
Also adds range-checking throughout to prevent out-of-bounds reads on
malformed or unexpectedly short group list packets.
2026-03-10 00:58:56 -07:00
Kelsi
6951b7803d game: fix SMSG_SPELL_GO miss-entry consumption in WotLK and TBC parsers
Both SpellGoParser::parse (WotLK) and TbcPacketParsers::parseSpellGo
(TBC) read missCount but did not consume the per-miss (guid + missType)
entries that follow, leaving unread bytes in the packet and silently
corrupting any subsequent parsing of cast-flags–gated spell data.

- Add SpellGoMissEntry{targetGuid, missType} and missTargets vector
  to SpellGoData
- WotLK parser now reads packed GUIDs + missType per miss entry
- TBC parser now reads full uint64 GUIDs + missType per miss entry
  (9 bytes per entry, bounds-checked)
- handleSpellGo now shows MISS/DODGE/PARRY/BLOCK combat text
  for each missed target when the local player cast the spell,
  complementing the existing SMSG_SPELLLOGMISS path
- Remove unused foliageLikeModel variable in m2_renderer pass-2 loop
  (fix unused-variable warning)
- Update smoke model comment in m2_renderer to reflect current state
2026-03-09 23:00:21 -07:00
Kelsi
06a628dae2 game: implement SMSG_PET_SPELLS/MODE/BROKEN and pet action plumbing
SMSG_PET_SPELLS: Parse full packet — pet GUID, react/command state,
10 action bar slots, per-spell entries with autocast flags.  Previously
only read the GUID.

SMSG_PET_MODE: Parse petGuid + mode uint32 (command low byte, react
high byte) to keep stance state in sync after server updates.

SMSG_PET_BROKEN: Clear pet state and show "Your pet has died." chat
message.

SMSG_PET_LEARNED_SPELL / SMSG_PET_UNLEARNED_SPELL: Maintain pet spell
list incrementally.

SMSG_PET_CAST_FAILED: Parse and log cast count + spell + reason.

New state accessors: getPetActionSlot(), getPetCommand(), getPetReact(),
getPetSpells(), isPetSpellAutocast().

CMSG_PET_ACTION: Add targetGuid (uint64) field — the wire format
requires petGuid(8)+action(4)+targetGuid(8).  Was sending an 12-byte
packet instead of the required 20 bytes.

sendPetAction(): New method that builds and sends CMSG_PET_ACTION with
the correct target guid.
2026-03-09 22:53:09 -07:00
Kelsi
52c1fed6ab game: implement dual-spec switch via CMSG_SET_ACTIVE_TALENT_GROUP (0x4C3)
switchTalentSpec() was only updating local state without notifying the
server, leaving the server out of sync with the client's active talent
group. Now sends CMSG_SET_ACTIVE_TALENT_GROUP_OBSOLETE (WotLK wire
opcode 0x4C3) with the target group index (0=primary, 1=secondary),
prompting the server to apply the spec swap and respond with a fresh
SMSG_TALENTS_INFO for the newly active group.

Also adds ActivateTalentGroupPacket::build() to world_packets for the
packet construction.
2026-03-09 22:49:23 -07:00
Kelsi
f369fe9c6e 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
Kelsi
2d124e7e54 Implement duel request/accept/decline UI and packet handling
- Parse SMSG_DUEL_REQUESTED: store challenger guid/name, set
  pendingDuelRequest_ flag, show chat notification
- Parse SMSG_DUEL_COMPLETE: clear pending flag, notify on cancel
- Parse SMSG_DUEL_WINNER: show "X defeated Y in a duel!" chat message
- Handle SMSG_DUEL_OUTOFBOUNDS with warning message
- Add acceptDuel() method sending CMSG_DUEL_ACCEPTED (new builder)
- Wire forfeitDuel() to clear pendingDuelRequest_ on decline
- Add renderDuelRequestPopup() ImGui window (Accept/Decline buttons)
  positioned near group invite popup; shown when challenge is pending
- Add DuelAcceptPacket builder to world_packets.hpp/cpp
2026-03-09 13:58:02 -07:00
Kelsi
b948720ec3 Fix NPC chat showing only name without message text
Two bugs in SMSG_MESSAGECHAT parser for MONSTER_SAY/YELL/EMOTE:

1. Sender name included trailing null byte from server (nameLen includes
   null terminator). The embedded null in std::string caused ImGui to
   truncate the concatenated display string at the NPC name, hiding
   " says: <message>" entirely.

2. Missing NamedGuid receiver name for non-player/non-pet targets. When
   the receiver GUID is a creature, the server writes an additional
   SizedCString (target name) that we weren't reading, shifting all
   subsequent field reads.

Also adds MONSTER_WHISPER, MONSTER_PARTY, RAID_BOSS_EMOTE, RAID_BOSS_WHISPER
chat types with proper parsing and display formatting (says/yells/whispers).
2026-03-02 08:31:34 -08:00
Kelsi
74b78cd10b Add pet tracking via SMSG_PET_SPELLS and dismiss pet button 2026-02-26 10:41:29 -08:00
Kelsi
1c07e87b7e Add missing movement ACK responses to avoid server stalls
Implement generic handlers for force speed changes (walk, run back,
swim, swim back, flight, flight back, turn rate, pitch rate),
movement flag toggles (CAN_FLY, HOVER, feather fall, water walk),
and knockback ACKs. Fix SMSG_TIME_SYNC_REQ to respond with
CMSG_TIME_SYNC_RESP instead of silently dropping.
2026-02-26 03:02:51 -08:00
Kelsi
c919477e74 Fix item use (CMSG_USE_ITEM), mount tab, and inventory right-click
- Fix SMSG_ITEM_QUERY_SINGLE_RESPONSE parsing: read statsCount stat
  pairs instead of always 10, use 2 damage entries (MAX_ITEM_PROTO_DAMAGES),
  and parse item spell data (spellId + spellTrigger per slot)
- Pass item spell ID in CMSG_USE_ITEM packet so server processes item
  use requests (spellId=0 caused silent server rejection)
- Add spellId parameter to buildUseItem interface across all expansions
- Fix spellbook mount tab to use SkillLine 777 (Mounts) instead of 762
  (Riding), so known mount summon spells appear correctly
- Fix inventory right-click: use IsItemHovered+IsMouseClicked instead
  of IsItemClicked for InvisibleButton (which only tracks left-clicks)
- Fix SlotKind enum declaration order in inventory_screen.hpp
2026-02-26 00:59:07 -08:00
Kelsi
1ae5fe867c Improve auction house UI with search filters, pagination, sell picker, and tooltips
- Add item class/subclass category filters (Weapon, Armor, etc.) with correct WoW 3.3.5a IDs
- Add sell item picker dropdown with icons and Create Auction button
- Add pagination (Prev/Next) for browse results with filter preservation
- Add Buy/Bid action buttons to Bids tab
- Add item icons and stat tooltips on hover across all three tabs
- Add Enter-to-search from name field and search delay countdown
- Parse SMSG_AUCTION_OWNER/BIDDER_NOTIFICATION into chat messages
- Auto-refresh browse results after bid/buyout using saved search params
- Clamp level range inputs to 0-80
2026-02-25 14:44:44 -08:00
Kelsi
9906269671 Add mail item attachment support for sending
- CMSG_SEND_MAIL now includes item GUIDs (up to 12 per WotLK)
- Right-click items in bags to attach when mail compose is open
- Compose window shows 12-slot attachment grid with item icons
- Click attached items to remove them
- Classic/Vanilla falls back to single item GUID format
2026-02-25 14:11:09 -08:00
Kelsi
c04e97e375 Fix street sign interaction text and M2 sign orientation
Add page-text support for sign-like gameobject interactions by handling SMSG_GAMEOBJECT_PAGETEXT and SMSG_PAGE_TEXT_QUERY_RESPONSE, and issuing CMSG_PAGE_TEXT_QUERY when page IDs are available from cached GO template data.

Normalize received page text tokens before chat display and add a fallback for basic signpost GO type clicks to print sign names when no page data is present.

Correct M2 gameobject yaw alignment for signposts/arrows by applying render-space -90deg offset consistently across spawn, position update, and move-callback transforms; keep WMO orientation path unchanged.
2026-02-20 23:31:30 -08:00