[9653] Correctly update talent free points in diff cases.

Before at .unlearn or .learn all_mytalents commands free talent points not updated correctly.
Same for .learn all_mypettalents.
This commit is contained in:
VladimirMangos 2010-04-02 02:44:27 +04:00
parent d004549fd4
commit daaeb0a998
8 changed files with 86 additions and 49 deletions

View file

@ -665,14 +665,19 @@ TalentSpellPos const* GetTalentSpellPos(uint32 spellId)
return &itr->second; 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 pos->rank+1;
return 0; return 0;
} }
uint32 GetTalentSpellCost(uint32 spellId)
{
return GetTalentSpellCost(GetTalentSpellPos(spellId));
}
int32 GetAreaFlagByAreaID(uint32 area_id) int32 GetAreaFlagByAreaID(uint32 area_id)
{ {
AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id); AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id);

View file

@ -33,6 +33,7 @@ typedef std::list<uint32> SimpleFactionsList;
SimpleFactionsList const* GetFactionTeamList(uint32 faction); SimpleFactionsList const* GetFactionTeamList(uint32 faction);
char* GetPetName(uint32 petfamily, uint32 dbclang); char* GetPetName(uint32 petfamily, uint32 dbclang);
uint32 GetTalentSpellCost(uint32 spellId); uint32 GetTalentSpellCost(uint32 spellId);
uint32 GetTalentSpellCost(TalentSpellPos const* pos);
TalentSpellPos const* GetTalentSpellPos(uint32 spellId); TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found

View file

@ -1953,6 +1953,8 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/)
player->learnSpellHighRank(spellid); player->learnSpellHighRank(spellid);
} }
player->SendTalentsInfoData(false);
SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS);
return true; return true;
} }
@ -2029,6 +2031,8 @@ bool ChatHandler::HandleLearnAllMyPetTalentsCommand(const char* /*args*/)
pet->learnSpellHighRank(spellid); pet->learnSpellHighRank(spellid);
} }
player->SendTalentsInfoData(true);
SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS);
return true; return true;
} }

View file

@ -1380,11 +1380,8 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel
uint32 talentCost = GetTalentSpellCost(spell_id); uint32 talentCost = GetTalentSpellCost(spell_id);
if (talentCost) if (talentCost)
{ {
int32 free_points = GetMaxTalentPointsForLevel(getLevel());
m_usedTalentCount+=talentCost; m_usedTalentCount+=talentCost;
// update free talent points UpdateFreeTalentPoints(false);
free_points-=m_usedTalentCount;
SetFreeTalentPoints(free_points > 0 ? free_points : 0);
} }
return true; return true;
} }
@ -1493,9 +1490,8 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
m_usedTalentCount-=talentCost; m_usedTalentCount-=talentCost;
else else
m_usedTalentCount = 0; m_usedTalentCount = 0;
// update free talent points
int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount; UpdateFreeTalentPoints(false);
SetFreeTalentPoints(free_points > 0 ? free_points : 0);
} }
if (learn_prev) if (learn_prev)
@ -1720,17 +1716,33 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* online_pet /*= NULL*/)
CharacterDatabase.Execute(ss.str().c_str()); CharacterDatabase.Execute(ss.str().c_str());
} }
void Pet::InitTalentForLevel() void Pet::UpdateFreeTalentPoints(bool resetIfNeed)
{ {
uint32 level = getLevel(); uint32 level = getLevel();
uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level);
// Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent) // 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 // 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); resetTalents(true);
else
SetFreeTalentPoints(0);
} }
else
SetFreeTalentPoints(0);
}
else
SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount);
}
void Pet::InitTalentForLevel()
{
UpdateFreeTalentPoints();
Unit *owner = GetOwner(); Unit *owner = GetOwner();
if (!owner || owner->GetTypeId() != TYPEID_PLAYER) if (!owner || owner->GetTypeId() != TYPEID_PLAYER)

View file

@ -230,6 +230,7 @@ class Pet : public Creature
uint8 GetMaxTalentPointsForLevel(uint32 level); uint8 GetMaxTalentPointsForLevel(uint32 level);
uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); } void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); }
void UpdateFreeTalentPoints(bool resetIfNeed = true);
uint32 m_resetTalentsCost; uint32 m_resetTalentsCost;
time_t m_resetTalentsTime; time_t m_resetTalentsTime;

View file

@ -2518,15 +2518,16 @@ void Player::GiveLevel(uint32 level)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL);
} }
void Player::InitTalentForLevel() void Player::UpdateFreeTalentPoints(bool resetIfNeed)
{ {
uint32 level = getLevel(); uint32 level = getLevel();
// talents base at level diff ( talents = level - 9 but some can be used already) // talents base at level diff ( talents = level - 9 but some can be used already)
if(level < 10) if (level < 10)
{ {
// Remove all talent points // Remove all talent points
if(m_usedTalentCount > 0) // Free any used talents if (m_usedTalentCount > 0) // Free any used talents
{ {
if (resetIfNeed)
resetTalents(true); resetTalents(true);
SetFreeTalentPoints(0); SetFreeTalentPoints(0);
} }
@ -2536,9 +2537,9 @@ void Player::InitTalentForLevel()
uint32 talentPointsForLevel = CalculateTalentsPoints(); uint32 talentPointsForLevel = CalculateTalentsPoints();
// if used more that have then reset // 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); resetTalents(true);
else else
SetFreeTalentPoints(0); SetFreeTalentPoints(0);
@ -2547,8 +2548,13 @@ void Player::InitTalentForLevel()
else else
SetFreeTalentPoints(talentPointsForLevel-m_usedTalentCount); SetFreeTalentPoints(talentPointsForLevel-m_usedTalentCount);
} }
}
if(!GetSession()->PlayerLoading()) void Player::InitTalentForLevel()
{
UpdateFreeTalentPoints();
if (!GetSession()->PlayerLoading())
SendTalentsInfoData(false); // update at client 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) if(!disabled_case) // skip new spell adding if spell already known (disabled spells case)
{ {
// talent: unlearn all other talent ranks (high and low) // 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 )) 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; 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) // 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 // 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) // ignore stance requirement for talent learn spell (stance set for spell only for client spell description show)
CastSpell(this, spell_id, true); CastSpell(this, spell_id, true);
@ -3106,16 +3126,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
return false; 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 // add dependent skills
uint16 maxskill = GetMaxSkillValueForLevel(); 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))) if(PetAura const* petSpell = sSpellMgr.GetPetAura(spell_id, SpellEffectIndex(i)))
RemovePetAura(petSpell); RemovePetAura(petSpell);
// free talent points TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id);
uint32 talentCosts = GetTalentSpellCost(spell_id); if (talentPos)
if(talentCosts > 0)
{ {
// free talent points
uint32 talentCosts = GetTalentSpellCost(talentPos);
if(talentCosts < m_usedTalentCount) if(talentCosts < m_usedTalentCount)
m_usedTalentCount -= talentCosts; m_usedTalentCount -= talentCosts;
else else
m_usedTalentCount = 0; m_usedTalentCount = 0;
UpdateFreeTalentPoints(false);
} }
// update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning) // 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); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
// if talent then lesser rank also talent and need learn // if talent then lesser rank also talent and need learn
if (talentCosts) if (talentPos)
{ {
if(learn_low_rank) if(learn_low_rank)
learnSpell (prev_id,false); learnSpell (prev_id,false);
@ -3626,20 +3640,20 @@ bool Player::resetTalents(bool no_cost)
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab );
if(!talentTabInfo) if (!talentTabInfo)
continue; continue;
// unlearn only talents for character class // 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, // 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 // to prevent unexpected lost normal learned spell skip another class talents
if( (getClassMask() & talentTabInfo->ClassMask) == 0 ) if ((getClassMask() & talentTabInfo->ClassMask) == 0)
continue; continue;
for (int j = 0; j < MAX_TALENT_RANK; ++j) for (int j = 0; j < MAX_TALENT_RANK; ++j)
{ {
for(PlayerSpellMap::iterator itr = GetSpellMap().begin(); itr != GetSpellMap().end();) 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; ++itr;
continue; continue;
@ -5632,10 +5646,10 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const
void Player::SendInitialActionButtons() 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)); 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]; ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec];
for(uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) for(uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button)
{ {
@ -5647,7 +5661,7 @@ void Player::SendInitialActionButtons() const
} }
GetSession()->SendPacket( &data ); 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) 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(); 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() ); while( result->NextRow() );
@ -20892,9 +20908,6 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// learn! (other talent ranks will unlearned at learning) // learn! (other talent ranks will unlearned at learning)
learnSpell(spellid, false); learnSpell(spellid, false);
sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talentId, talentRank, spellid); 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) void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank)

View file

@ -1544,6 +1544,7 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); } uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); }
void SetFreeTalentPoints(uint32 points) { SetUInt32Value(PLAYER_CHARACTER_POINTS1,points); } void SetFreeTalentPoints(uint32 points) { SetUInt32Value(PLAYER_CHARACTER_POINTS1,points); }
void UpdateFreeTalentPoints(bool resetIfNeed = true);
bool resetTalents(bool no_cost = false); bool resetTalents(bool no_cost = false);
uint32 resetTalentsCost() const; uint32 resetTalentsCost() const;
void InitTalentForLevel(); void InitTalentForLevel();

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9652" #define REVISION_NR "9653"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__