aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/DataStores/DBCStructure.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp94
-rw-r--r--src/server/game/Entities/Player/Player.h53
3 files changed, 69 insertions, 80 deletions
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index f3b6355091e..2556c141d8d 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -2139,7 +2139,7 @@ struct SummonPropertiesEntry
uint32 Flags; // 5
};
-#define MAX_PET_TALENT_RANK 3 // use in calculations, expected <= MAX_TALENT_RANK
+#define MAX_TALENT_TIERS 7
struct TalentEntry
{
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 016666e2945..ad870f0262b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -3310,7 +3310,6 @@ void DeleteSpellFromAllPlayers(uint32 spellId)
bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
{
- /* TODO: 6.x update talent system
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
@@ -3342,37 +3341,25 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
return false;
}
- PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(spellId);
- if (itr != GetTalentMap(spec)->end())
- itr->second->state = PLAYERSPELL_UNCHANGED;
- else if (TalentSpellPos const* talentPos = GetTalentSpellPos(spellId))
- {
- if (TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentPos->talent_id))
- {
- for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank)
- {
- // skip learning spell and no rank spell case
- uint32 rankSpellId = talentInfo->RankID[rank];
- if (!rankSpellId || rankSpellId == spellId)
- continue;
+ TalentEntry const* talentEntry = GetTalentBySpellID(spellId);
- itr = GetTalentMap(spec)->find(rankSpellId);
- if (itr != GetTalentMap(spec)->end())
- itr->second->state = PLAYERSPELL_REMOVED;
- }
- }
+ // Check if talent exists in Talent.dbc
+ if (!talentEntry) {
+ TC_LOG_ERROR("spells", "Player::addTalent: Learning non-talent spell %u not allowed.", spellId);
+ return false;
+ }
+
+ TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec);
- PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED;
- PlayerTalent* newtalent = new PlayerTalent();
+ // Check if player already has this talent
+ if (talentSpecInfo->HasTalent(spellId))
+ return false;
- newtalent->state = state;
- newtalent->spec = spec;
+ talentSpecInfo->Talents[talentEntry->TierID].SpellID = spellId;
+ if (learning)
+ talentSpecInfo->Talents[talentEntry->TierID].State = PLAYERSPELL_NEW;
- (*GetTalentMap(spec))[spellId] = newtalent;
- return true;
- }
- */
- return false;
+ return true;
}
bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, bool fromSkill /*= false*/)
@@ -4133,6 +4120,8 @@ bool Player::ResetTalents(bool no_cost)
}
RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
+
+ uint8 spec = GetActiveSpec();
for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
{
@@ -4159,10 +4148,8 @@ bool Player::ResetTalents(bool no_cost)
if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL)
RemoveSpell(_spellEntry->Effects[i].TriggerSpell, true);
- // if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
- PlayerTalentMap::iterator plrTalent = GetTalentMap(GetActiveSpec())->find(talentInfo->SpellID);
- if (plrTalent != GetTalentMap(GetActiveSpec())->end())
- plrTalent->second->state = PLAYERSPELL_REMOVED;
+ // Reset talents store
+ GetTalentSpecInfo(spec)->Reset();
}
// Remove all specialization specific spells and give default ones which were overriden
@@ -4181,12 +4168,12 @@ bool Player::ResetTalents(bool no_cost)
}
// Unlearn masteries
- ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec()));
+ ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(spec));
for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
if (uint32 mastery = chrSpec->MasterySpellID[i])
RemoveAurasDueToSpell(mastery);
- SetTalentSpec(GetActiveSpec(), 0);
+ SetTalentSpec(spec, 0);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
_SaveTalents(trans);
@@ -4278,10 +4265,9 @@ bool Player::HasSpell(uint32 spell) const
!itr->second->disabled);
}
-bool Player::HasTalent(uint32 spell, uint8 spec) const
+bool Player::HasTalent(uint32 spell, uint8 spec)
{
- PlayerTalentMap::const_iterator itr = GetTalentMap(spec)->find(spell);
- return (itr != GetTalentMap(spec)->end() && itr->second->state != PLAYERSPELL_REMOVED);
+ return GetTalentSpecInfo(spec)->HasTalent(spell);
}
bool Player::HasActiveSpell(uint32 spell) const
@@ -26142,38 +26128,36 @@ void Player::_SaveTalents(SQLTransaction& trans)
{
PreparedStatement* stmt = NULL;
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ for (uint8 spec = 0; spec < MAX_TALENT_SPECS; ++spec)
{
- for (PlayerTalentMap::iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end();)
+ TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec);
+
+ for (uint32 tier = 0; tier < MAX_TALENT_TIERS; ++tier)
{
- if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
+ PlayerTalent* talent = &talentSpecInfo->Talents[tier];
+
+ if (talent->State == PLAYERSPELL_REMOVED || talent->State == PLAYERSPELL_CHANGED)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC);
stmt->setUInt64(0, GetGUID().GetCounter());
- stmt->setUInt32(1, itr->first);
- stmt->setUInt8(2, itr->second->spec);
+ stmt->setUInt32(1, talent->SpellID);
+ stmt->setUInt8(2, spec);
trans->Append(stmt);
}
- if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED)
+ if (talent->State == PLAYERSPELL_NEW || talent->State == PLAYERSPELL_CHANGED)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT);
stmt->setUInt64(0, GetGUID().GetCounter());
- stmt->setUInt32(1, itr->first);
- stmt->setUInt8(2, itr->second->spec);
+ stmt->setUInt32(1, talent->SpellID);
+ stmt->setUInt8(2, spec);
trans->Append(stmt);
}
- if (itr->second->state == PLAYERSPELL_REMOVED)
- {
- delete itr->second;
- GetTalentMap(i)->erase(itr++);
- }
- else
- {
- itr->second->state = PLAYERSPELL_UNCHANGED;
- ++itr;
- }
+ if (talent->State == PLAYERSPELL_REMOVED)
+ talent->SpellID = 0;
+
+ talent->State = PLAYERSPELL_UNCHANGED;
}
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index d1a477ac5e1..19105f49add 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -117,8 +117,8 @@ struct PlayerSpell
struct PlayerTalent
{
- PlayerSpellState state : 8;
- uint8 spec : 8;
+ PlayerSpellState State : 8;
+ uint32 SpellID : 32;
};
extern uint32 const MasterySpells[MAX_CLASSES];
@@ -189,7 +189,6 @@ struct PlayerCurrency
uint32 weekCount;
};
-typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap;
typedef std::unordered_map<uint32, PlayerSpell*> PlayerSpellMap;
typedef std::list<SpellModifier*> SpellModList;
typedef std::unordered_map<uint32, PlayerCurrency> PlayerCurrenciesMap;
@@ -1218,35 +1217,42 @@ private:
bool _isPvP;
};
-struct PlayerTalentInfo
+struct TalentSpecInfo
{
- PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveSpec(0), SpecsCount(1)
+ PlayerTalent Talents[MAX_TALENT_TIERS];
+ uint32 Glyphs[MAX_GLYPH_SLOT_INDEX];
+ uint32 TalentSpec;
+
+ bool HasTalent(uint32 spellId)
{
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
- {
- SpecInfo[i].Talents = new PlayerTalentMap();
- memset(SpecInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32));
- SpecInfo[i].TalentSpec = 0;
+ for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i)
+ if (Talents[i].SpellID == spellId)
+ return true;
+ return false;
+ }
+
+ void Reset()
+ {
+ for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) {
+ Talents[i].State = PLAYERSPELL_REMOVED;
+ Talents[i].SpellID = 0;
}
}
+};
- ~PlayerTalentInfo()
+struct PlayerTalentInfo
+{
+ PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveSpec(0), SpecsCount(1)
{
for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
{
- for (PlayerTalentMap::const_iterator itr = SpecInfo[i].Talents->begin(); itr != SpecInfo[i].Talents->end(); ++itr)
- delete itr->second;
- delete SpecInfo[i].Talents;
+ memset(SpecInfo[i].Talents, 0, sizeof(PlayerTalent)*MAX_TALENT_TIERS);
+ memset(SpecInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32));
+ SpecInfo[i].TalentSpec = 0;
}
}
- struct TalentSpecInfo
- {
- PlayerTalentMap* Talents;
- uint32 Glyphs[MAX_GLYPH_SLOT_INDEX];
- uint32 TalentSpec;
- } SpecInfo[MAX_TALENT_SPECS];
-
+ TalentSpecInfo SpecInfo[MAX_TALENT_SPECS];
uint32 ResetTalentsCost;
time_t ResetTalentsTime;
uint8 ActiveSpec;
@@ -1835,7 +1841,7 @@ class Player : public Unit, public GridObject<Player>
void SendTalentsInfoData(bool pet);
bool LearnTalent(uint32 talentId);
bool AddTalent(uint32 spellId, uint8 spec, bool learning);
- bool HasTalent(uint32 spell_id, uint8 spec) const;
+ bool HasTalent(uint32 spell_id, uint8 spec);
// Dual Spec
void UpdateSpecCount(uint8 count);
@@ -1848,8 +1854,7 @@ class Player : public Unit, public GridObject<Player>
void SetGlyph(uint8 slot, uint32 glyph);
uint32 GetGlyph(uint8 spec, uint8 slot) const { return _talentMgr->SpecInfo[spec].Glyphs[slot]; }
- PlayerTalentMap const* GetTalentMap(uint8 spec) const { return _talentMgr->SpecInfo[spec].Talents; }
- PlayerTalentMap* GetTalentMap(uint8 spec) { return _talentMgr->SpecInfo[spec].Talents; }
+ TalentSpecInfo* GetTalentSpecInfo(uint8 spec) { return &_talentMgr->SpecInfo[spec]; }
ActionButtonList const& GetActionButtons() const { return m_actionButtons; }
uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); }