From 01ff6db748e45af971c662576adc78e9f95eab29 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Mon, 9 Feb 2026 22:13:31 -0800 Subject: [PATCH] Fix trainer prerequisite checking Issue: Trainer buttons were all greyed out because alreadyKnown was incorrectly calculated using (state == 0 || isKnown(spellId)), which marked spells with state=0 as 'already known' even when they weren't in the knownSpells list. This caused prerequisite checks to fail since they only check knownSpells. Fix: Changed alreadyKnown to only check isKnown(spellId), removing the state==0 check. Now prerequisites work correctly. Added extensive debug logging to track: - Known spells count and spell IDs - Individual prerequisite checks (chain1, chain2, chain3) - Whether spells are in initial SMSG_INITIAL_SPELLS packet Note: Some trainers may still show greyed buttons due to server-side data issues where prerequisite spells are marked as unavailable (state=0) even though they haven't been learned yet. This is correct client behavior. --- src/game/game_handler.cpp | 5 +++++ src/ui/game_screen.cpp | 36 +++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index e439c30e..d12f12b3 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -3985,6 +3985,11 @@ void GameHandler::handleInitialSpells(network::Packet& packet) { knownSpells = data.spellIds; + // Debug: check if specific spells are in initial spells + bool has527 = std::find(knownSpells.begin(), knownSpells.end(), 527u) != knownSpells.end(); + bool has988 = std::find(knownSpells.begin(), knownSpells.end(), 988u) != knownSpells.end(); + LOG_INFO("Initial spells include: 527=", has527, " 988=", has988); + // Ensure Attack (6603) and Hearthstone (8690) are always present if (std::find(knownSpells.begin(), knownSpells.end(), 6603u) == knownSpells.end()) { knownSpells.insert(knownSpells.begin(), 6603u); diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index 97245b36..50ae4b7f 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -3596,7 +3596,13 @@ void GameScreen::renderTrainerWindow(game::GameHandler& gameHandler) { const auto& knownSpells = gameHandler.getKnownSpells(); auto isKnown = [&](uint32_t id) { if (id == 0) return true; - return std::find(knownSpells.begin(), knownSpells.end(), id) != knownSpells.end(); + bool found = std::find(knownSpells.begin(), knownSpells.end(), id) != knownSpells.end(); + static int debugCount = 0; + if (debugCount < 5 && !found && id != 0) { + LOG_INFO("isKnown(", id, ") = false, knownSpells.size()=", knownSpells.size()); + debugCount++; + } + return found; }; uint32_t playerLevel = gameHandler.getPlayerLevel(); @@ -3607,11 +3613,12 @@ void GameScreen::renderTrainerWindow(game::GameHandler& gameHandler) { ImGui::PushID(static_cast(spell->spellId)); // Check prerequisites client-side - bool prereqsMet = isKnown(spell->chainNode1) - && isKnown(spell->chainNode2) - && isKnown(spell->chainNode3); + bool prereq1Met = isKnown(spell->chainNode1); + bool prereq2Met = isKnown(spell->chainNode2); + bool prereq3Met = isKnown(spell->chainNode3); + bool prereqsMet = prereq1Met && prereq2Met && prereq3Met; bool levelMet = (spell->reqLevel == 0 || playerLevel >= spell->reqLevel); - bool alreadyKnown = (spell->state == 0) || isKnown(spell->spellId); + bool alreadyKnown = isKnown(spell->spellId); ImVec4 color; const char* statusLabel; @@ -3690,16 +3697,23 @@ void GameScreen::renderTrainerWindow(game::GameHandler& gameHandler) { && prereqsMet && levelMet && (money >= spell->spellCost); - // Debug logging for first spell to see why buttons are disabled - static bool logged = false; - if (!logged) { + // Debug logging for first 3 spells to see why buttons are disabled + static int logCount = 0; + static uint64_t lastTrainerGuid = 0; + if (trainer.trainerGuid != lastTrainerGuid) { + logCount = 0; + lastTrainerGuid = trainer.trainerGuid; + } + if (logCount < 3) { LOG_INFO("Trainer button debug: spellId=", spell->spellId, " alreadyKnown=", alreadyKnown, " state=", (int)spell->state, - " prereqsMet=", prereqsMet, " levelMet=", levelMet, + " prereqsMet=", prereqsMet, " (", prereq1Met, ",", prereq2Met, ",", prereq3Met, ")", + " levelMet=", levelMet, + " reqLevel=", spell->reqLevel, " playerLevel=", playerLevel, + " chain1=", spell->chainNode1, " chain2=", spell->chainNode2, " chain3=", spell->chainNode3, " canAfford=", (money >= spell->spellCost), - " money=", money, " cost=", spell->spellCost, " canTrain=", canTrain); - logged = true; + logCount++; } if (!canTrain) ImGui::BeginDisabled();