aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOvahlord <dreadkiller@gmx.de>2023-11-21 02:04:32 +0100
committerOvahlord <dreadkiller@gmx.de>2023-11-21 02:04:32 +0100
commitca3d9ca0fcef0f217998be0664c5ce986685b8cc (patch)
tree41058dfbe87a417fde57a0545553f0930c897280 /src
parent6b0a3afe6810e524ba3e444aababf13d03ed7022 (diff)
Core/Players: no longer rely on artificially created spell ranks and manually manage talent spell ranks
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp100
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp3
-rw-r--r--src/server/game/Spells/SpellMgr.cpp61
-rw-r--r--src/server/game/Spells/SpellMgr.h1
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();