fix: correct talent rank indexing — store 1-indexed, fix prereq and learn checks

SMSG_TALENTS_INFO wire format sends 0-indexed ranks (0=has rank 1). Both
handlers were storing raw 0-indexed values, but handleSpellLearnedServer
correctly stored rank+1 (1-indexed). This caused:
 - getTalentRank() returning 0 for both "not learned" and "has rank 1",
   making pointsInTree always wrong and blocking tier access
 - Prereq check `prereqRank < DBC_prereqRank` always met when not learned
   (0 < 0 = false), incorrectly unlocking talents
 - Click handler sending wrong desiredRank to server

Fixes:
 - Both SMSG_TALENTS_INFO handlers: store rank+1u (1-indexed)
 - talent_screen.cpp prereq check: change < to <= (DBC is 0-indexed,
   storage is 1-indexed; must use > for "met", <= for "not met")
 - talent_screen.cpp click handler: send currentRank directly (1-indexed
   value equals what CMSG_LEARN_TALENT requestedRank expects)
 - Tooltip: display prereqRank+1 so "Requires 1 point" shows correctly
This commit is contained in:
Kelsi 2026-03-13 03:32:45 -07:00
parent 952f36b732
commit 863faf9b54
2 changed files with 11 additions and 16 deletions

View file

@ -12701,7 +12701,7 @@ void GameHandler::handleInspectResults(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 5) break;
uint32_t talentId = packet.readUInt32();
uint8_t rank = packet.readUInt8();
learnedTalents_[g][talentId] = rank;
learnedTalents_[g][talentId] = rank + 1u; // wire sends 0-indexed; store 1-indexed
}
if (packet.getSize() - packet.getReadPos() < 1) break;
learnedGlyphs_[g].fill(0);
@ -16545,7 +16545,7 @@ void GameHandler::handleTalentsInfo(network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() < 5) break;
uint32_t talentId = packet.readUInt32();
uint8_t rank = packet.readUInt8();
learnedTalents_[g][talentId] = rank;
learnedTalents_[g][talentId] = rank + 1u; // wire sends 0-indexed; store 1-indexed
}
learnedGlyphs_[g].fill(0);
if (packet.getSize() - packet.getReadPos() < 1) break;

View file

@ -303,7 +303,7 @@ void TalentScreen::renderTalentTree(game::GameHandler& gameHandler, uint32_t tab
if (fromIt == talentPositions.end() || toIt == talentPositions.end()) continue;
uint8_t prereqRank = gameHandler.getTalentRank(talent->prereqTalent[i]);
bool met = prereqRank >= talent->prereqRank[i];
bool met = prereqRank > talent->prereqRank[i]; // storage 1-indexed, DBC 0-indexed
ImU32 lineCol = met ? IM_COL32(100, 220, 100, 200) : IM_COL32(120, 120, 120, 150);
ImVec2 from = fromIt->second.center;
@ -374,7 +374,7 @@ void TalentScreen::renderTalent(game::GameHandler& gameHandler,
for (int i = 0; i < 3; ++i) {
if (talent.prereqTalent[i] != 0) {
uint8_t prereqRank = gameHandler.getTalentRank(talent.prereqTalent[i]);
if (prereqRank < talent.prereqRank[i]) {
if (prereqRank <= talent.prereqRank[i]) { // storage 1-indexed, DBC 0-indexed
prereqsMet = false;
canLearn = false;
break;
@ -541,14 +541,15 @@ void TalentScreen::renderTalent(game::GameHandler& gameHandler,
if (!prereq || prereq->rankSpells[0] == 0) continue;
uint8_t prereqCurrentRank = gameHandler.getTalentRank(talent.prereqTalent[i]);
bool met = prereqCurrentRank >= talent.prereqRank[i];
bool met = prereqCurrentRank > talent.prereqRank[i]; // storage 1-indexed, DBC 0-indexed
ImVec4 pColor = met ? ImVec4(0.3f, 0.9f, 0.3f, 1) : ImVec4(1.0f, 0.3f, 0.3f, 1);
const std::string& prereqName = gameHandler.getSpellName(prereq->rankSpells[0]);
ImGui::Spacing();
const uint8_t reqRankDisplay = talent.prereqRank[i] + 1u; // DBC 0-indexed → display 1-indexed
ImGui::TextColored(pColor, "Requires %u point%s in %s",
talent.prereqRank[i],
talent.prereqRank[i] > 1 ? "s" : "",
reqRankDisplay,
reqRankDisplay > 1 ? "s" : "",
prereqName.empty() ? "prerequisite" : prereqName.c_str());
}
@ -573,16 +574,10 @@ void TalentScreen::renderTalent(game::GameHandler& gameHandler,
ImGui::EndTooltip();
}
// Handle click
// Handle click — currentRank is 1-indexed (0=not learned, 1=rank1, ...)
// CMSG_LEARN_TALENT requestedRank must equal current count of learned ranks (same value)
if (clicked && canLearn && prereqsMet) {
const auto& learned = gameHandler.getLearnedTalents();
uint8_t desiredRank;
if (learned.find(talent.talentId) == learned.end()) {
desiredRank = 0; // First rank (0-indexed on wire)
} else {
desiredRank = currentRank; // currentRank is already the next 0-indexed rank to learn
}
gameHandler.learnTalent(talent.talentId, desiredRank);
gameHandler.learnTalent(talent.talentId, currentRank);
}
ImGui::PopID();