[2771] Applied MaNGOS coding style (see trunk/bcpp.cfg).
[mangos-git.git] / src / game / SkillHandler.cpp
blob761172b6d40e65af567de124c65a29cf49ecaf66
1 /*
2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
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 "ObjectMgr.h"
28 #include "UpdateMask.h"
29 #include "SpellAuras.h"
31 void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
33 WorldPacket data;
34 uint32 talent_id, requested_rank;
35 recv_data >> talent_id >> requested_rank;
37 uint32 CurTalentPoints = GetPlayer()->GetUInt32Value(PLAYER_CHARACTER_POINTS1);
38 if(CurTalentPoints == 0)
39 return;
41 if (requested_rank > 4)
42 return;
44 TalentEntry *talentInfo = sTalentStore.LookupEntry( talent_id );
46 if(!talentInfo)
47 return;
49 TalentTabEntry *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab );
51 if(!talentTabInfo)
52 return;
54 Player * player = GetPlayer();
56 // prevent learn talent for different class (cheating)
57 if( (player->getClassMask() & talentTabInfo->ClassMask) == 0 )
58 return;
60 // prevent skip talent ranks (cheating)
61 if(requested_rank > 0 && !player->HasSpell(talentInfo->RankID[requested_rank-1]))
62 return;
64 // Check if it requires another talent
65 if (talentInfo->DependsOn > 0)
67 TalentEntry *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn);
68 bool hasEnoughRank = false;
69 for (int i = talentInfo->DependsOnRank; i <= 4; i++)
71 if (depTalentInfo->RankID[i] != 0)
72 if (player->HasSpell(depTalentInfo->RankID[i]))
73 hasEnoughRank = true;
75 if (!hasEnoughRank)
76 return;
79 // Find out how many points we have in this field
80 uint32 spentPoints = 0;
82 uint32 tTab = talentInfo->TalentTab;
83 if (talentInfo->Row > 0)
85 unsigned int numRows = sTalentStore.GetNumRows();
86 for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
88 // Someday, someone needs to revamp
89 TalentEntry *tmpTalent = sTalentStore.data[i];
90 if (tmpTalent) // the way talents are tracked
92 if (tmpTalent->TalentTab == tTab)
94 for (int j = 0; j <= 4; j++)
96 if (tmpTalent->RankID[j] != 0)
98 if (player->HasSpell(tmpTalent->RankID[j]))
100 spentPoints += j + 1;
109 uint32 spellid = talentInfo->RankID[requested_rank];
110 if( spellid == 0 )
112 sLog.outDetail("Talent: %u Rank: %u = 0", talent_id, requested_rank);
114 else
116 if(spentPoints < (talentInfo->Row * 5)) // Min points spent
118 return;
121 if(!(GetPlayer( )->HasSpell(spellid)))
123 if(!GetPlayer( )->addSpell((uint16)spellid,1))
124 return;
126 data.Initialize(SMSG_LEARNED_SPELL);
127 sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
128 data << spellid;
129 GetPlayer( )->GetSession()->SendPacket(&data);
131 SpellEntry *spellInfo = sSpellStore.LookupEntry( spellid );
132 assert(spellInfo); // checked in addSpell
134 // already apply in addSpell function
135 //for(uint32 i = 0;i<3;i++)
137 // uint8 eff = spellInfo->Effect[i];
138 // if (eff>=TOTAL_SPELL_EFFECTS)
139 // continue;
141 // // Duration 21 = permanent
142 // if ((eff == 6) && (spellInfo->DurationIndex == 21) && (spellInfo->rangeIndex == 1))
143 // {
144 // Aura *Aur = new Aura(spellInfo, i, GetPlayer());
145 // GetPlayer()->AddAura(Aur);
146 // }
149 if(requested_rank > 0 )
151 uint32 respellid = talentInfo->RankID[requested_rank-1];
152 GetPlayer( )->removeSpell((uint16)respellid);
153 GetPlayer()->RemoveAurasDueToSpell(respellid);
155 GetPlayer()->SetUInt32Value(PLAYER_CHARACTER_POINTS1, CurTalentPoints - 1);
160 void WorldSession::HandleTalentWipeOpcode( WorldPacket & recv_data )
162 sLog.outString("MSG_TALENT_WIPE_CONFIRM");
163 uint64 guid;
164 recv_data >> guid;
166 Creature *unit = ObjectAccessor::Instance().GetCreature(*_player, guid);
168 if (!unit)
170 sLog.outDebug( "WORLD: HandleTalentWipeOpcode - NO SUCH UNIT! (GUID: %u)", uint32(GUID_LOPART(guid)) );
171 return;
174 if( unit->IsHostileTo(_player)) // do not talk with enemies
175 return;
177 if( !unit->isTrainer()) // it's not trainer
178 return;
180 if(!(_player->resetTalents()))
182 WorldPacket data;
183 data.Initialize( MSG_TALENT_WIPE_CONFIRM ); //you have not any talent
184 SendPacket( &data );
185 return;
188 // send spell 14867
189 WorldPacket data;
190 data.Initialize(SMSG_SPELL_START );
191 data.append(_player->GetPackGUID());
192 data.append(unit->GetPackGUID());
193 data << uint16(14867) << uint16(0x00) << uint16(0x0F) << uint32(0x00)<< uint16(0x00);
194 SendPacket( &data );
196 data.Initialize(SMSG_SPELL_GO);
197 data.append(_player->GetPackGUID());
198 data.append(unit->GetPackGUID());
199 data << uint16(14867) << uint16(0x00) << uint8(0x0D) << uint8(0x01)<< uint8(0x01) << _player->GetGUID();
200 data << uint32(0x00) << uint16(0x0200) << uint16(0x00);
201 SendPacket( &data );
204 void WorldSession::HandleUnlearnSkillOpcode(WorldPacket & recv_data)
206 uint32 skill_id;
207 recv_data >> skill_id;
208 GetPlayer()->SetSkill(skill_id, 0, 0);