Commit graph

551 commits

Author SHA1 Message Date
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
b5291d1883 Revert quest reward window delay that caused dialog to hang
The delayed-opening logic conflicted with quest details' use of the same
questDetailsOpenTime variable, causing the reward dialog to never appear.
Reverted to immediately opening the window. Item info queries are still
triggered, but will populate asynchronously with placeholders shown initially.
2026-03-11 19:11:02 -07:00
Kelsi
510370dc7b Delay quest reward window opening to load item icons/names
Add 100ms delay before opening the quest offer reward dialog, giving item
info queries time to complete. Prevents "Item X" placeholders where players
can't see item names or icons needed to choose rewards. Reuses the existing
questDetailsOpenTime mechanism with delayed flag check in isQuestOfferRewardOpen().
2026-03-11 18:55:13 -07:00
Kelsi
182b6686ac Pre-query action bar item information to avoid placeholder display
When items are placed on the action bar, pre-fetch their ItemDef information
so the action bar displays the item name instead of a generic "Item" placeholder.
This ensures item names are available when the action bar is rendered, consistent
with the fix applied to quest reward items display.

Calls queryItemInfo() when an item is assigned to an action bar slot.
2026-03-11 18:36:32 -07:00
Kelsi
eef269ffb8 Fix quest reward items showing as 'Item {number}' on first frame
Quest reward items (both in details and offer-reward windows) were showing as "Item {itemId}"
placeholders because the window opened immediately after receiving SMSG_QUESTGIVER_QUEST_DETAILS,
before the item query responses from pre-fetched queries had time to arrive.

Solution: Delay opening the quest details window by 100ms to allow item queries to complete
and be cached before the window first renders. Uses std::chrono::steady_clock for timing.

- Add questDetailsOpenTime field to track delayed opening timestamp
- Modify isQuestDetailsOpen() to check timer and open window when time expires
- Reset timer whenever quest details window closes
- Updated comment to clarify pre-fetch benefits both details and offer-reward windows
2026-03-11 17:27:23 -07:00
Kelsi
b5a48729b8 Add diagnostic logging for player appearance extraction failures
Log a warning when player model spawn fails due to appearance data extraction failure.
This helps diagnose why players appear invisible (missing field indices or malformed
update packets). Logs at both CREATE_OBJECT and VALUES update points.
2026-03-11 17:12:05 -07:00
Kelsi
eb3cdbcc5f Fix stacked item count display in bags after looting
Move onlineItems_ lookup outside field iteration to ensure consistent item
reference when updating stack count/durability. This fixes an issue where
stacked item counts in open bags wouldn't update immediately when looting
additional items until the item was moved to another slot.
2026-03-11 16:58:36 -07:00
Kelsi
4d0eef1f6f Skip tab-targeting empty looted corpses
Dead creatures with no remaining loot items are now excluded from tab-targeting
cycle. Prevents cycling through empty corpses when looking for targetable enemies.
Corpses with available loot remain targetable.
2026-03-11 16:52:53 -07:00
Kelsi
593f06bdf7 fix: correct Classic/TBC loot packet format parsing (missing randomSuffix/randomPropId)
SMSG_LOOT_START_ROLL, SMSG_LOOT_ALL_PASSED, and loot roll handlers unconditionally
read randomSuffix and randomPropertyId fields. These fields only exist in WotLK 3.3.5a
and NOT in Classic 1.12 / TBC 2.4.3, causing packet stream corruption on Classic/TBC servers.

Packet format differences:
- WotLK: includes randomSuffix (4) + randomPropId (4) fields
- Classic/TBC: no random property fields

Fix gates the field reads based on active expansion:
- SMSG_LOOT_START_ROLL: WotLK 33 bytes vs Classic/TBC 25 bytes
- SMSG_LOOT_ALL_PASSED: WotLK 24 bytes vs Classic/TBC 16 bytes
- SMSG_LOOT_ROLL: WotLK 34 bytes vs Classic/TBC 26 bytes
- SMSG_LOOT_ROLL_WON: WotLK 34 bytes vs Classic/TBC 26 bytes

This prevents packet stream desynchronization when loot rolls occur on Classic/TBC servers.
2026-03-11 05:09:43 -07:00
Kelsi
dd67c88175 fix: conditionally include trailing byte in CMSG_BUY_ITEM for Classic/TBC
CMSG_BUY_ITEM format differs by expansion:
- WotLK 3.3.5a / AzerothCore: includes trailing uint8(0) after count field (17 bytes)
- Classic 1.12 / TBC 2.4.3: no trailing byte (16 bytes)

The static BuyItemPacket::build() helper always adds the byte (AzerothCore compat).
GameHandler::buyItem() now gates the byte based on active expansion, allowing
Classic/TBC servers to receive correctly-sized packets.
2026-03-11 04:49:18 -07:00
Kelsi
9d0da6242d fix: correct Classic/TBC MSG_MOVE_TELEPORT_ACK movement info parsing
Classic 1.12 and TBC 2.4.3 movement packets omit the moveFlags2 (uint16)
field present in WotLK 3.3.5a. The prior handler unconditionally read 2 bytes
for moveFlags2, shifting the timestamp and position reads by 2 bytes and
producing garbage coordinates after a teleport. Now gated by expansion.
2026-03-11 04:32:00 -07:00
Kelsi
d3241dce9e fix: handle Classic 1.12 SMSG_WEATHER missing isAbrupt byte
Classic 1.12 sends weatherType(4)+intensity(4) with no trailing isAbrupt byte;
TBC/WotLK append uint8 isAbrupt. The prior check required >= 9 bytes, so weather
never updated on Classic servers. Now accept >= 8 bytes and read isAbrupt only if
the byte is present.
2026-03-11 04:25:00 -07:00
Kelsi
fed03f970c fix: correct SMSG_BATTLEFIELD_STATUS Classic 1.12 packet layout
Classic uses queueSlot(4)+bgTypeId(4)+unk(2)+instanceId(4)+isReg(1)+statusId(4);
TBC/WotLK prefixes arenaType(1)+unk(1) before bgTypeId. Reading TBC format on
Classic caused bgTypeId to be read from wrong offset, corrupting BG queue state.
2026-03-11 04:22:18 -07:00
Kelsi
8493729a10 fix: use uint16 spellId in Classic 1.12 SMSG_LEARNED/REMOVED/SUPERCEDED_SPELL
Classic 1.12 (vmangos/cmangos) sends uint16 spellIds in SMSG_LEARNED_SPELL,
SMSG_REMOVED_SPELL, and SMSG_SUPERCEDED_SPELL. TBC 2.4.3 and WotLK 3.3.5a
use uint32. The handlers were unconditionally reading uint32, causing the
first byte of the next field to be consumed as part of the spellId on
Classic, producing garbage spell IDs and breaking known-spell tracking.

Apply the same Classic/TBC+WotLK gate used by the SMSG_INITIAL_SPELLS
heuristic: read uint16 for Classic, uint32 for all others.
2026-03-11 04:08:16 -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
dd7d74cb93 fix: correct SMSG_SPELL_FAILURE Classic format and result enum shift
Classic 1.12 SMSG_SPELL_FAILURE omits the castCount byte that TBC/WotLK
include (format: uint64 GUID + uint32 spellId + uint8 failReason).
The previous code read a castCount for all expansions, misaligning
spellId and failReason for Classic by one byte.

Also apply the same +1 enum shift used in parseCastFailed/parseCastResult:
Classic result 0=AFFECTING_COMBAT maps to WotLK 1=AFFECTING_COMBAT,
so Classic failReason=0 now correctly shows an error instead of being
silently swallowed.
2026-03-11 03:54:33 -07:00
Kelsi
2f0809b570 fix: correct TBC aura entry minimum-size guard from 13 to 15 bytes
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
Each SMSG_INIT/SET_EXTRA_AURA_INFO entry is 15 bytes:
  uint8 slot(1) + uint32 spellId(4) + uint8 effectIndex(1)
  + uint8 flags(1) + uint32 durationMs(4) + uint32 maxDurMs(4) = 15

The previous guard of 13 would allow the loop to start reading a
partial entry, silently returning zeroes for durationMs/maxDurMs
when 13-14 bytes remained in the packet.
2026-03-11 03:49:54 -07:00
Kelsi
144c87a72f feat: show spell failure reason in chat from SMSG_SPELL_FAILURE
SMSG_SPELL_FAILURE carries a failReason byte (same enum as SMSG_CAST_RESULT)
that was previously ignored. Now parse castCount+spellId+failReason and
display the localized reason string for the player's interrupted casts
(e.g. 'Interrupted', 'Stunned', 'Can\'t do that while moving').
2026-03-11 03:42:41 -07:00
Kelsi
1446d4fddd fix: pass player power type to getSpellCastResultString for result 85
Result 85 is 'not enough power' — the message should say 'Not enough
rage', 'Not enough energy', 'Not enough runic power', etc. based on
the player's actual power type rather than always showing 'Not enough
mana'.
2026-03-11 03:41:49 -07:00
Kelsi
84a6ee4801 fix: surface absorb/resist in SMSG_ENVIRONMENTAL_DAMAGE_LOG (Classic/TBC)
The Classic/TBC variant handler was discarding the resisted field entirely
(only reading absorbed but discarding it). Now reads and shows both as
ABSORB/RESIST combat text, matching the WotLK SMSG_ENVIRONMENTALDAMAGELOG
fix from the previous commit.
2026-03-11 03:40:41 -07:00
Kelsi
00db93b7f2 fix: show RESIST (not MISS) for SMSG_PROCRESIST combat text
SMSG_PROCRESIST is sent when a proc effect is resisted. Show 'Resisted'
rather than 'Miss' to correctly communicate what happened to the player.
2026-03-11 03:38:39 -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
d1c5e09127 fix: correct SMSG_PERIODICAURALOG packet format for WotLK 3.3.5a
WotLK adds an overkill(4) field between damage and school for aura type
3/89 (periodic damage), and adds absorbed(4)+isCrit(1) after overHeal
for aura type 8/124/45 (periodic heal). Without these fields the absorb
and resist values were reading out-of-alignment, producing garbage data.

Also surfaces the heal-absorbed amount as ABSORB combat text (e.g. when
a HoT tick is partially absorbed by Vampiric Embrace counter-healing).
2026-03-11 03:34:27 -07:00
Kelsi
f50cb04887 feat: surface absorb/resist from SMSG_ENVIRONMENTALDAMAGELOG
Environmental damage (drowning, lava, fire) also carries absorb/resist
fields. Show these as ABSORB/RESIST combat text so players see the full
picture of incoming environmental hits, consistent with spell/melee.
2026-03-11 03:31:33 -07:00
Kelsi
031448ec6d feat: show absorb/resist on periodic damage (DoT) ticks
SMSG_PERIODICAURALOG already parsed abs/res fields for type 3/89 but
discarded them. Surface these as ABSORB/RESIST combat text so players
see when DoT ticks are being partially absorbed (e.g. vs. PW:Shield).
2026-03-11 03:30:24 -07:00
Kelsi
dfc78572f5 feat: show melee absorb/resist in combat text from SMSG_ATTACKERSTATEUPDATE
Sub-damage entries carry absorbed/resisted per school. Accumulate these
and emit ABSORB/RESIST combat text alongside the hit damage when nonzero,
matching the behavior just added for SMSG_SPELLNONMELEEDAMAGELOG.
2026-03-11 03:29:37 -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
d5196abaec fix: show IMMUNE text for miss type 5 in SMSG_SPELL_GO and SMSG_SPELLLOGMISS
IMMUNE misses (spell miss type 5) were shown as generic MISS text in both
spell cast feedback handlers. Now consistently shows IMMUNE combat text
to match the fix already applied to SMSG_ATTACKERSTATEUPDATE.
2026-03-11 03:13:14 -07:00
Kelsi
35683920ff fix: handle EVADE/IMMUNE/DEFLECT victimStates in melee combat text
SMSG_ATTACKERSTATEUPDATE victimState values 5 (EVADE), 6 (IMMUNE), and
7 (DEFLECT) were previously falling through to the damage display path,
showing incorrect damage numbers instead of the proper miss/immune feedback.
Now correctly shows MISS for evade/deflect and IMMUNE for immune hits.
2026-03-11 03:09:39 -07:00
Kelsi
1646bef1c2 fix: add size guards to spell learn/remove handlers and implement SMSG_SPELLSTEALLOG
handleLearnedSpell, handleRemovedSpell, handleSupercededSpell, and
handleUnlearnSpells all lacked size checks before reading packet fields.
Also implements SMSG_SPELLSTEALLOG (previously silently consumed) with
proper player feedback showing the stolen spell name when the local player
is the caster, matching the same expansion-conditional packed-guid format
as SPELLDISPELLOG.
2026-03-11 03:03:44 -07:00
Kelsi
ae6c2aa056 fix: correct SMSG_SPELLDISPELLOG entry size from 8 to 5 bytes
Each dispelled spell entry is uint32(spellId) + uint8(isPositive) = 5 bytes,
not uint32 + uint32 = 8 bytes as the loop previously assumed.

The incorrect stride caused the second and subsequent entries to be read at
wrong offsets, potentially showing the wrong spell name for multi-dispels.
2026-03-11 02:57:05 -07:00
Kelsi
603e52e5b0 fix: add size check and skip WotLK guid suffix in handleCooldownEvent
SMSG_COOLDOWN_EVENT in WotLK appends an 8-byte unit guid after the spellId.
The handler was reading without a size check and not consuming the trailing
guid, which could misalign subsequent reads.
2026-03-11 02:51:58 -07:00
Kelsi
0a17683545 fix: correct WotLK packed guid format in SMSG_PROCRESIST and SMSG_TOTEM_CREATED
Both opcodes use packed GUIDs in WotLK 3.3.5a but were reading full uint64,
causing incorrect GUID parsing and potentially matching wrong player entities.

SMSG_PROCRESIST: caster + victim guids (packed in WotLK, uint64 in TBC/Classic)
SMSG_TOTEM_CREATED: totem guid (packed in WotLK, uint64 in TBC/Classic)
2026-03-11 02:50:53 -07:00
Kelsi
9cd7e7978d fix: correct SMSG_DISPEL_FAILED packet format and improve message
WotLK sends spellId(4) + packed_guid caster + packed_guid victim, while
TBC/Classic sends full uint64 caster + uint64 victim + spellId(4).
The previous handler assumed TBC format unconditionally, causing incorrect
reads in WotLK mode.

Also use the spell name cache to display "Purge failed to dispel." rather
than a raw "Dispel failed! (spell N)" message.
2026-03-11 02:49:37 -07:00
Kelsi
1f4880985b fix: correct SMSG_SPELLLOGMISS packet format for all expansions
All expansions send spellId(4) before the caster guid — the previous
handler was missing this field entirely, causing the caster guid read
to consume spellId bytes and corrupt all subsequent parsing.

Additionally, in WotLK mode, victim guids inside the per-miss loop are
packed guids (not full uint64), matching the caster guid format.

Also handle the REFLECT (missInfo=11) extra payload in WotLK: the server
appends reflectSpellId(4) + reflectResult(1) for reflected spells, which
previously caused the following loop entries to be mis-parsed.
2026-03-11 02:47:15 -07:00
Kelsi
d696da9227 fix: also use school mask for pre-cast melee range/facing check in castSpell()
Same DBC-driven physical school detection replaces the brittle hardcoded
warrior spell list in the pre-cast range check, so rogue, DK, paladin,
feral druid, and hunter melee abilities get correct range/facing enforcement.
2026-03-11 02:40:27 -07:00
Kelsi
21c55ad6b4 fix: detect melee abilities via spell school mask instead of hardcoded spell ID list
Replace the brittle warrior-only hardcoded spell ID list for melee ability
detection with a DBC-driven check: physical school mask (1) from spellNameCache_
covers warrior, rogue, DK, paladin, feral druid, and all other physical-school
instant abilities generically. Instant detection: spellId != currentCastSpellId.
2026-03-11 02:39:25 -07:00
Kelsi
643d48ee89 fix: show reason-specific messages for SMSG_TRANSFER_ABORTED
Replace generic 'Transfer aborted' message with WotLK TRANSFER_ABORT_*
reason codes: difficulty, expansion required, instance full, too many
instances, zone in combat, etc.
2026-03-11 02:36:55 -07:00
Kelsi
3082df2ac0 fix: use packed guids in SMSG_SPELLDAMAGESHIELD for WotLK and read absorbed field
WotLK 3.3.5a format uses packed guids (not full uint64) for victim and caster,
and adds an absorbed(4) field before schoolMask. Classic/TBC use full uint64 guids.
Previously the handler always read full uint64 guids, causing misparse on WotLK
(e.g. Thorns and Shield Spike damage shield combat text was garbled/wrong).
2026-03-11 02:27:57 -07:00
Kelsi
c4b2089d31 fix: handle OBS_MOD_POWER and PERIODIC_ENERGIZE aura types in SMSG_PERIODICAURALOG
Add PERIODIC_ENERGIZE (91) and OBS_MOD_POWER (46) handling so mana/energy/rage
restore ticks from common WotLK auras (Replenishment, Mana Spring Totem, Divine
Plea, etc.) appear as ENERGIZE in floating combat text. Also handle PERIODIC_MANA_LEECH
(98) to properly consume its 12 bytes instead of halting mid-event parse.
2026-03-11 02:25:42 -07:00
Kelsi
a67feb6d93 Fix handleInstanceDifficulty to handle variable-length packet formats
MSG_SET_DUNGEON_DIFFICULTY sends 4 or 12 bytes (difficulty + optional
isInGroup + savedBool) while SMSG_INSTANCE_DIFFICULTY sends 8 bytes
(difficulty + heroic).  The previous guard of < 8 caused the handler
to silently return for 4-byte variants, leaving instanceDifficulty_
unchanged.  Now reads as much as available and infers heroic flag from
the field count.
2026-03-11 02:08:38 -07:00
Kelsi
570465f51a fix: handle MSG_SET_DUNGEON_DIFFICULTY and suppress SMSG_LEARNED_DANCE_MOVES warnings 2026-03-11 01:48:18 -07:00
Kelsi
4393798409 fix: parse WotLK areaId field in SMSG_INIT_WORLD_STATES to fix truncation warning 2026-03-11 01:40:33 -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
170ff1597c fix: prefetch item info for trade slot items in SMSG_TRADE_STATUS_EXTENDED
After parsing the peer's trade window state, query item info for all
occupied slots so item names display immediately rather than showing
'Item 12345' until the cache is populated on the next frame.
2026-03-11 00:46:11 -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
7c5d688c00 fix: show area name in SMSG_ZONE_UNDER_ATTACK system message
Replace the raw area ID in the zone-under-attack message with the
resolved area name from the zone manager, matching retail WoW behavior
('Hillsbrad Foothills is under attack!' instead of 'area 267').
2026-03-11 00:36:40 -07:00
Kelsi
eaf827668a fix: parse SMSG_QUESTUPDATE_ADD_PVP_KILL and update quest log kill counts
Previously only displayed a chat message without updating the quest
tracker. Now parses the full packet (guid+questId+count+reqCount),
stores progress under entry-key 0 in killCounts, and shows a progress
message matching the format used for creature kills.

Handles both WotLK (4-field) and Classic (3-field, no reqCount) variants
with fallback to the existing killCounts or killObjectives for reqCount.
2026-03-11 00:34:23 -07:00
Kelsi
72a16a2427 fix: clear gossip/quest POI markers on map change (SMSG_NEW_WORLD)
Quest POI markers are map-specific. Clearing gossipPois_ on world entry
prevents stale markers from previous maps being displayed on the new map.
Quest POIs will be re-fetched as the quest log re-queries on the new map.
2026-03-11 00:24:35 -07:00