diff options
-rw-r--r-- | src/game/Player.cpp | 215 |
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 } } } |