aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/Player.cpp215
1 files changed, 113 insertions, 102 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 83aefa50710..8a674149eca 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -2966,7 +2966,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if (!spellInfo)
{
// do character spell book cleanup (all characters)
- if(!IsInWorld() && !learning) // spell load case
+ if (!IsInWorld() && !learning) // spell load case
{
sLog.outError("Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.",spell_id);
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id);
@@ -2977,7 +2977,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
return false;
}
- if(!SpellMgr::IsSpellValid(spellInfo,this,false))
+ if (!SpellMgr::IsSpellValid(spellInfo,this,false))
{
// do character spell book cleanup (all characters)
if(!IsInWorld() && !learning) // spell load case
@@ -3006,11 +3006,11 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
{
uint32 next_active_spell_id = 0;
// fix activate state for non-stackable low rank (and find next spell for !active case)
- if(!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
+ if (!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
{
- if(uint32 next = spellmgr.GetNextSpellInChain(spell_id))
+ if (uint32 next = spellmgr.GetNextSpellInChain(spell_id))
{
- if(HasSpell(next))
+ if (HasSpell(next))
{
// high rank already known so this must !active
active = false;
@@ -3020,10 +3020,10 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
// not do anything if already known in expected state
- if(itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active &&
+ if (itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active &&
itr->second->dependent == dependent && itr->second->disabled == disabled)
{
- if(!IsInWorld() && !learning) // explicitly load from DB and then exist in it already and set correctly
+ if (!IsInWorld() && !learning) // explicitly load from DB and then exist in it already and set correctly
itr->second->state = PLAYERSPELL_UNCHANGED;
return false;
@@ -3039,21 +3039,21 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
// update active state for known spell
- if(itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled)
+ if (itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled)
{
itr->second->active = active;
- if(!IsInWorld() && !learning && !dependent_set) // explicitly load from DB and then exist in it already and set correctly
+ if (!IsInWorld() && !learning && !dependent_set) // explicitly load from DB and then exist in it already and set correctly
itr->second->state = PLAYERSPELL_UNCHANGED;
- else if(itr->second->state != PLAYERSPELL_NEW)
+ else if (itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
- if(active)
+ if (active)
{
if (IsPassiveSpell(spell_id) && IsNeedCastPassiveSpellAtLearn(spellInfo))
- CastSpell (this,spell_id,true);
+ CastSpell(this, spell_id, true);
}
- else if(IsInWorld())
+ else if (IsInWorld())
{
if(next_active_spell_id)
{
@@ -3061,7 +3061,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
data << uint32(spell_id);
data << uint32(next_active_spell_id);
- GetSession()->SendPacket( &data );
+ GetSession()->SendPacket(&data);
}
else
{
@@ -3074,18 +3074,18 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
return active; // learn (show in spell book if active now)
}
- if(itr->second->disabled != disabled && itr->second->state != PLAYERSPELL_REMOVED)
+ if (itr->second->disabled != disabled && itr->second->state != PLAYERSPELL_REMOVED)
{
- if(itr->second->state != PLAYERSPELL_NEW)
+ if (itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
itr->second->disabled = disabled;
- if(disabled)
+ if (disabled)
return false;
disabled_case = true;
}
- else switch(itr->second->state)
+ else switch (itr->second->state)
{
case PLAYERSPELL_UNCHANGED: // known saved spell
return false;
@@ -3099,7 +3099,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
default: // known not saved yet spell (new or modified)
{
// can be in case spell loading but learned at some previous spell loading
- if(!IsInWorld() && !learning && !dependent_set)
+ if (!IsInWorld() && !learning && !dependent_set)
itr->second->state = PLAYERSPELL_UNCHANGED;
return false;
@@ -3107,18 +3107,19 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
}
- if(!disabled_case) // skip new spell adding if spell already known (disabled spells case)
+ // skip new spell adding if spell already known (disabled spells case)
+ if (!disabled_case)
{
// talent: unlearn all other talent ranks (high and low)
- if(TalentSpellPos const *talentPos = GetTalentSpellPos(spell_id))
+ if (TalentSpellPos const *talentPos = GetTalentSpellPos(spell_id))
{
- if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id ))
+ 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 == spell_id)
+ if (!rankSpellId || rankSpellId == spell_id)
continue;
removeSpell(rankSpellId,false,false);
@@ -3126,9 +3127,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
}
// non talent spell: learn low ranks (recursive call)
- else if(uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id))
+ else if (uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id))
{
- if(!IsInWorld() || disabled) // at spells loading, no output, but allow save
+ if (!IsInWorld() || disabled) // at spells loading, no output, but allow save
addSpell(prev_spell,active,true,true,disabled);
else // at normal learning
learnSpell(prev_spell,true);
@@ -3141,21 +3142,23 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
newspell->disabled = disabled;
// replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible
- if(newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
+ if (newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
{
for (PlayerSpellMap::iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2 )
{
- if(itr2->second->state == PLAYERSPELL_REMOVED) continue;
+ if (itr2->second->state == PLAYERSPELL_REMOVED)
+ continue;
SpellEntry const *i_spellInfo = sSpellStore.LookupEntry(itr2->first);
- if(!i_spellInfo) continue;
+ if (!i_spellInfo)
+ continue;
- if( spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first) )
+ if (spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first))
{
- if(itr2->second->active)
+ if (itr2->second->active)
{
- if(spellmgr.IsHighRankOfSpell(spell_id,itr2->first))
+ if (spellmgr.IsHighRankOfSpell(spell_id,itr2->first))
{
- if(IsInWorld()) // not send spell (re-/over-)learn packets at loading
+ if (IsInWorld()) // not send spell (re-/over-)learn packets at loading
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
data << uint32(itr2->first);
@@ -3169,19 +3172,19 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
itr2->second->state = PLAYERSPELL_CHANGED;
superceded_old = true; // new spell replace old in action bars and spell book.
}
- else if(spellmgr.IsHighRankOfSpell(itr2->first,spell_id))
+ else if (spellmgr.IsHighRankOfSpell(itr2->first, spell_id))
{
- if(IsInWorld()) // not send spell (re-/over-)learn packets at loading
+ if (IsInWorld()) // not send spell (re-/over-)learn packets at loading
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
data << uint32(spell_id);
data << uint32(itr2->first);
- GetSession()->SendPacket( &data );
+ GetSession()->SendPacket(&data);
}
// mark new spell as disable (not learned yet for client and will not learned)
newspell->active = false;
- if(newspell->state != PLAYERSPELL_NEW)
+ if (newspell->state != PLAYERSPELL_NEW)
newspell->state = PLAYERSPELL_CHANGED;
}
}
@@ -3223,7 +3226,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
// update free primary prof.points (if any, can be none in case GM .learn prof. learning)
if (uint32 freeProfs = GetFreePrimaryProfessionPoints())
{
- if(spellmgr.IsPrimaryProfessionFirstRankSpell(spell_id))
+ if (spellmgr.IsPrimaryProfessionFirstRankSpell(spell_id))
SetFreePrimaryProfessions(freeProfs-1);
}
@@ -3247,7 +3250,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if (skill_max_value < new_skill_max_value)
skill_max_value = new_skill_max_value;
- SetSkill(spellLearnSkill->skill,skill_value,skill_max_value);
+ SetSkill(spellLearnSkill->skill, skill_value, skill_max_value);
}
else
{
@@ -3265,16 +3268,16 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
// lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
((pSkill->id==SKILL_LOCKPICKING || pSkill->id==SKILL_RUNEFORGING) && _spell_idx->second->max_value==0))
{
- switch(GetSkillRangeType(pSkill,_spell_idx->second->racemask!=0))
+ switch (GetSkillRangeType(pSkill,_spell_idx->second->racemask!=0))
{
case SKILL_RANGE_LANGUAGE:
- SetSkill(pSkill->id, 300, 300 );
+ SetSkill(pSkill->id, 300, 300);
break;
case SKILL_RANGE_LEVEL:
- SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel() );
+ SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel());
break;
case SKILL_RANGE_MONO:
- SetSkill(pSkill->id, 1, 1 );
+ SetSkill(pSkill->id, 1, 1);
break;
default:
break;
@@ -3291,9 +3294,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if (!itr2->second.autoLearned)
{
if (!IsInWorld() || !itr2->second.active) // at spells loading, no output, but allow save
- addSpell(itr2->second.spell,itr2->second.active,true,true,false);
+ addSpell(itr2->second.spell, itr2->second.active, true, true, false);
else // at normal learning
- learnSpell(itr2->second.spell,true);
+ learnSpell(itr2->second.spell, true);
}
}
@@ -3783,17 +3786,12 @@ bool Player::resetTalents(bool no_cost)
if ((getClassMask() & talentTabInfo->ClassMask) == 0)
continue;
- /*
- for (PlayerTalentMap::iterator itr = m_talents[m_activeSpec]->begin(); itr != m_talents[m_activeSpec]->end(); ++itr)
- {
- removeSpell(itr->first, !IsPassiveSpell(itr->first), false);
- itr->second->state = PLAYERSPELL_REMOVED;
- }
- */
-
for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank)
{
- PlayerTalentMap::iterator plrTalent = m_talents[m_activeSpec]->find(talentInfo->RankID[rank]);
+ // skip non-existant talent ranks
+ if (talentInfo->RankID[rank] == 0)
+ continue;
+ // remove all talent related spells from the PlayerSpellMap
for (PlayerSpellMap::iterator itr = GetSpellMap().begin(); itr != GetSpellMap().end(); ++itr)
{
// remove learned spells (all ranks)
@@ -3801,12 +3799,14 @@ bool Player::resetTalents(bool no_cost)
// unlearn if first rank is talent or learned by talent
if (itrFirstId == talentInfo->RankID[rank])
- removeSpell(itr->first, true, false);
+ removeSpell(itr->first, true, false); // disable the talent, delete it at the next _SaveSpells() call
else if (spellmgr.IsSpellLearnToSpell(talentInfo->RankID[rank], itrFirstId))
- removeSpell(itr->first, true, true);
+ removeSpell(itr->first, true, true); // disable the talent, delete it at the next _SaveSpells() call
}
+ // 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->RankID[rank]);
if (plrTalent != m_talents[m_activeSpec]->end())
- plrTalent->second->state = PLAYERSPELL_REMOVED; // mark the talent in the talent map as removed
+ plrTalent->second->state = PLAYERSPELL_REMOVED;
}
}
@@ -3848,7 +3848,7 @@ Mail* Player::GetMail(uint32 id)
void Player::_SetCreateBits(UpdateMask *updateMask, Player *target) const
{
- if(target == this)
+ if (target == this)
Object::_SetCreateBits(updateMask, target);
else
{
@@ -3860,7 +3860,7 @@ void Player::_SetCreateBits(UpdateMask *updateMask, Player *target) const
void Player::_SetUpdateBits(UpdateMask *updateMask, Player *target) const
{
- if(target == this)
+ if (target == this)
Object::_SetUpdateBits(updateMask, target);
else
{
@@ -21984,39 +21984,45 @@ void Player::ActivateSpec(uint8 spec)
//RemoveAllAuras(this->GetGUID(), NULL, false, true); // removes too many auras
//ExitVehicle(); // should be impossible to switch specs from inside a vehicle..
- // find class talent tabs (all players have 3 talent tabs)
- uint32 const *talentTabIds = GetTalentTabPages(getClass());
-
- for (uint8 i = 0; i < 3; ++i)
+ for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
{
- uint32 talentTabId = talentTabIds[i];
+ TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
- for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
- {
- TalentEntry const *talentInfo = sTalentStore.LookupEntry(talentId);
- if (!talentInfo)
- continue;
+ if (!talentInfo)
+ continue;
- // skip another tab talents
- if (talentInfo->TalentTab != talentTabId)
- continue;
+ TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
- for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank)
+ if (!talentTabInfo)
+ continue;
+
+ // unlearn only talents for character class
+ // some spell learned by one class as normal spells or know at creation but another class learn it as talent,
+ // to prevent unexpected lost normal learned spell skip another class talents
+ if ((getClassMask() & talentTabInfo->ClassMask) == 0)
+ continue;
+
+ for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank)
+ {
+ // skip non-existant talent ranks
+ if (talentInfo->RankID[rank] == 0)
+ continue;
+ // remove all talent related spells from the PlayerSpellMap
+ for (PlayerSpellMap::iterator itr = GetSpellMap().begin(); itr != GetSpellMap().end(); ++itr)
{
- //PlayerTalentMap::iterator plrTalent = m_talents[m_activeSpec]->find(talentInfo->RankID[rank]);
- for (PlayerSpellMap::iterator itr = GetSpellMap().begin(); itr != GetSpellMap().end(); ++itr)
- {
- // remove learned spells (all ranks)
- uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first);
-
- // unlearn if first rank is talent or learned by talent
- if (itrFirstId == talentInfo->RankID[rank])
- removeSpell(itr->first, true, false);
- else if (spellmgr.IsSpellLearnToSpell(talentInfo->RankID[rank], itrFirstId))
- removeSpell(itr->first, true, true);
- }
- //plrTalent->second->state = PLAYERSPELL_REMOVED; // mark the talent in the talent map as removed
+ // remove learned spells (all ranks)
+ uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first);
+
+ // unlearn if first rank is talent or learned by talent
+ if (itrFirstId == talentInfo->RankID[rank])
+ removeSpell(itr->first, true, false); // disable the talent, delete it at the next _SaveSpells() call
+ else if (spellmgr.IsSpellLearnToSpell(talentInfo->RankID[rank], itrFirstId))
+ removeSpell(itr->first, true, true); // disable the talent, delete it at the next _SaveSpells() call
}
+ // 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->RankID[rank]);
+ //if (plrTalent != m_talents[m_activeSpec]->end())
+ // plrTalent->second->state = PLAYERSPELL_REMOVED;
}
}
@@ -22030,28 +22036,33 @@ void Player::ActivateSpec(uint8 spec)
SetActiveSpec(spec);
uint32 spentTalents = 0;
- for (uint8 i = 0; i < 3; ++i)
+ for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
{
- uint32 talentTabId = talentTabIds[i];
+ TalentEntry const *talentInfo = sTalentStore.LookupEntry(talentId);
- for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
- {
- TalentEntry const *talentInfo = sTalentStore.LookupEntry(talentId);
- if (!talentInfo)
- continue;
+ if (!talentInfo)
+ continue;
- // skip another tab talents
- if (talentInfo->TalentTab != talentTabId)
- continue;
+ TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
- // learn highest talent rank that exists in newly activated spec
- for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank)
+ if (!talentTabInfo)
+ continue;
+
+ // learn only talents for character class
+ if ((getClassMask() & talentTabInfo->ClassMask) == 0)
+ continue;
+
+ // learn highest talent rank that exists in newly activated spec
+ for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank)
+ {
+ // skip non-existant talent ranks
+ if (talentInfo->RankID[rank] == 0)
+ continue;
+ // if the talent can be found in the newly activated PlayerTalentMap
+ if (HasTalent(talentInfo->RankID[rank], m_activeSpec))
{
- if (talentInfo->RankID[rank] && HasTalent(talentInfo->RankID[rank], m_activeSpec))
- {
- learnSpell(talentInfo->RankID[rank], false);
- spentTalents += (rank + 1);
- }
+ learnSpell(talentInfo->RankID[rank], false); // add the talent to the PlayerSpellMap
+ spentTalents += (rank + 1); // increment the spentTalents count
}
}
}