diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 100 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 4 | ||||
-rw-r--r-- | src/server/game/Handlers/SkillHandler.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 61 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.h | 1 |
5 files changed, 51 insertions, 118 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ad3f5185550..50cf8a1e90b 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2711,34 +2711,18 @@ void DeleteSpellFromAllPlayers(uint32 spellId) CharacterDatabase.Execute(stmt); } -bool Player::AddTalent(TalentEntry const* talent, uint16 rank, uint8 talentGroupId, bool learning) +bool Player::AddTalent(TalentEntry const* talent, uint8 rank, uint8 talentGroupId, bool learning) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellRank[rank], DIFFICULTY_NONE); if (!spellInfo) { - // do character spell book cleanup (all characters) - if (!IsInWorld() && !learning) // spell load case - { - TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: {}) does not exist. Deleting for all characters in `character_spell` and `character_talent`.", talent->SpellRank[rank]); - DeleteSpellFromAllPlayers(talent->SpellRank[rank]); - } - else - TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: {}) does not exist", talent->SpellRank[rank]); - + TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: {}) does not exist", talent->SpellRank[rank]); return false; - } + } if (!SpellMgr::IsSpellValid(spellInfo, this, false)) { - // do character spell book cleanup (all characters) - if (!IsInWorld() && !learning) // spell load case - { - TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: {}) is invalid. Deleting for all characters in `character_spell` and `character_talent`.", talent->SpellRank[rank]); - DeleteSpellFromAllPlayers(talent->SpellRank[rank]); - } - else - TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: {}) is invalid", talent->SpellRank[rank]); - + TC_LOG_ERROR("spells", "Player::AddTalent: Spell (ID: {}) is invalid", talent->SpellRank[rank]); return false; } @@ -2746,19 +2730,30 @@ bool Player::AddTalent(TalentEntry const* talent, uint16 rank, uint8 talentGroup auto itr = talentMap.find(talent->ID); if (itr != talentMap.end()) { + // Remove the previously learned talent + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talent->SpellRank[itr->second.Rank], DIFFICULTY_NONE)) + { + RemoveSpell(spellInfo->Id, true); + + // search for spells that the talent teaches and unlearn them + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) + RemoveSpell(spellEffectInfo.TriggerSpell, true); + } + itr->second.State = PLAYERSPELL_UNCHANGED; itr->second.Rank = static_cast<uint8>(rank); } else - talentMap[talent->ID] = { PLAYERSPELL_UNCHANGED, static_cast<uint8>(rank) }; + talentMap[talent->ID] = { PLAYERSPELL_UNCHANGED, rank }; // Inactive talent groups will only be initialized - if (GetActiveTalentGroup() != talentGroupId) - return true; - - LearnSpell(spellInfo->Id, false); - if (talent->OverridesSpellID) - AddOverrideSpell(talent->OverridesSpellID, talent->SpellID); + if (GetActiveTalentGroup() == talentGroupId) + { + LearnSpell(spellInfo->Id, true); + if (talent->OverridesSpellID) + AddOverrideSpell(talent->OverridesSpellID, talent->SpellID); + } if (learning) RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2::ChangeTalent); @@ -2774,19 +2769,15 @@ void Player::RemoveTalent(TalentEntry const* talent) return; uint32 spellId = talent->SpellRank[itr->second.Rank]; - if (!spellId) - return; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE); - if (!spellInfo) - return; - - RemoveSpell(spellId, true); + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE)) + { + RemoveSpell(spellId, true); - // search for spells that the talent teaches and unlearn them - for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) - if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) - RemoveSpell(spellEffectInfo.TriggerSpell, true); + // search for spells that the talent teaches and unlearn them + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) + RemoveSpell(spellEffectInfo.TriggerSpell, true); + } if (talent->OverridesSpellID) RemoveOverrideSpell(talent->OverridesSpellID, talent->SpellID); @@ -26117,7 +26108,7 @@ bool Player::ModifierTreeSatisfied(uint32 modifierTreeId) const static constexpr uint8 NEEDED_TALENT_POINT_PER_TIER = 5; -bool Player::LearnTalent(uint32 talentId, uint16 requestedRank) +bool Player::LearnTalent(uint32 talentId, uint8 requestedRank) { // No talent points left to spend, skip learn request if (!m_activePlayerData->CharacterPoints) @@ -26196,16 +26187,14 @@ bool Player::LearnTalent(uint32 talentId, uint16 requestedRank) return false; } - // already known - if (HasSpell(spellId)) + if (!AddTalent(talentInfo, requestedRank, GetActiveTalentGroup(), true)) return false; - AddTalent(talentInfo, requestedRank, GetActiveTalentGroup(), true); - TC_LOG_DEBUG("misc", "Player::LearnTalent: TalentID: {} Spell: {} Group: {}\n", talentId, spellId, uint32(GetActiveTalentGroup())); // update free talent points SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CharacterPoints), static_cast<int32>(CalculateTalentsPoints() - GetSpentTalentPointsCount())); + SendTalentsInfoData(); return true; } @@ -27029,16 +27018,23 @@ void Player::ActivateTalentGroup(uint8 talentGroup) if (!talentEntry) continue; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentEntry->SpellRank[pair.second.Rank], DIFFICULTY_NONE); - if (!spellInfo) - continue; + for (auto it = talentEntry->SpellRank.rbegin(); it != talentEntry->SpellRank.rend(); ++it) + { + uint32 spellId = *it; + if (!spellId) + continue; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE); + if (!spellInfo) + continue; - RemoveSpell(spellInfo->Id, true); + RemoveSpell(spellInfo->Id, true); - // search for spells that the talent teaches and unlearn them - for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) - if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) - RemoveSpell(spellEffectInfo.TriggerSpell, true); + // search for spells that the talent teaches and unlearn them + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) + RemoveSpell(spellEffectInfo.TriggerSpell, true); + } if (talentEntry->OverridesSpellID) RemoveOverrideSpell(talentEntry->OverridesSpellID, talentEntry->SpellID); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index b3c613fa794..1a42b8011be 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1826,8 +1826,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void InitTalentForLevel(); void SendTalentsInfoData(); uint32 CalculateTalentsPoints() const; - bool LearnTalent(uint32 talentId, uint16 requestedRank); - bool AddTalent(TalentEntry const* talent, uint16 rank, uint8 talentGroupId, bool learning); + bool LearnTalent(uint32 talentId, uint8 requestedRank); + bool AddTalent(TalentEntry const* talent, uint8 rank, uint8 talentGroupId, bool learning); void RemoveTalent(TalentEntry const* talent); void EnablePvpRules(bool dueToCombat = false); diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index 4316db154d8..77471c3b350 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -32,8 +32,7 @@ void WorldSession::HandleLearnTalentsOpcode(WorldPackets::Talent::LearnTalents& void WorldSession::HandleLearnTalentOpcode(WorldPackets::Talent::LearnTalent& packet) { - if (_player->LearnTalent(packet.TalentID, packet.RequestedRank)) - _player->SendTalentsInfoData(); + _player->LearnTalent(packet.TalentID, packet.RequestedRank); } void WorldSession::HandleLearnPvpTalentsOpcode(WorldPackets::Talent::LearnPvpTalents& /*packet*/) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 65b4f0faf1c..0d7f7ddf240 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -809,69 +809,8 @@ void SpellMgr::UnloadSpellInfoChains() mSpellChains.clear(); } -void SpellMgr::LoadSpellTalentRanks() -{ - // cleanup core data before reload - remove reference to ChainNode from SpellInfo - UnloadSpellInfoChains(); - - for (TalentEntry const* talentInfo : sTalentStore) - { - SpellInfo const* lastSpell = nullptr; - for (uint8 rank = talentInfo->SpellRank.size() - 1; rank > 0; --rank) - { - if (talentInfo->SpellRank[rank]) - { - lastSpell = GetSpellInfo(talentInfo->SpellRank[rank], DIFFICULTY_NONE); - break; - } - } - - if (!lastSpell) - continue; - - SpellInfo const* firstSpell = GetSpellInfo(talentInfo->SpellRank[0], DIFFICULTY_NONE); - if (!firstSpell) - { - TC_LOG_ERROR("spells", "SpellMgr::LoadSpellTalentRanks: First Rank Spell {} for TalentEntry {} does not exist.", talentInfo->SpellRank[0], talentInfo->ID); - continue; - } - - SpellInfo const* prevSpell = nullptr; - for (uint8 rank = 0; rank < talentInfo->SpellRank.size(); ++rank) - { - uint32 spellId = talentInfo->SpellRank[rank]; - if (!spellId) - break; - - SpellInfo const* currentSpell = GetSpellInfo(spellId, DIFFICULTY_NONE); - if (!currentSpell) - { - TC_LOG_ERROR("spells", "SpellMgr::LoadSpellTalentRanks: Spell {} (Rank: {}) for TalentEntry {} does not exist.", spellId, rank + 1, talentInfo->ID); - break; - } - - SpellChainNode node; - node.first = firstSpell; - node.last = lastSpell; - node.rank = rank + 1; - - node.prev = prevSpell; - node.next = node.rank < MAX_TALENT_RANK ? GetSpellInfo(talentInfo->SpellRank[node.rank], DIFFICULTY_NONE) : nullptr; - - mSpellChains[spellId] = node; - for (SpellInfo const& difficultyInfo : _GetSpellInfo(spellId)) - const_cast<SpellInfo&>(difficultyInfo).ChainEntry = &mSpellChains[spellId]; - - prevSpell = currentSpell; - } - } -} - void SpellMgr::LoadSpellRanks() { - // cleanup data and load spell ranks for talents from dbc - LoadSpellTalentRanks(); - uint32 oldMSTime = getMSTime(); std::map<uint32 /*spell*/, uint32 /*next*/> chains; diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index cff70dd58d4..b547c154c79 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -768,7 +768,6 @@ class TC_GAME_API SpellMgr // Loading data at server startup void UnloadSpellInfoChains(); - void LoadSpellTalentRanks(); void LoadSpellRanks(); void LoadSpellRequired(); void LoadSpellLearnSkills(); |