Fix talent system packet parsing and rank logic

- Parse SMSG_TALENTS_INFO with correct byte-for-byte structure:
  * Header: uint8 spec, uint8 unspent, be32 talentCount, be16 entryCount
  * Entries: entryCount × (le32 id + uint8 rank)
  * Glyphs: uint8 glyphSlots + glyphSlots × le16 glyphId
- Fix rank storage: store all talents from packet (rank 0 = first point)
- Fix UI rank logic: send rank 0 for new, rank+1 for upgrades
- Fix rank display: show (rank+1) for learned talents
- Add sanity checks: entryCount max 64, glyphSlots max 12
- Add network boundary logging for packet debugging
This commit is contained in:
Kelsi 2026-02-10 13:16:38 -08:00
parent e7556605d7
commit 3c13cf4b12
5 changed files with 141 additions and 31 deletions

View file

@ -4413,6 +4413,20 @@ void GameHandler::handleLearnedSpell(network::Packet& packet) {
uint32_t spellId = packet.readUInt32();
knownSpells.push_back(spellId);
LOG_INFO("Learned spell: ", spellId);
// Check if this spell corresponds to a talent rank
for (const auto& [talentId, talent] : talentCache_) {
for (int rank = 0; rank < 5; ++rank) {
if (talent.rankSpells[rank] == spellId) {
// Found the talent! Update the rank for the active spec
uint8_t newRank = rank + 1; // rank is 0-indexed in array, but stored as 1-indexed
learnedTalents_[activeTalentSpec_][talentId] = newRank;
LOG_INFO("Talent learned: id=", talentId, " rank=", (int)newRank,
" (spell ", spellId, ") in spec ", (int)activeTalentSpec_);
return;
}
}
}
}
void GameHandler::handleRemovedSpell(network::Packet& packet) {
@ -4483,11 +4497,10 @@ void GameHandler::handleTalentsInfo(network::Packet& packet) {
unspentTalentPoints_[data.talentSpec] = data.unspentPoints;
// Clear and rebuild learned talents map for this spec
// Note: If a talent appears in the packet, it's learned (ranks are 0-indexed)
learnedTalents_[data.talentSpec].clear();
for (const auto& talent : data.talents) {
if (talent.currentRank > 0) {
learnedTalents_[data.talentSpec][talent.talentId] = talent.currentRank;
}
learnedTalents_[data.talentSpec][talent.talentId] = talent.currentRank;
}
LOG_INFO("Talents loaded: spec=", (int)data.talentSpec,