Character re-customization fix
[getmangos.git] / src / game / SkillHandler.cpp
blob2985449245f65825f20816859b4cc03959c65ee0
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "Opcodes.h"
22 #include "Log.h"
23 #include "Player.h"
24 #include "World.h"
25 #include "WorldPacket.h"
26 #include "WorldSession.h"
27 #include "ObjectAccessor.h"
28 #include "UpdateMask.h"
29 #include "SpellAuras.h"
31 void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
33 CHECK_PACKET_SIZE(recv_data,4+4);
35 uint32 talent_id, requested_rank;
36 recv_data >> talent_id >> requested_rank;
38 uint32 CurTalentPoints = GetPlayer()->GetFreeTalentPoints();
40 if(CurTalentPoints == 0)
41 return;
43 if (requested_rank > 4)
44 return;
46 TalentEntry const *talentInfo = sTalentStore.LookupEntry( talent_id );
48 if(!talentInfo)
49 return;
51 TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab );
53 if(!talentTabInfo)
54 return;
56 Player * player = GetPlayer();
58 // prevent learn talent for different class (cheating)
59 if( (player->getClassMask() & talentTabInfo->ClassMask) == 0 )
60 return;
62 // prevent skip talent ranks (cheating)
63 if(requested_rank > 0 && !player->HasSpell(talentInfo->RankID[requested_rank-1]))
64 return;
66 // Check if it requires another talent
67 if (talentInfo->DependsOn > 0)
69 if(TalentEntry const *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn))
71 bool hasEnoughRank = false;
72 for (int i = talentInfo->DependsOnRank; i <= 4; i++)
74 if (depTalentInfo->RankID[i] != 0)
75 if (player->HasSpell(depTalentInfo->RankID[i]))
76 hasEnoughRank = true;
78 if (!hasEnoughRank)
79 return;
83 // Find out how many points we have in this field
84 uint32 spentPoints = 0;
86 uint32 tTab = talentInfo->TalentTab;
87 if (talentInfo->Row > 0)
89 unsigned int numRows = sTalentStore.GetNumRows();
90 for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
92 // Someday, someone needs to revamp
93 const TalentEntry *tmpTalent = sTalentStore.LookupEntry(i);
94 if (tmpTalent) // the way talents are tracked
96 if (tmpTalent->TalentTab == tTab)
98 for (int j = 0; j <= 4; j++)
100 if (tmpTalent->RankID[j] != 0)
102 if (player->HasSpell(tmpTalent->RankID[j]))
104 spentPoints += j + 1;
113 // not have required min points spent in talent tree
114 if(spentPoints < (talentInfo->Row * 5))
115 return;
117 // spell not set in talent.dbc
118 uint32 spellid = talentInfo->RankID[requested_rank];
119 if( spellid == 0 )
121 sLog.outError("Talent.dbc have for talent: %u Rank: %u spell id = 0", talent_id, requested_rank);
122 return;
125 // already known
126 if(GetPlayer( )->HasSpell(spellid))
127 return;
129 // learn! (other talent ranks will unlearned at learning)
130 GetPlayer( )->learnSpell(spellid);
131 sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
133 // update free talent points
134 GetPlayer()->SetFreeTalentPoints(CurTalentPoints - 1);
137 void WorldSession::HandleTalentWipeOpcode( WorldPacket & recv_data )
139 CHECK_PACKET_SIZE(recv_data,8);
141 sLog.outDetail("MSG_TALENT_WIPE_CONFIRM");
142 uint64 guid;
143 recv_data >> guid;
145 Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER);
146 if (!unit)
148 sLog.outDebug( "WORLD: HandleTalentWipeOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
149 return;
152 // remove fake death
153 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
154 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
156 if(!(_player->resetTalents()))
158 WorldPacket data( MSG_TALENT_WIPE_CONFIRM, 8+4); //you have not any talent
159 data << uint64(0);
160 data << uint32(0);
161 SendPacket( &data );
162 return;
165 unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect"
168 void WorldSession::HandleUnlearnSkillOpcode(WorldPacket & recv_data)
170 CHECK_PACKET_SIZE(recv_data,4);
172 uint32 skill_id;
173 recv_data >> skill_id;
174 GetPlayer()->SetSkill(skill_id, 0, 0);