aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp218
-rw-r--r--src/server/game/Entities/Player/Player.h82
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp2
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp10
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp12
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
6 files changed, 179 insertions, 147 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 3585d38954c..452d1342ba6 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -194,9 +194,6 @@ Player::Player(WorldSession* session): Unit(true)
if (!GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS))
SetAcceptWhispers(true);
- m_usedTalentCount = 0;
- m_questRewardTalentCount = 0;
-
m_regenTimer = 0;
m_regenTimerCount = 0;
m_foodEmoteTimerCount = 0;
@@ -302,8 +299,6 @@ Player::Player(WorldSession* session): Unit(true)
unReadMails = 0;
m_nextMailDelivereTime = 0;
- m_resetTalentsCost = 0;
- m_resetTalentsTime = 0;
m_itemUpdateQueueBlocked = false;
/////////////////// Instance System /////////////////////
@@ -316,16 +311,7 @@ Player::Player(WorldSession* session): Unit(true)
m_lastPotionId = 0;
- m_activeSpec = 0;
- m_specsCount = 1;
-
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
- {
- for (uint8 g = 0; g < MAX_GLYPH_SLOT_INDEX; ++g)
- m_Glyphs[i][g] = 0;
-
- m_talents[i] = new PlayerTalentMap();
- }
+ _talentMgr = new PlayerTalentInfo();
for (uint8 i = 0; i < BASEMOD_END; ++i)
{
@@ -412,12 +398,7 @@ Player::~Player()
for (uint8 i = 0; i < PLAYER_SLOTS_COUNT; ++i)
delete m_items[i];
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
- {
- for (PlayerTalentMap::const_iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end(); ++itr)
- delete itr->second;
- delete m_talents[i];
- }
+ delete _talentMgr;
//all mailed items should be deleted, also all mail should be deallocated
for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr)
@@ -2607,7 +2588,7 @@ void Player::InitTalentForLevel()
if (level < 10)
{
// Remove all talent points
- if (m_usedTalentCount > 0) // Free any used talents
+ if (GetUsedTalentCount() > 0) // Free any used talents
{
ResetTalents(true);
SetFreeTalentPoints(0);
@@ -2615,16 +2596,16 @@ void Player::InitTalentForLevel()
}
else
{
- if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || m_specsCount == 0)
+ if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || GetSpecsCount() == 0)
{
- m_specsCount = 1;
- m_activeSpec = 0;
+ SetSpecsCount(1);
+ SetActiveSpec(0);
}
uint32 talentPointsForLevel = CalculateTalentsPoints();
// if used more that have then reset
- if (m_usedTalentCount > talentPointsForLevel)
+ if (GetUsedTalentCount() > talentPointsForLevel)
{
if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED))
ResetTalents(true);
@@ -2633,7 +2614,7 @@ void Player::InitTalentForLevel()
}
// else update amount of free points
else
- SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount);
+ SetFreeTalentPoints(talentPointsForLevel - GetUsedTalentCount());
}
if (!GetSession()->PlayerLoading())
@@ -3005,8 +2986,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
return false;
}
- PlayerTalentMap::iterator itr = m_talents[spec]->find(spellId);
- if (itr != m_talents[spec]->end())
+ PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(spellId);
+ if (itr != GetTalentMap(spec)->end())
itr->second->state = PLAYERSPELL_UNCHANGED;
else if (TalentSpellPos const* talentPos = GetTalentSpellPos(spellId))
{
@@ -3019,8 +3000,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
if (!rankSpellId || rankSpellId == spellId)
continue;
- itr = m_talents[spec]->find(rankSpellId);
- if (itr != m_talents[spec]->end())
+ itr = GetTalentMap(spec)->find(rankSpellId);
+ if (itr != GetTalentMap(spec)->end())
itr->second->state = PLAYERSPELL_REMOVED;
}
}
@@ -3030,7 +3011,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
newtalent->state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED;
newtalent->spec = spec;
- (*m_talents[spec])[spellId] = newtalent;
+ (*GetTalentMap(spec))[spellId] = newtalent;
return true;
}
return false;
@@ -3323,7 +3304,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
}
// update used talent points count
- m_usedTalentCount += talentCost;
+ SetUsedTalentCount(GetUsedTalentCount() + talentCost);
// update free primary prof.points (if any, can be none in case GM .learn prof. learning)
if (uint32 freeProfs = GetFreePrimaryProfessionPoints())
@@ -3556,10 +3537,10 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
uint32 talentCosts = GetTalentSpellCost(spell_id);
if (talentCosts > 0 && giveTalentPoints)
{
- if (talentCosts < m_usedTalentCount)
- m_usedTalentCount -= talentCosts;
+ if (talentCosts < GetUsedTalentCount())
+ SetUsedTalentCount(GetUsedTalentCount() - talentCosts);
else
- m_usedTalentCount = 0;
+ SetUsedTalentCount(0);
}
// update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning)
@@ -3776,28 +3757,28 @@ uint32 Player::ResetTalentsCost() const
return 0;
// The first time reset costs 1 gold
- if (m_resetTalentsCost < 1*GOLD)
+ if (GetTalentResetCost() < 1*GOLD)
return 1*GOLD;
// then 5 gold
- else if (m_resetTalentsCost < 5*GOLD)
+ else if (GetTalentResetCost() < 5*GOLD)
return 5*GOLD;
// After that it increases in increments of 5 gold
- else if (m_resetTalentsCost < 10*GOLD)
+ else if (GetTalentResetCost() < 10*GOLD)
return 10*GOLD;
else
{
- uint64 months = (GameTime::GetGameTime() - m_resetTalentsTime)/MONTH;
+ uint64 months = (GameTime::GetGameTime() - GetTalentResetTime())/MONTH;
if (months > 0)
{
// This cost will be reduced by a rate of 5 gold per month
- int32 new_cost = int32(m_resetTalentsCost - 5*GOLD*months);
+ int32 new_cost = int32(GetTalentResetCost() - 5*GOLD*months);
// to a minimum of 10 gold.
return (new_cost < 10*GOLD ? 10*GOLD : new_cost);
}
else
{
// After that it increases in increments of 5 gold
- int32 new_cost = m_resetTalentsCost + 5*GOLD;
+ int32 new_cost = GetTalentResetCost() + 5*GOLD;
// until it hits a cap of 50 gold.
if (new_cost > 50*GOLD)
new_cost = 50*GOLD;
@@ -3809,9 +3790,9 @@ uint32 Player::ResetTalentsCost() const
void Player::IncreaseResetTalentsCostAndCounters(uint32 lastResetTalentsCost)
{
if (lastResetTalentsCost > 0) // We don't want to reset the accumulated talent reset cost if we decide to temporarily enable CONFIG_NO_RESET_TALENT_COST
- m_resetTalentsCost = lastResetTalentsCost;
+ _talentMgr->ResetTalentsCost = lastResetTalentsCost;
- m_resetTalentsTime = GameTime::GetGameTime();
+ _talentMgr->ResetTalentsTime = GameTime::GetGameTime();
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, lastResetTalentsCost);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS, 1);
@@ -3827,7 +3808,7 @@ bool Player::ResetTalents(bool involuntarily /*= false*/)
uint32 talentPointsForLevel = CalculateTalentsPoints();
- if (m_usedTalentCount == 0)
+ if (!GetUsedTalentCount())
{
SetFreeTalentPoints(talentPointsForLevel);
return false;
@@ -3867,8 +3848,8 @@ bool Player::ResetTalents(bool involuntarily /*= false*/)
if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0)
RemoveSpell(spellEffectInfo.TriggerSpell, true);
// if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
- PlayerTalentMap::iterator plrTalent = m_talents[m_activeSpec]->find(talentInfo->SpellRank[rank]);
- if (plrTalent != m_talents[m_activeSpec]->end())
+ PlayerTalentMap::iterator plrTalent = GetTalentMap(GetActiveSpec())->find(talentInfo->SpellRank[rank]);
+ if (plrTalent != GetTalentMap(GetActiveSpec())->end())
plrTalent->second->state = PLAYERSPELL_REMOVED;
}
}
@@ -3972,8 +3953,8 @@ bool Player::HasSpell(uint32 spell) const
bool Player::HasTalent(uint32 spell, uint8 spec) const
{
- PlayerTalentMap::const_iterator itr = m_talents[spec]->find(spell);
- return (itr != m_talents[spec]->end() && itr->second->state != PLAYERSPELL_REMOVED);
+ PlayerTalentMap::const_iterator itr = GetTalentMap(spec)->find(spell);
+ return (itr != GetTalentMap(spec)->end() && itr->second->state != PLAYERSPELL_REMOVED);
}
bool Player::HasActiveSpell(uint32 spell) const
@@ -15128,9 +15109,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
SetTitle(titleEntry);
}
- if (quest->GetBonusTalents())
+ if (uint32 talents = quest->GetBonusTalents())
{
- m_questRewardTalentCount += quest->GetBonusTalents();
+ AddQuestRewardedTalentCount(talents);
InitTalentForLevel();
}
@@ -17552,8 +17533,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
m_Played_time[PLAYED_TIME_TOTAL] = fields[24].GetUInt32();
m_Played_time[PLAYED_TIME_LEVEL] = fields[25].GetUInt32();
- m_resetTalentsCost = fields[29].GetUInt32();
- m_resetTalentsTime = time_t(fields[30].GetUInt32());
+ SetTalentResetCost(fields[29].GetUInt32());
+ SetTalentResetTime(time_t(fields[30].GetUInt32()));
if (!m_taxi.LoadTaxiMask(fields[22].GetString())) // must be before InitTaxiNodesForLevel
TC_LOG_WARN("entities.player.loading", "Player::LoadFromDB: Player ({}) has invalid taximask ({}) in DB. Forced partial load.", GetGUID().ToString(), fields[22].GetString());
@@ -17636,15 +17617,15 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
//mails are loaded only when needed ;-) - when player in game click on mailbox.
//_LoadMail();
- m_specsCount = fields[64].GetUInt8();
- m_activeSpec = fields[65].GetUInt8();
+ SetSpecsCount(fields[64].GetUInt8());
+ SetActiveSpec(fields[65].GetUInt8());
// sanity check
- if (m_specsCount > MAX_TALENT_SPECS || m_activeSpec > MAX_TALENT_SPEC || m_specsCount < MIN_TALENT_SPECS)
+ if (GetSpecsCount() > MAX_TALENT_SPECS || GetActiveSpec() > MAX_TALENT_SPEC || GetSpecsCount() < MIN_TALENT_SPECS)
{
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player {} ({}) has invalid SpecCount = {} and/or invalid ActiveSpec = {}.",
- GetName(), GetGUID().ToString(), uint32(m_specsCount), uint32(m_activeSpec));
- m_activeSpec = 0;
+ GetName(), GetGUID().ToString(), uint32(GetSpecsCount()), uint32(GetActiveSpec()));
+ SetActiveSpec(0);
}
UpdateDisplayPower();
@@ -17965,7 +17946,7 @@ void Player::_LoadGlyphAuras()
{
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyph = GetGlyph(i))
+ if (uint32 glyph = GetGlyph(GetActiveSpec(), i))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
@@ -18502,8 +18483,8 @@ void Player::_LoadQuestStatusRewarded(PreparedQueryResult result)
SetTitle(titleEntry);
}
- if (quest->GetBonusTalents())
- m_questRewardTalentCount += quest->GetBonusTalents();
+ if (uint32 talents = quest->GetBonusTalents())
+ AddQuestRewardedTalentCount(talents);
if (quest->CanIncreaseRewardedQuestCounters())
m_RewardedQuests.insert(quest_id);
@@ -19263,8 +19244,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false
stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0));
//save, far from tavern/city
//save, but in tavern/city
- stmt->setUInt32(index++, m_resetTalentsCost);
- stmt->setUInt32(index++, uint32(m_resetTalentsTime));
+ stmt->setUInt32(index++, GetTalentResetCost());
+ stmt->setUInt32(index++, uint32(GetTalentResetTime()));
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
stmt->setUInt8(index++, m_petStable ? m_petStable->MaxStabledPets : 0);
stmt->setUInt16(index++, (uint16)m_atLoginFlags);
@@ -19293,8 +19274,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, m_specsCount);
- stmt->setUInt8(index++, m_activeSpec);
+ stmt->setUInt8(index++, GetSpecsCount());
+ stmt->setUInt8(index++, GetActiveSpec());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -19388,8 +19369,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false
stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0));
//save, far from tavern/city
//save, but in tavern/city
- stmt->setUInt32(index++, m_resetTalentsCost);
- stmt->setUInt32(index++, uint32(m_resetTalentsTime));
+ stmt->setUInt32(index++, GetTalentResetCost());
+ stmt->setUInt32(index++, uint32(GetTalentResetTime()));
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
stmt->setUInt8(index++, m_petStable ? m_petStable->MaxStabledPets : 0);
stmt->setUInt16(index++, (uint16)m_atLoginFlags);
@@ -19418,8 +19399,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, m_specsCount);
- stmt->setUInt8(index++, m_activeSpec);
+ stmt->setUInt8(index++, GetSpecsCount());
+ stmt->setUInt8(index++, GetActiveSpec());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -19527,7 +19508,7 @@ void Player::_SaveActions(CharacterDatabaseTransaction trans)
case ACTIONBUTTON_NEW:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION);
stmt->setUInt32(0, GetGUID().GetCounter());
- stmt->setUInt8(1, m_activeSpec);
+ stmt->setUInt8(1, GetActiveSpec());
stmt->setUInt8(2, itr->first);
stmt->setUInt32(3, itr->second.GetAction());
stmt->setUInt8(4, uint8(itr->second.GetType()));
@@ -19542,7 +19523,7 @@ void Player::_SaveActions(CharacterDatabaseTransaction trans)
stmt->setUInt8(1, uint8(itr->second.GetType()));
stmt->setUInt32(2, GetGUID().GetCounter());
stmt->setUInt8(3, itr->first);
- stmt->setUInt8(4, m_activeSpec);
+ stmt->setUInt8(4, GetActiveSpec());
trans->Append(stmt);
itr->second.uState = ACTIONBUTTON_UNCHANGED;
@@ -19552,7 +19533,7 @@ void Player::_SaveActions(CharacterDatabaseTransaction trans)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC);
stmt->setUInt32(0, GetGUID().GetCounter());
stmt->setUInt8(1, itr->first);
- stmt->setUInt8(2, m_activeSpec);
+ stmt->setUInt8(2, GetActiveSpec());
trans->Append(stmt);
m_actionButtons.erase(itr++);
@@ -24457,7 +24438,7 @@ void Player::InitGlyphsForLevel()
void Player::SetGlyph(uint8 slot, uint32 glyph)
{
- m_Glyphs[m_activeSpec][slot] = glyph;
+ _talentMgr->SpecInfo[GetActiveSpec()].Glyphs[slot] = glyph;
SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph);
}
@@ -24822,16 +24803,16 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
uint32 Player::CalculateTalentsPoints() const
{
- uint32 base_talent = GetLevel() < 10 ? 0 : GetLevel()-9;
+ uint32 baseForLevel = GetLevel() < 10 ? 0 : GetLevel() - 9;
if (GetClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609)
- return uint32(base_talent * sWorld->getRate(RATE_TALENT));
+ return uint32(baseForLevel * sWorld->getRate(RATE_TALENT));
uint32 talentPointsForLevel = GetLevel() < 56 ? 0 : GetLevel() - 55;
- talentPointsForLevel += m_questRewardTalentCount;
+ talentPointsForLevel += GetQuestRewardedTalentCount();
- if (talentPointsForLevel > base_talent)
- talentPointsForLevel = base_talent;
+ if (talentPointsForLevel > baseForLevel)
+ talentPointsForLevel = baseForLevel;
return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT));
}
@@ -25133,29 +25114,29 @@ void Player::CompletedAchievement(AchievementEntry const* entry)
m_achievementMgr->CompletedAchievement(entry);
}
-void Player::LearnTalent(uint32 talentId, uint32 talentRank)
+bool Player::LearnTalent(uint32 talentId, uint32 talentRank)
{
uint32 CurTalentPoints = GetFreeTalentPoints();
if (CurTalentPoints == 0)
- return;
+ return false;
if (talentRank >= MAX_TALENT_RANK)
- return;
+ return false;
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
if (!talentInfo)
- return;
+ return false;
TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TabID);
if (!talentTabInfo)
- return;
+ return false;
// prevent learn talent for different class (cheating)
if ((GetClassMask() & talentTabInfo->ClassMask) == 0)
- return;
+ return false;
// find current max talent rank (0~5)
uint8 curtalent_maxrank = 0; // 0 = not learned any rank
@@ -25170,11 +25151,11 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// we already have same or higher talent rank learned
if (curtalent_maxrank >= (talentRank + 1))
- return;
+ return false;
// check if we have enough talent points
if (CurTalentPoints < (talentRank - curtalent_maxrank + 1))
- return;
+ return false;
// Check if it requires another talent
if (talentInfo->PrereqTalent > 0)
@@ -25189,7 +25170,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
hasEnoughRank = true;
}
if (!hasEnoughRank)
- return;
+ return false;
}
}
@@ -25198,8 +25179,8 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
uint32 tTab = talentInfo->TabID;
if (talentInfo->TierID > 0)
- for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) // Loop through all talents.
- if (TalentEntry const* tmpTalent = sTalentStore.LookupEntry(i)) // the way talents are tracked
+ for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) // Loop through all talents.
+ if (TalentEntry const* tmpTalent = sTalentStore.LookupEntry(i)) // Someday, someone needs to revamp the way talents are tracked
if (tmpTalent->TabID == tTab)
for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++)
if (tmpTalent->SpellRank[rank] != 0)
@@ -25208,28 +25189,29 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// not have required min points spent in talent tree
if (spentPoints < (talentInfo->TierID * MAX_TALENT_RANK))
- return;
+ return false;
// spell not set in talent.dbc
uint32 spellid = talentInfo->SpellRank[talentRank];
if (spellid == 0)
{
TC_LOG_ERROR("entities.player", "Player::LearnTalent: Talent.dbc has no spellInfo for talent: {} (spell id = 0)", talentId);
- return;
+ return false;
}
// already known
if (HasSpell(spellid))
- return;
+ return false;
// learn! (other talent ranks will unlearned at learning)
LearnSpell(spellid, false);
- AddTalent(spellid, m_activeSpec, true);
+ AddTalent(spellid, GetActiveSpec(), true);
- TC_LOG_DEBUG("misc", "Player::LearnTalent: TalentID: {} Spell: {} Group: {}\n", talentId, spellid, uint32(m_activeSpec));
+ TC_LOG_DEBUG("misc", "Player::LearnTalent: TalentID: {} Spell: {} Group: {}\n", talentId, spellid, uint32(GetActiveSpec()));
// update free talent points
SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1));
+ return true;
}
void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank)
@@ -25442,16 +25424,16 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const
void Player::BuildPlayerTalentsInfoData(WorldPacket* data)
{
*data << uint32(GetFreeTalentPoints()); // unspentTalentPoints
- *data << uint8(m_specsCount); // talent group count (0, 1 or 2)
- *data << uint8(m_activeSpec); // talent group index (0 or 1)
+ *data << uint8(GetSpecsCount()); // talent group count (0, 1 or 2)
+ *data << uint8(GetActiveSpec()); // talent group index (0 or 1)
- if (m_specsCount)
+ if (GetSpecsCount())
{
- if (m_specsCount > MAX_TALENT_SPECS)
- m_specsCount = MAX_TALENT_SPECS;
+ if (GetSpecsCount() > MAX_TALENT_SPECS)
+ SetSpecsCount(MAX_TALENT_SPECS);
// loop through all specs (only 1 for now)
- for (uint32 specIdx = 0; specIdx < m_specsCount; ++specIdx)
+ for (uint32 specIdx = 0; specIdx < GetSpecsCount(); ++specIdx)
{
uint8 talentIdCount = 0;
size_t pos = data->wpos();
@@ -25501,7 +25483,7 @@ void Player::BuildPlayerTalentsInfoData(WorldPacket* data)
*data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- *data << uint16(m_Glyphs[specIdx][i]); // GlyphProperties.dbc
+ *data << uint16(GetGlyph(specIdx, i)); // GlyphProperties.dbc
}
}
}
@@ -25827,15 +25809,11 @@ void Player::_LoadGlyphs(PreparedQueryResult result)
Field* fields = result->Fetch();
uint8 spec = fields[0].GetUInt8();
- if (spec >= m_specsCount)
+ if (spec >= GetSpecsCount())
continue;
- m_Glyphs[spec][0] = fields[1].GetUInt16();
- m_Glyphs[spec][1] = fields[2].GetUInt16();
- m_Glyphs[spec][2] = fields[3].GetUInt16();
- m_Glyphs[spec][3] = fields[4].GetUInt16();
- m_Glyphs[spec][4] = fields[5].GetUInt16();
- m_Glyphs[spec][5] = fields[6].GetUInt16();
+ for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
+ _talentMgr->SpecInfo[spec].Glyphs[i] = fields[i + 1].GetUInt16();
}
while (result->NextRow());
}
@@ -25846,7 +25824,7 @@ void Player::_SaveGlyphs(CharacterDatabaseTransaction trans) const
stmt->setUInt32(0, GetGUID().GetCounter());
trans->Append(stmt);
- for (uint8 spec = 0; spec < m_specsCount; ++spec)
+ for (uint8 spec = 0; spec < GetSpecsCount(); ++spec)
{
uint8 index = 0;
@@ -25856,7 +25834,7 @@ void Player::_SaveGlyphs(CharacterDatabaseTransaction trans) const
stmt->setUInt8(index++, spec);
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- stmt->setUInt16(index++, uint16(m_Glyphs[spec][i]));
+ stmt->setUInt16(index++, uint16(GetGlyph(spec, i)));
trans->Append(stmt);
}
@@ -25879,7 +25857,7 @@ void Player::_SaveTalents(CharacterDatabaseTransaction trans)
for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
{
- for (PlayerTalentMap::iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end();)
+ for (PlayerTalentMap::iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end();)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
{
@@ -25902,7 +25880,7 @@ void Player::_SaveTalents(CharacterDatabaseTransaction trans)
if (itr->second->state == PLAYERSPELL_REMOVED)
{
delete itr->second;
- m_talents[i]->erase(itr++);
+ GetTalentMap(i)->erase(itr++);
}
else
{
@@ -25919,7 +25897,7 @@ void Player::UpdateSpecCount(uint8 count)
if (curCount == count)
return;
- if (m_activeSpec >= count)
+ if (GetActiveSpec() >= count)
ActivateSpec(0);
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
@@ -25946,11 +25924,11 @@ void Player::UpdateSpecCount(uint8 count)
_SaveActions(trans);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC);
- stmt->setUInt8(0, m_activeSpec);
+ stmt->setUInt8(0, GetActiveSpec());
stmt->setUInt32(1, GetGUID().GetCounter());
trans->Append(stmt);
- m_activeSpec = 0;
+ SetActiveSpec(0);
}
CharacterDatabase.CommitTransaction(trans);
@@ -26045,7 +26023,7 @@ void Player::ActivateSpec(uint8 spec)
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
// remove secondary glyph
- if (uint32 oldglyph = m_Glyphs[m_activeSpec][slot])
+ if (uint32 oldglyph = GetGlyph(GetActiveSpec(), slot))
if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
RemoveAurasDueToSpell(old_gp->SpellID);
@@ -26075,7 +26053,7 @@ void Player::ActivateSpec(uint8 spec)
if (talentInfo->SpellRank[rank] == 0)
continue;
// if the talent can be found in the newly activated PlayerTalentMap
- if (HasTalent(talentInfo->SpellRank[rank], m_activeSpec))
+ if (HasTalent(talentInfo->SpellRank[rank], GetActiveSpec()))
{
LearnSpell(talentInfo->SpellRank[rank], false); // add the talent to the PlayerSpellMap
spentTalents += (rank + 1); // increment the spentTalents count
@@ -26086,7 +26064,7 @@ void Player::ActivateSpec(uint8 spec)
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
{
- uint32 glyph = m_Glyphs[m_activeSpec][slot];
+ uint32 glyph = GetGlyph(GetActiveSpec(), slot);
// apply primary glyph
if (glyph)
@@ -26096,14 +26074,14 @@ void Player::ActivateSpec(uint8 spec)
SetGlyph(slot, glyph);
}
- m_usedTalentCount = spentTalents;
+ SetUsedTalentCount(spentTalents);
InitTalentForLevel();
// load them asynchronously
{
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC);
stmt->setUInt32(0, GetGUID().GetCounter());
- stmt->setUInt8(1, m_activeSpec);
+ stmt->setUInt8(1, GetActiveSpec());
WorldSession* mySess = GetSession();
mySess->GetQueryProcessor().AddCallback(CharacterDatabase.AsyncQuery(stmt)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 80125b66595..f8646c2f95e 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -877,6 +877,47 @@ struct ResurrectionData
#define SPELL_DK_RAISE_ALLY 46619
+struct PlayerTalentInfo
+{
+ PlayerTalentInfo() :
+ UsedTalentCount(0), QuestRewardedTalentCount(0),
+ ResetTalentsCost(0), ResetTalentsTime(0),
+ ActiveSpec(0), SpecsCount(1)
+ {
+ 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));
+ }
+ }
+
+ ~PlayerTalentInfo()
+ {
+ 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;
+ }
+ }
+
+ struct TalentSpecInfo
+ {
+ PlayerTalentMap* Talents;
+ uint32 Glyphs[MAX_GLYPH_SLOT_INDEX];
+ } SpecInfo[MAX_TALENT_SPECS];
+
+ uint32 UsedTalentCount;
+ uint32 QuestRewardedTalentCount;
+ uint32 ResetTalentsCost;
+ time_t ResetTalentsTime;
+ uint8 ActiveSpec;
+ uint8 SpecsCount;
+
+private:
+ PlayerTalentInfo(PlayerTalentInfo const&);
+};
+
class TC_GAME_API Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
@@ -1439,8 +1480,23 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SetReputation(uint32 factionentry, uint32 value);
uint32 GetReputation(uint32 factionentry) const;
std::string const& GetGuildName() const;
+
+ // Talents
uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); }
void SetFreeTalentPoints(uint32 points);
+ uint32 GetUsedTalentCount() const { return _talentMgr->UsedTalentCount; }
+ void SetUsedTalentCount(uint32 talents) { _talentMgr->UsedTalentCount = talents; }
+ uint32 GetQuestRewardedTalentCount() const { return _talentMgr->QuestRewardedTalentCount; }
+ void AddQuestRewardedTalentCount(uint32 points) { _talentMgr->QuestRewardedTalentCount += points; }
+ uint32 GetTalentResetCost() const { return _talentMgr->ResetTalentsCost; }
+ void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; }
+ time_t GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; }
+ void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; }
+ uint8 GetActiveSpec() const { return _talentMgr->ActiveSpec; }
+ void SetActiveSpec(uint8 spec){ _talentMgr->ActiveSpec = spec; }
+ uint8 GetSpecsCount() const { return _talentMgr->SpecsCount; }
+ void SetSpecsCount(uint8 count) { _talentMgr->SpecsCount = count; }
+
bool ResetTalents(bool involuntarily = false);
uint32 ResetTalentsCost() const;
void IncreaseResetTalentsCostAndCounters(uint32 lastResetTalentsCost);
@@ -1448,29 +1504,27 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void BuildPlayerTalentsInfoData(WorldPacket* data);
void BuildPetTalentsInfoData(WorldPacket* data);
void SendTalentsInfoData(bool pet);
- void LearnTalent(uint32 talentId, uint32 talentRank);
+ bool LearnTalent(uint32 talentId, uint32 talentRank);
void LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank);
void SendTameFailure(uint8 result);
-
bool AddTalent(uint32 spellId, uint8 spec, bool learning);
bool HasTalent(uint32 spell_id, uint8 spec) const;
-
uint32 CalculateTalentsPoints() const;
// Dual Spec
void UpdateSpecCount(uint8 count);
- uint32 GetActiveSpec() const { return m_activeSpec; }
- void SetActiveSpec(uint8 spec){ m_activeSpec = spec; }
- uint8 GetSpecsCount() const { return m_specsCount; }
- void SetSpecsCount(uint8 count) { m_specsCount = count; }
void ActivateSpec(uint8 spec);
void LoadActions(PreparedQueryResult result);
void InitGlyphsForLevel();
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
- uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
+ uint32 GetGlyphSlot(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
void SetGlyph(uint8 slot, uint32 glyph);
- uint32 GetGlyph(uint8 slot) { return m_Glyphs[m_activeSpec][slot]; }
+ 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; }
+ ActionButtonList const& GetActionButtons() const { return m_actionButtons; }
uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); }
void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2, profs); }
@@ -2334,13 +2388,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
PlayerMails m_mail;
PlayerSpellMap m_spells;
- PlayerTalentMap* m_talents[MAX_TALENT_SPECS];
uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use
- uint8 m_activeSpec;
- uint8 m_specsCount;
-
- uint32 m_Glyphs[MAX_TALENT_SPECS][MAX_GLYPH_SLOT_INDEX];
+ PlayerTalentInfo* _talentMgr;
ActionButtonList m_actionButtons;
@@ -2403,10 +2453,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
float m_rest_bonus;
uint32 _restFlagMask;
////////////////////Rest System/////////////////////
- uint32 m_resetTalentsCost;
- time_t m_resetTalentsTime;
- uint32 m_usedTalentCount;
- uint32 m_questRewardTalentCount;
// Social
PlayerSocial* m_social;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 472f1556551..3431df6ef56 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1339,7 +1339,7 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData)
return;
}
- if (uint32 glyph = _player->GetGlyph(slot))
+ if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index a75220e7b2c..8911b36fdc0 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -30,8 +30,8 @@ void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData)
uint32 talentId, requestedRank;
recvData >> talentId >> requestedRank;
- _player->LearnTalent(talentId, requestedRank);
- _player->SendTalentsInfoData(false);
+ if (_player->LearnTalent(talentId, requestedRank))
+ _player->SendTalentsInfoData(false);
}
void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
@@ -50,7 +50,11 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
{
recvPacket >> talentId >> talentRank;
- _player->LearnTalent(talentId, talentRank);
+ if (!_player->LearnTalent(talentId, talentRank))
+ {
+ recvPacket.rfinish();
+ break;
+ }
}
_player->SendTalentsInfoData(false);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 98e89e73fff..1346f8682ae 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1168,7 +1168,9 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (target->GetTypeId() == TYPEID_PLAYER)
{
- PlayerSpellMap const& sp_list = target->ToPlayer()->GetSpellMap();
+ Player* plrTarget = target->ToPlayer();
+
+ PlayerSpellMap const& sp_list = plrTarget->GetSpellMap();
for (auto itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if (itr->second.state == PLAYERSPELL_REMOVED || itr->second.disabled)
@@ -1188,7 +1190,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
// Also do it for Glyphs
for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyphId = target->ToPlayer()->GetGlyph(i))
+ if (uint32 glyphId = plrTarget->GetGlyph(plrTarget->GetActiveSpec(), i))
{
if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId))
{
@@ -1203,19 +1205,21 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
}
// Leader of the Pack
- if (target->ToPlayer()->HasSpell(17007))
+ if (plrTarget->HasSpell(17007))
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(24932);
if (spellInfo && spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1)))
target->CastSpell(target, 24932, this);
}
+
// Improved Barkskin - apply/remove armor bonus due to shapeshift
- if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411))
+ if (plrTarget->HasSpell(63410) || plrTarget->HasSpell(63411))
{
target->RemoveAurasDueToSpell(66530);
if (GetMiscValue() == FORM_TRAVEL || GetMiscValue() == FORM_NONE) // "while in Travel Form or while not shapeshifted"
target->CastSpell(target, 66530, true);
}
+
// Heart of the Wild
if (HotWSpellId)
{ // hacky, but the only way as spell family is not SPELLFAMILY_DRUID
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index be1fefa8a51..423883689d7 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3805,7 +3805,7 @@ void Spell::EffectApplyGlyph()
}
// remove old glyph
- if (uint32 oldglyph = player->GetGlyph(m_glyphIndex))
+ if (uint32 oldglyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex))
{
if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
{