/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "StdAfx.h"
void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
{
if(!_player->IsInWorld()) return;
uint32 talent_id, requested_rank;
recv_data >> talent_id >> requested_rank;
uint32 CurTalentPoints = GetPlayer()->GetUInt32Value(PLAYER_CHARACTER_POINTS1);
if(CurTalentPoints == 0)
return;
if (requested_rank > 4)
return;
unsigned int numRows = sTalentStore.GetNumRows();
TalentEntry *talentInfo=NULL ;
for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
{
TalentEntry *t= sTalentStore.LookupEntry( i );
if(t->TalentID==talent_id)
{
talentInfo=t;
break;
}
}
if(!talentInfo)return;
Player * player = GetPlayer();
// Check if it requires another talent
if (talentInfo->DependsOn > 0)
{
TalentEntry *depTalentInfo = NULL;
for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
{
TalentEntry *t= sTalentStore.LookupEntry( i );
if(t->TalentID==talentInfo->DependsOn)
{
depTalentInfo=t;
break;
}
}
bool hasEnoughRank = false;
for (int i = talentInfo->DependsOnRank; i < 5; i++)
{
if (depTalentInfo->RankID[i] != 0)
{
if (player->HasSpell(depTalentInfo->RankID[i]))
{
hasEnoughRank = true;
break;
}
}
}
if (!hasEnoughRank)
return;
}
// Find out how many points we have in this field
uint32 spentPoints = 0;
uint32 tTree = talentInfo->TalentTree;
if (talentInfo->Row > 0)
{
for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
{
// Someday, someone needs to revamp
TalentEntry *tmpTalent = sTalentStore.LookupEntry(i);
if (tmpTalent) // the way talents are tracked
{
if (tmpTalent->TalentTree == tTree)
{
for (int j = 0; j < 5; j++)
{
if (tmpTalent->RankID[j] != 0)
{
if (player->HasSpell(tmpTalent->RankID[j]))
{
spentPoints += j + 1;
// break;
}
}
else
break;
}
}
}
}
}
uint32 spellid = talentInfo->RankID[requested_rank];
if( spellid == 0 )
{
sLog.outDetail("Talent: %u Rank: %u = 0", talent_id, requested_rank);
}
else
{
if(spentPoints < (talentInfo->Row * 5)) // Min points spent
{
return;
}
if(!(GetPlayer( )->HasSpell(spellid)))
{
GetPlayer( )->addSpell(spellid);
SpellEntry *spellInfo = sSpellStore.LookupEntry( spellid );
if(requested_rank > 0 )
{
uint32 respellid = talentInfo->RankID[requested_rank-1];
if(respellid)
{
_player->removeSpell(respellid, false, false, 0);
if(_player->m_SSSPecificSpells.size())
_player->m_SSSPecificSpells.erase(respellid);
}
}
if(spellInfo->Attributes & ATTRIBUTES_PASSIVE || (spellInfo->Effect[0] == SPELL_EFFECT_LEARN_SPELL ||
spellInfo->Effect[1] == SPELL_EFFECT_LEARN_SPELL ||
spellInfo->Effect[2] == SPELL_EFFECT_LEARN_SPELL))
{
Spell*sp=new Spell(_player,spellInfo,true,NULL);
SpellCastTargets tgt;
tgt.m_unitTarget=_player->GetGUID();
sp->prepare(&tgt);
if(spellInfo->RequiredShapeShift && (_player->getClass()==DRUID || _player->getClass()==WARRIOR))
{
if(spellInfo->Attributes & 64)//add for further cast
_player->m_SSSPecificSpells.insert(spellInfo->Id);
}
}
_player->SetUInt32Value(PLAYER_CHARACTER_POINTS1, CurTalentPoints-1);
}
}
}
void WorldSession::HandleUnlearnTalents( WorldPacket & recv_data )
{
if(!_player->IsInWorld()) return;
uint32 playerGold = GetPlayer()->GetUInt32Value( PLAYER_FIELD_COINAGE );
uint32 price = GetPlayer()->CalcTalentResetCost(GetPlayer()->GetTalentResetTimes());
if( playerGold < price ) return;
GetPlayer()->SetTalentResetTimes(GetPlayer()->GetTalentResetTimes() + 1);
GetPlayer()->SetUInt32Value( PLAYER_FIELD_COINAGE, playerGold - price );
GetPlayer()->Reset_Talents();
/* // Unlearn all talent spells
WorldPacket data;
std::list *talentproto = GetPlayer()->getTalentproto();
std::list::iterator itr;
for (itr = talentproto->begin(); itr != talentproto->end(); ++itr)
{
GetPlayer()->removeSpell((*itr));
// Handled in removespell.
//data.Initialize(SMSG_REMOVED_SPELL);
//data << (*itr);
//SendPacket( &data );
}
talentproto->clear();
*/
}
void WorldSession::HandleUnlearnSkillOpcode(WorldPacket& recv_data)
{
if(!_player->IsInWorld()) return;
uint32 skill_line;
uint32 points_remaining=_player->GetUInt32Value(PLAYER_CHARACTER_POINTS2);
recv_data >> skill_line;
// Cheater detection
// if(!_player->HasSkillLine(skill_line)) return;
// Remove any spells within that line that the player has
_player->RemoveSpellsFromLine(skill_line);
// Finally, remove the skill line.
_player->_RemoveSkillLine(skill_line);
//added by Zack : This is probably wrong or already made elsewhere : restore skill learnability
if(points_remaining==_player->GetUInt32Value(PLAYER_CHARACTER_POINTS2))
{
//we unlearned a kill so we enable a new one to be learned
skilllineentry *sk=sSkillLineStore.LookupEntry(skill_line);
if(!sk)
return;
if(sk->type==SKILL_TYPE_PROFESSION && points_remaining<2)
_player->SetUInt32Value(PLAYER_CHARACTER_POINTS2,points_remaining+1);
}
}