From 03c4d595926cdfea11b02c75512044f9f32905c0 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 10 Mar 2026 07:41:27 -0700 Subject: [PATCH] game: fix talent state not resetting across login sessions Replace static-local firstSpecReceived with talentsInitialized_ member variable, reset in handleLoginVerifyWorld alongside other per-session state. Also clear learnedTalents_, unspentTalentPoints_, and activeTalentSpec_ at world entry so reconnects and character switches start from a clean talent state instead of carrying over stale data. --- include/game/game_handler.hpp | 1 + src/game/game_handler.cpp | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index dc6c06e6..269f018f 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -1841,6 +1841,7 @@ private: std::unordered_map talentCache_; // talentId -> entry std::unordered_map talentTabCache_; // tabId -> entry bool talentDbcLoaded_ = false; + bool talentsInitialized_ = false; // Reset on world entry; guards first-spec selection // ---- Area trigger detection ---- struct AreaTriggerEntry { diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 877afa64..21bc04c0 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -6039,6 +6039,15 @@ void GameHandler::handleLoginVerifyWorld(network::Packet& packet) { encounterUnitGuids_.fill(0); raidTargetGuids_.fill(0); + // Reset talent initialization so the first SMSG_TALENTS_INFO after login + // correctly sets the active spec (static locals don't reset across logins) + talentsInitialized_ = false; + learnedTalents_[0].clear(); + learnedTalents_[1].clear(); + unspentTalentPoints_[0] = 0; + unspentTalentPoints_[1] = 0; + activeTalentSpec_ = 0; + // Suppress area triggers on initial login — prevents exit portals from // immediately firing when spawning inside a dungeon/instance. activeAreaTriggers_.clear(); @@ -13220,10 +13229,9 @@ void GameHandler::handleTalentsInfo(network::Packet& packet) { " unspent=", (int)unspentTalentPoints_[data.talentSpec], " learned=", learnedTalents_[data.talentSpec].size()); - // If this is the first spec received, set it as active - static bool firstSpecReceived = false; - if (!firstSpecReceived) { - firstSpecReceived = true; + // If this is the first spec received after login, set it as the active spec + if (!talentsInitialized_) { + talentsInitialized_ = true; activeTalentSpec_ = data.talentSpec; // Show message to player about active spec