diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index 51feb835f..a94b411bf 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -665,14 +665,19 @@ TalentSpellPos const* GetTalentSpellPos(uint32 spellId) return &itr->second; } -uint32 GetTalentSpellCost(uint32 spellId) +uint32 GetTalentSpellCost(TalentSpellPos const* pos) { - if(TalentSpellPos const* pos = GetTalentSpellPos(spellId)) + if (pos) return pos->rank+1; return 0; } +uint32 GetTalentSpellCost(uint32 spellId) +{ + return GetTalentSpellCost(GetTalentSpellPos(spellId)); +} + int32 GetAreaFlagByAreaID(uint32 area_id) { AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id); diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h index e9cf95674..5acc2b806 100644 --- a/src/game/DBCStores.h +++ b/src/game/DBCStores.h @@ -33,6 +33,7 @@ typedef std::list SimpleFactionsList; SimpleFactionsList const* GetFactionTeamList(uint32 faction); char* GetPetName(uint32 petfamily, uint32 dbclang); uint32 GetTalentSpellCost(uint32 spellId); +uint32 GetTalentSpellCost(TalentSpellPos const* pos); TalentSpellPos const* GetTalentSpellPos(uint32 spellId); int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 520251d7a..23291aece 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1953,6 +1953,8 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) player->learnSpellHighRank(spellid); } + player->SendTalentsInfoData(false); + SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); return true; } @@ -2029,6 +2031,8 @@ bool ChatHandler::HandleLearnAllMyPetTalentsCommand(const char* /*args*/) pet->learnSpellHighRank(spellid); } + player->SendTalentsInfoData(true); + SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); return true; } diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index dc88b571f..e2a7918ac 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1380,11 +1380,8 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel uint32 talentCost = GetTalentSpellCost(spell_id); if (talentCost) { - int32 free_points = GetMaxTalentPointsForLevel(getLevel()); m_usedTalentCount+=talentCost; - // update free talent points - free_points-=m_usedTalentCount; - SetFreeTalentPoints(free_points > 0 ? free_points : 0); + UpdateFreeTalentPoints(false); } return true; } @@ -1493,9 +1490,8 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab) m_usedTalentCount-=talentCost; else m_usedTalentCount = 0; - // update free talent points - int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount; - SetFreeTalentPoints(free_points > 0 ? free_points : 0); + + UpdateFreeTalentPoints(false); } if (learn_prev) @@ -1720,17 +1716,33 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* online_pet /*= NULL*/) CharacterDatabase.Execute(ss.str().c_str()); } -void Pet::InitTalentForLevel() +void Pet::UpdateFreeTalentPoints(bool resetIfNeed) { uint32 level = getLevel(); uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); // Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent) - if(talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel) + if (talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel) { - // Remove all talent points - resetTalents(true); + // Remove all talent points (except for admin pets) + if (resetIfNeed) + { + Unit *owner = GetOwner(); + if (!owner || owner->GetTypeId() != TYPEID_PLAYER || ((Player*)owner)->GetSession()->GetSecurity() < SEC_ADMINISTRATOR) + resetTalents(true); + else + SetFreeTalentPoints(0); + } + else + SetFreeTalentPoints(0); } - SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); + else + SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); +} + + +void Pet::InitTalentForLevel() +{ + UpdateFreeTalentPoints(); Unit *owner = GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) diff --git a/src/game/Pet.h b/src/game/Pet.h index fdad92cef..efc9ecdf3 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -230,6 +230,7 @@ class Pet : public Creature uint8 GetMaxTalentPointsForLevel(uint32 level); uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); } + void UpdateFreeTalentPoints(bool resetIfNeed = true); uint32 m_resetTalentsCost; time_t m_resetTalentsTime; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a5ccb3033..a39906a44 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2518,16 +2518,17 @@ void Player::GiveLevel(uint32 level) GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); } -void Player::InitTalentForLevel() +void Player::UpdateFreeTalentPoints(bool resetIfNeed) { uint32 level = getLevel(); // talents base at level diff ( talents = level - 9 but some can be used already) - if(level < 10) + if (level < 10) { // Remove all talent points - if(m_usedTalentCount > 0) // Free any used talents + if (m_usedTalentCount > 0) // Free any used talents { - resetTalents(true); + if (resetIfNeed) + resetTalents(true); SetFreeTalentPoints(0); } } @@ -2536,9 +2537,9 @@ void Player::InitTalentForLevel() uint32 talentPointsForLevel = CalculateTalentsPoints(); // if used more that have then reset - if(m_usedTalentCount > talentPointsForLevel) + if (m_usedTalentCount > talentPointsForLevel) { - if (GetSession()->GetSecurity() < SEC_ADMINISTRATOR) + if (resetIfNeed && GetSession()->GetSecurity() < SEC_ADMINISTRATOR) resetTalents(true); else SetFreeTalentPoints(0); @@ -2547,8 +2548,13 @@ void Player::InitTalentForLevel() else SetFreeTalentPoints(talentPointsForLevel-m_usedTalentCount); } +} - if(!GetSession()->PlayerLoading()) +void Player::InitTalentForLevel() +{ + UpdateFreeTalentPoints(); + + if (!GetSession()->PlayerLoading()) SendTalentsInfoData(false); // update at client } @@ -2996,10 +3002,12 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen } } + TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id); + if(!disabled_case) // skip new spell adding if spell already known (disabled spells case) { // talent: unlearn all other talent ranks (high and low) - if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id)) + if (talentPos) { if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id )) { @@ -3085,11 +3093,23 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen return false; } - uint32 talentCost = GetTalentSpellCost(spell_id); + if (talentPos) + { + // update used talent points count + m_usedTalentCount += GetTalentSpellCost(talentPos); + UpdateFreeTalentPoints(false); + } + + // update free primary prof.points (if any, can be none in case GM .learn prof. learning) + if (uint32 freeProfs = GetFreePrimaryProfessionPoints()) + { + if(sSpellMgr.IsPrimaryProfessionFirstRankSpell(spell_id)) + SetFreePrimaryProfessions(freeProfs-1); + } // cast talents with SPELL_EFFECT_LEARN_SPELL (other dependent spells will learned later as not auto-learned) // note: all spells with SPELL_EFFECT_LEARN_SPELL isn't passive - if (talentCost > 0 && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_LEARN_SPELL)) + if (talentPos && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_LEARN_SPELL)) { // ignore stance requirement for talent learn spell (stance set for spell only for client spell description show) CastSpell(this, spell_id, true); @@ -3106,16 +3126,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen return false; } - // update used talent points count - m_usedTalentCount += talentCost; - - // update free primary prof.points (if any, can be none in case GM .learn prof. learning) - if (uint32 freeProfs = GetFreePrimaryProfessionPoints()) - { - if(sSpellMgr.IsPrimaryProfessionFirstRankSpell(spell_id)) - SetFreePrimaryProfessions(freeProfs-1); - } - // add dependent skills uint16 maxskill = GetMaxSkillValueForLevel(); @@ -3286,14 +3296,18 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank, bo if(PetAura const* petSpell = sSpellMgr.GetPetAura(spell_id, SpellEffectIndex(i))) RemovePetAura(petSpell); - // free talent points - uint32 talentCosts = GetTalentSpellCost(spell_id); - if(talentCosts > 0) + TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id); + if (talentPos) { + // free talent points + uint32 talentCosts = GetTalentSpellCost(talentPos); + if(talentCosts < m_usedTalentCount) m_usedTalentCount -= talentCosts; else m_usedTalentCount = 0; + + UpdateFreeTalentPoints(false); } // update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning) @@ -3381,7 +3395,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank, bo SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); // if talent then lesser rank also talent and need learn - if (talentCosts) + if (talentPos) { if(learn_low_rank) learnSpell (prev_id,false); @@ -3626,20 +3640,20 @@ bool Player::resetTalents(bool no_cost) TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); - if(!talentTabInfo) + 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 ) + if ((getClassMask() & talentTabInfo->ClassMask) == 0) continue; for (int j = 0; j < MAX_TALENT_RANK; ++j) { for(PlayerSpellMap::iterator itr = GetSpellMap().begin(); itr != GetSpellMap().end();) { - if(itr->second.state == PLAYERSPELL_REMOVED || itr->second.disabled) + if (itr->second.state == PLAYERSPELL_REMOVED || itr->second.disabled) { ++itr; continue; @@ -5632,10 +5646,10 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const void Player::SendInitialActionButtons() const { - sLog.outDetail( "Initializing Action Buttons for '%u'", GetGUIDLow() ); + sLog.outDetail( "Initializing Action Buttons for '%u' spec '%u'", GetGUIDLow(), m_activeSpec); WorldPacket data(SMSG_ACTION_BUTTONS, 1+(MAX_ACTION_BUTTONS*4)); - data << uint8(1); // can be 0, 1, 2 (talent spec) + data << uint8(m_activeSpec); // can be 0, 1, 2 (talent spec) ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec]; for(uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) { @@ -5647,7 +5661,7 @@ void Player::SendInitialActionButtons() const } GetSession()->SendPacket( &data ); - sLog.outDetail( "Action Buttons for '%u' Initialized", GetGUIDLow() ); + sLog.outDetail( "Action Buttons for '%u' spec '%u' Initialized", GetGUIDLow(), m_activeSpec ); } bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type, Player* player, bool msg) @@ -15874,7 +15888,9 @@ void Player::_LoadSpells(QueryResult *result) { Field *fields = result->Fetch(); - addSpell(fields[0].GetUInt32(), fields[1].GetBool(), false, false, fields[2].GetBool()); + uint32 spell_id = fields[0].GetUInt32(); + + addSpell(spell_id, fields[1].GetBool(), false, false, fields[2].GetBool()); } while( result->NextRow() ); @@ -20892,9 +20908,6 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) // learn! (other talent ranks will unlearned at learning) learnSpell(spellid, false); sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talentId, talentRank, spellid); - - // update free talent points - SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1)); } void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank) diff --git a/src/game/Player.h b/src/game/Player.h index b9c62ca43..18c93ac23 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1544,6 +1544,7 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); } void SetFreeTalentPoints(uint32 points) { SetUInt32Value(PLAYER_CHARACTER_POINTS1,points); } + void UpdateFreeTalentPoints(bool resetIfNeed = true); bool resetTalents(bool no_cost = false); uint32 resetTalentsCost() const; void InitTalentForLevel(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5fdf5ba98..c66795c22 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9652" + #define REVISION_NR "9653" #endif // __REVISION_NR_H__