[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;
}
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);

View file

@ -33,6 +33,7 @@ typedef std::list<uint32> 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

View file

@ -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;
}

View file

@ -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)

View file

@ -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;

View file

@ -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)

View file

@ -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();

View file

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