[2612] Applied MaNGOS coding style (see trunk/bcpp.cfg).
[mangos-git.git] / src / game / SpellEffects.cpp
blob23e324190a02dd24558c90f8a2c0901b110cdddb
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 "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "Opcodes.h"
24 #include "Log.h"
25 #include "UpdateMask.h"
26 #include "World.h"
27 #include "ObjectMgr.h"
28 #include "Player.h"
29 #include "Unit.h"
30 #include "CreatureAI.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "RedZoneDistrict.h"
39 #include "CellImpl.h"
40 #include "SharedDefines.h"
41 #include "Pet.h"
42 #include "GameObject.h"
43 #include "GossipDef.h"
44 #include "Creature.h"
45 #include "Totem.h"
46 #include "CreatureAI.h"
48 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
50 &Spell::EffectNULL, //nothing
51 &Spell::EffectInstaKill, //SPELL_EFFECT_INSTAKILL = 1
52 &Spell::EffectSchoolDMG, //SPELL_EFFECT_SCHOOL_DAMAGE = 2
53 &Spell::EffectDummy, //SPELL_EFFECT_DUMMY = 3
54 &Spell::EffectNULL, //SPELL_EFFECT_PORTAL_TELEPORT = 4
55 &Spell::EffectTeleportUnits, //SPELL_EFFECT_TELEPORT_UNITS = 5
56 &Spell::EffectApplyAura, //SPELL_EFFECT_APPLY_AURA = 6
57 &Spell::EffectSchoolDMG, //SPELL_EFFECT_ENVIRONMENTAL_DAMAGE =7
58 &Spell::EffectManaDrain, //SPELL_EFFECT_MANA_DRAIN = 8
59 &Spell::EffectHealthLeach, //SPELL_EFFECT_HEALTH_LEECH = 9
60 &Spell::EffectHeal, //SPELL_EFFECT_HEAL = 10
61 &Spell::EffectNULL, //SPELL_EFFECT_BIND = 11
62 &Spell::EffectNULL, //SPELL_EFFECT_PORTAL = 12
63 &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_BASE = 13
64 &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_SPECIALIZE = 14
65 &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15
66 &Spell::EffectQuestComplete, //SPELL_EFFECT_QUEST_COMPLETE = 16
67 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17
68 &Spell::EffectResurrect, //SPELL_EFFECT_RESURRECT = 18
69 &Spell::EffectNULL, //SPELL_EFFECT_ADD_EXTRA_ATTACKS = 19
70 &Spell::EffectNULL, //SPELL_EFFECT_DODGE = 20
71 &Spell::EffectNULL, //SPELL_EFFECT_EVADE = 21
72 &Spell::EffectParry, //SPELL_EFFECT_PARRY = 22
73 &Spell::EffectNULL, //SPELL_EFFECT_BLOCK = 23
74 &Spell::EffectCreateItem, //SPELL_EFFECT_CREATE_ITEM = 24
75 &Spell::EffectNULL, //SPELL_EFFECT_WEAPON = 25
76 &Spell::EffectNULL, //SPELL_EFFECT_DEFENSE = 26
77 &Spell::EffectPersistentAA, //SPELL_EFFECT_PERSISTENT_AREA_AURA = 27
78 &Spell::EffectSummon, //SPELL_EFFECT_SUMMON = 28
79 &Spell::EffectMomentMove, //SPELL_EFFECT_LEAP = 29
80 &Spell::EffectEnergize, //SPELL_EFFECT_ENERGIZE = 30
81 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_PERCENT_DAMAGE = 31
82 &Spell::EffectNULL, //SPELL_EFFECT_TRIGGER_MISSILE = 32 //Useless
83 &Spell::EffectOpenLock, //SPELL_EFFECT_OPEN_LOCK = 33
84 &Spell::EffectSummonChangeItem, //SPELL_EFFECT_SUMMON_CHANGE_ITEM = 34
85 &Spell::EffectApplyAA, //SPELL_EFFECT_APPLY_AREA_AURA = 35
86 &Spell::EffectLearnSpell, //SPELL_EFFECT_LEARN_SPELL = 36
87 &Spell::EffectNULL, //SPELL_EFFECT_SPELL_DEFENSE = 37 //Useless
88 &Spell::EffectDispel, //SPELL_EFFECT_DISPEL = 38
89 &Spell::EffectNULL, //SPELL_EFFECT_LANGUAGE = 39
90 &Spell::EffectDualWield, //SPELL_EFFECT_DUAL_WIELD = 40
91 &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_WILD = 41
92 &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_GUARDIAN = 42
93 &Spell::EffectTeleUnitsFaceCaster, //SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER = 43
94 &Spell::EffectLearnSkill, //SPELL_EFFECT_SKILL_STEP = 44
95 &Spell::EffectNULL, //unknown45 = 45
96 &Spell::EffectNULL, //SPELL_EFFECT_SPAWN = 46
97 &Spell::EffectTradeSkill, //SPELL_EFFECT_TRADE_SKILL = 47
98 &Spell::EffectNULL, //SPELL_EFFECT_STEALTH = 48 //Useless
99 &Spell::EffectNULL, //SPELL_EFFECT_DETECT = 49
100 &Spell::EffectTransmitted, //SPELL_EFFECT_TRANS_DOOR = 50
101 &Spell::EffectNULL, //SPELL_EFFECT_FORCE_CRITICAL_HIT = 51 //Useless
102 &Spell::EffectNULL, //SPELL_EFFECT_GUARANTEE_HIT = 52
103 &Spell::EffectEnchantItemPerm, //SPELL_EFFECT_ENCHANT_ITEM = 53
104 &Spell::EffectEnchantItemTmp, //SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54
105 &Spell::EffectTameCreature, //SPELL_EFFECT_TAMECREATURE = 55
106 &Spell::EffectSummonPet, //SPELL_EFFECT_SUMMON_PET = 56
107 &Spell::EffectLearnPetSpell, //SPELL_EFFECT_LEARN_PET_SPELL = 57
108 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_DAMAGE = 58
109 &Spell::EffectOpenSecretSafe, //SPELL_EFFECT_OPEN_LOCK_ITEM = 59
110 &Spell::EffectProficiency, //SPELL_EFFECT_PROFICIENCY = 60
111 &Spell::EffectSendEvent, //SPELL_EFFECT_SEND_EVENT = 61
112 &Spell::EffectPowerDrain, //SPELL_EFFECT_POWER_BURN = 62
113 &Spell::EffectThreat, //SPELL_EFFECT_THREAT = 63
114 &Spell::EffectTriggerSpell, //SPELL_EFFECT_TRIGGER_SPELL = 64
115 &Spell::EffectNULL, //SPELL_EFFECT_HEALTH_FUNNEL = 65 //Useless
116 &Spell::EffectNULL, //SPELL_EFFECT_POWER_FUNNEL = 66 //Useless
117 &Spell::EffectHealMaxHealth, //SPELL_EFFECT_HEAL_MAX_HEALTH = 67
118 &Spell::EffectInterruptCast, //SPELL_EFFECT_INTERRUPT_CAST = 68
119 &Spell::EffectNULL, //SPELL_EFFECT_DISTRACT = 69
120 &Spell::EffectNULL, //SPELL_EFFECT_PULL = 70
121 &Spell::EffectPickPocket, //SPELL_EFFECT_PICKPOCKET = 71
122 &Spell::EffectNULL, //SPELL_EFFECT_ADD_FARSIGHT = 72
123 &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_POSSESSED = 73
124 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_TOTEM = 74 //Useless
125 &Spell::EffectNULL, //SPELL_EFFECT_HEAL_MECHANICAL = 75
126 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_OBJECT_WILD = 76
127 &Spell::EffectScriptEffect, //SPELL_EFFECT_SCRIPT_EFFECT = 77
128 &Spell::EffectNULL, //SPELL_EFFECT_ATTACK = 78 //Useless
129 &Spell::EffectNULL, //SPELL_EFFECT_SANCTUARY = 79
130 &Spell::EffectAddComboPoints, //SPELL_EFFECT_ADD_COMBO_POINTS = 80
131 &Spell::EffectNULL, //SPELL_EFFECT_CREATE_HOUSE = 81
132 &Spell::EffectNULL, //SPELL_EFFECT_BIND_SIGHT = 82
133 &Spell::EffectDuel, //SPELL_EFFECT_DUEL = 83
134 &Spell::EffectNULL, //SPELL_EFFECT_STUCK = 84
135 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_PLAYER = 85
136 &Spell::EffectNULL, //SPELL_EFFECT_ACTIVATE_OBJECT = 86
137 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87
138 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88
139 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89
140 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90
141 &Spell::EffectNULL, //SPELL_EFFECT_THREAT_ALL = 91
142 &Spell::EffectEnchantHeldItem, //SPELL_EFFECT_ENCHANT_HELD_ITEM = 92
143 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_PHANTASM = 93
144 &Spell::EffectSelfResurrect, //SPELL_EFFECT_SELF_RESURRECT = 94
145 &Spell::EffectSkinning, //SPELL_EFFECT_SKINNING = 95
146 &Spell::EffectCharge, //SPELL_EFFECT_CHARGE = 96
147 &Spell::EffectSummonCritter, //SPELL_EFFECT_SUMMON_CRITTER = 97
148 &Spell::EffectNULL, //SPELL_EFFECT_KNOCK_BACK = 98
149 &Spell::EffectDisEnchant, //SPELL_EFFECT_DISENCHANT = 99
150 &Spell::EffectInebriate, //SPELL_EFFECT_INEBRIATE = 100
151 &Spell::EffectFeedPet, //SPELL_EFFECT_FEED_PET = 101
152 &Spell::EffectDismissPet, //SPELL_EFFECT_DISMISS_PET = 102
153 &Spell::EffectReputation, //SPELL_EFFECT_REPUTATION = 103
154 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104
155 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105
156 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106
157 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107
158 &Spell::EffectNULL, //SPELL_EFFECT_DISPEL_MECHANIC = 108
159 &Spell::EffectSummonDeadPet, //SPELL_EFFECT_SUMMON_DEAD_PET = 109
160 &Spell::EffectNULL, //SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110
161 &Spell::EffectNULL, //SPELL_EFFECT_DURABILITY_DAMAGE = 111
162 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_DEMON = 112
163 &Spell::EffectResurrectNew, //SPELL_EFFECT_RESURRECT_NEW = 113
164 &Spell::EffectAttackMe, //SPELL_EFFECT_ATTACK_ME = 114
165 &Spell::EffectNULL, //SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115
166 &Spell::EffectNULL, //SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116
167 &Spell::EffectNULL, //SPELL_EFFECT_SPIRIT_HEAL = 117
168 &Spell::EffectSkill, //SPELL_EFFECT_SKILL = 118 -- professions and more
169 &Spell::EffectNULL, //SPELL_EFFECT_APPLY_AURA_NEW = 119
170 &Spell::EffectNULL, //SPELL_EFFECT_TELEPORT_GRAVEYARD = 120
171 &Spell::EffectWeaponDmg //SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121
174 void Spell::EffectNULL(uint32 i)
176 sLog.outDebug("WORLD: Spell Effect DUMMY");
179 void Spell::EffectResurrectNew(uint32 i)
181 if(!unitTarget) return;
182 if(unitTarget->GetTypeId() != TYPEID_PLAYER) return;
183 if(unitTarget->isAlive()) return;
184 if(!unitTarget->IsInWorld()) return;
186 uint32 health = m_spellInfo->EffectBasePoints[i]+1;
187 uint32 mana = m_spellInfo->EffectMiscValue[i];
188 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
189 SendResurrectRequest((Player*)unitTarget);
192 void Spell::EffectInstaKill(uint32 i)
194 if( unitTarget && unitTarget->isAlive() )
196 uint32 health = unitTarget->GetHealth();
197 m_caster->DealDamage(unitTarget, health, 0, false);
201 void Spell::EffectSchoolDMG(uint32 i)
203 if( unitTarget && unitTarget->isAlive() )
204 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage);
207 void Spell::EffectDummy(uint32 i)
209 if(!unitTarget)
210 return;
212 // More spell specific code in begining
214 // Preparation Rogue - immediately finishes the cooldown on other Rogue abilities
215 if(m_spellInfo->Id == 14185)
217 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
218 return;
220 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
221 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
223 uint32 classspell = itr->first;
224 SpellEntry *spellInfo = sSpellStore.LookupEntry(classspell);
226 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->Id != 14185 &&
227 (spellInfo->RecoveryTime > 0 || spellInfo->CategoryRecoveryTime > 0))
229 WorldPacket data;
230 data.Initialize(SMSG_CLEAR_COOLDOWN);
231 data << classspell << m_caster->GetGUID();
232 data << uint32(0);
233 ((Player*)m_caster)->GetSession()->SendPacket(&data);
236 return;
239 // Cold Snap - immediately finishes the cooldown on Frost spells
240 if(m_spellInfo->Id == 12472)
242 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
243 return;
245 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
246 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
248 uint32 classspell = itr->first;
249 SpellEntry *spellInfo = sSpellStore.LookupEntry(classspell);
251 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && spellInfo->School == SPELL_SCHOOL_FROST && spellInfo->Id != 12472 &&
252 (spellInfo->RecoveryTime > 0 || spellInfo->CategoryRecoveryTime > 0))
254 WorldPacket data;
255 data.Initialize(SMSG_CLEAR_COOLDOWN);
256 data << classspell << m_caster->GetGUID();
257 data << uint32(0);
258 ((Player*)m_caster)->GetSession()->SendPacket(&data);
261 return;
264 // If spell cannibalize and his casted, check special requirements and cast aura Cannibalize is all ok
265 if(m_spellInfo->Id == 20577)
267 // non-standard cast requirement check
268 SpellRangeEntry* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
269 float max_range = GetMaxRange(srange);
270 bool found=false;
271 FactionTemplateResolver myFaction = m_caster->getFactionTemplateEntry();
272 std::list<Unit*> UnitList;
273 MapManager::Instance().GetMap(m_caster->GetMapId())->GetUnitList(m_caster->GetPositionX(), m_caster->GetPositionY(),UnitList);
274 for(std::list<Unit*>::iterator iter=UnitList.begin();iter!=UnitList.end();iter++)
276 FactionTemplateResolver its_faction = (*iter)->getFactionTemplateEntry();
277 if(myFaction.IsFriendlyTo(its_faction) || (*iter)->isAlive() || (*iter)->isInFlight() ||
278 (((Creature*)(*iter))->GetCreatureInfo()->type != CREATURE_TYPE_HUMANOID && ((Creature*)(*iter))->GetCreatureInfo()->type != CREATURE_TYPE_UNDEAD))
279 continue;
281 if(m_caster->IsWithinDist(*iter, max_range) )
283 found = true;
284 break;
287 if (!found)
289 // clear cooldown at fail
290 if(m_caster->GetTypeId()==TYPEID_PLAYER)
292 WorldPacket data;
293 data.Initialize(SMSG_CLEAR_COOLDOWN);
294 data << uint32(20577); // spell id
295 data << m_caster->GetGUID();
296 data << uint32(0);
297 ((Player*)m_caster)->GetSession()->SendPacket(&data);
300 SendCastResult(CAST_FAIL_NO_NEARBY_CORPSES_TO_EAT);
301 return;
304 // ok, main function spell can be casted
306 finish(); // prepere to replacing this cpell cast to main function spell
308 // casting
309 SpellEntry *spellInfo = sSpellStore.LookupEntry( 20578 );
310 Spell *spell = new Spell(m_caster, spellInfo, false, 0);
311 if(!spellInfo)
313 sLog.outError("WORLD: unknown spell id %i\n", 20578);
314 return;
317 SpellCastTargets targets;
318 targets.setUnitTarget(m_caster);
319 spell->prepare(&targets);
320 return;
323 // More generic code later
325 // starshards/curse of agony hack .. this applies to 1.10 only
326 if (m_triggeredByAura)
328 SpellEntry *trig_info = m_triggeredByAura->GetSpellProto();
329 if ((trig_info->SpellIconID == 1485 && trig_info->SpellFamilyName == SPELLFAMILY_PRIEST) ||
330 (trig_info->SpellIconID == 544 && trig_info->SpellFamilyName == SPELLFAMILY_WARLOCK))
332 Unit *tmpTarget = unitTarget;
333 unitTarget = m_triggeredByAura->GetTarget();
334 damage = trig_info->EffectBasePoints[i]+1;
335 EffectSchoolDMG(i);
336 unitTarget = tmpTarget;
340 if(m_spellInfo->SpellIconID == 1648)
342 uint32 dmg = damage;
343 dmg += uint32(m_caster->GetPower(POWER_RAGE)/10 * FindSpellRank(m_spellInfo->Id)*3);
344 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, dmg);
345 m_caster->SetPower(POWER_RAGE,0);
349 void Spell::EffectTriggerSpell(uint32 i)
351 SpellEntry *spellInfo = sSpellStore.LookupEntry( m_spellInfo->EffectTriggerSpell[i] );
353 if(!spellInfo)
355 sLog.outError("WORLD: unknown spell id %i\n", m_spellInfo->EffectTriggerSpell[i]);
356 return;
359 m_TriggerSpell = spellInfo;
362 void Spell::EffectTeleportUnits(uint32 i)
364 if(!unitTarget)
365 return;
366 HandleTeleport(m_spellInfo->Id,unitTarget);
369 void Spell::EffectApplyAura(uint32 i)
371 if(!unitTarget)
372 return;
373 if(!unitTarget->isAlive())
374 return;
375 uint8 castResult = 0;
376 //If m_immuneToState type contain this aura type, IMMUNE aura.
377 for (SpellImmuneList::iterator itr = unitTarget->m_spellImmune[IMMUNITY_EFFECT].begin(), next; itr != unitTarget->m_spellImmune[IMMUNITY_EFFECT].end(); itr = next)
379 next = itr;
380 next++;
381 if((*itr)->type == m_spellInfo->EffectApplyAuraName[i])
383 castResult = CAST_FAIL_IMMUNE;
384 break;
387 if(castResult)
389 SendCastResult(castResult);
390 return;
392 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
394 Aura* Aur = new Aura(m_spellInfo, i, unitTarget,m_caster, m_CastItem);
396 if (!Aur->IsPositive() && Aur->GetTarget()->GetTypeId() == TYPEID_UNIT)
398 switch (Aur->GetModifier()->m_auraname)
400 case SPELL_AURA_MOD_DETECT_RANGE:
401 case SPELL_AURA_AURAS_VISIBLE:
402 break;
403 default:
404 ((Creature*)Aur->GetTarget())->AI().AttackStart(m_caster);
408 bool added = unitTarget->AddAura(Aur);
410 if (added && Aur->IsTrigger())
412 // arcane missiles
413 SpellEntry *spellInfo = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
414 if (!spellInfo) return;
415 if (spellInfo->EffectImplicitTargetA[0] == TARGET_SINGLE_ENEMY && m_caster->GetTypeId() == TYPEID_PLAYER)
417 Unit *target = ObjectAccessor::Instance().GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
418 if (target)
420 if (!m_caster->IsFriendlyTo(target))
421 Aur->SetTarget(target);
422 else
423 cancel();
425 else
426 cancel();
431 void Spell::EffectManaDrain(uint32 i)
433 if(m_spellInfo->EffectMiscValue[i] > 4)
434 return;
436 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
438 if(!unitTarget)
439 return;
440 if(!unitTarget->isAlive())
441 return;
442 if(unitTarget->getPowerType() != drain_power)
443 return;
445 uint32 curPower = unitTarget->GetPower(drain_power);
446 float tmpvalue = m_spellInfo->EffectMultipleValue[i];
447 if(!tmpvalue)
448 tmpvalue = 1;
450 int32 new_damage;
451 if(curPower < damage)
452 new_damage = curPower;
453 else
454 new_damage = damage;
456 unitTarget->ModifyPower(drain_power,-new_damage);
458 if(drain_power == POWER_MANA)
459 m_caster->ModifyPower(POWER_MANA,uint32(new_damage*tmpvalue));
462 void Spell::EffectSendEvent(uint32 i)
466 void Spell::EffectPowerDrain(uint32 i)
468 if(!unitTarget)
469 return;
470 if(!unitTarget->isAlive())
471 return;
472 if(unitTarget->getPowerType()!=POWER_MANA)
473 return;
475 uint32 curPower = unitTarget->GetPower(POWER_MANA);
476 uint32 curHealth = unitTarget->GetHealth();
478 int32 new_damage;
479 if(curPower < damage)
480 new_damage = curPower;
481 else
482 new_damage = damage;
484 int32 tmpvalue = int32(new_damage*m_spellInfo->EffectMultipleValue[i]);
486 unitTarget->ModifyPower(POWER_MANA,-new_damage);
488 m_caster->ModifyPower(POWER_MANA,tmpvalue);
489 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage);
493 void Spell::EffectHeal( uint32 i )
495 if( unitTarget && unitTarget->isAlive() )
497 int32 addhealth = unitTarget->SpellHealingBonus(m_spellInfo, damage);
498 bool crit = m_caster->SpellCriticalBonus(m_spellInfo, &addhealth);
499 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
500 SendHealSpellOnPlayer(((Player*)unitTarget), m_spellInfo->Id, addhealth, crit);
502 unitTarget->ModifyHealth( addhealth );
504 //If the target is in combat, then player is in combat too
505 if( m_caster != unitTarget &&
506 m_caster->GetTypeId() == TYPEID_PLAYER &&
507 unitTarget->GetTypeId() == TYPEID_PLAYER &&
508 unitTarget->isInCombatWithPlayer() )
510 ((Player*)m_caster)->SetPvP(true);
515 void Spell::EffectHealthLeach(uint32 i)
517 if(!unitTarget)
518 return;
519 if(!unitTarget->isAlive())
520 return;
522 sLog.outDebug("HealthLeach :%u", damage);
524 uint32 curPower = unitTarget->GetPower(POWER_MANA);
525 uint32 curHealth = unitTarget->GetHealth();
527 int32 new_damage;
528 if(curHealth < damage)
529 new_damage = curHealth;
530 else
531 new_damage = damage;
533 int32 tmpvalue = int32(new_damage*m_spellInfo->EffectMultipleValue[i]);
535 m_caster->ModifyHealth(tmpvalue);
537 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
538 SendHealSpellOnPlayer(((Player*)unitTarget), m_spellInfo->Id, uint32(tmpvalue));
540 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage);
543 void Spell::EffectCreateItem(uint32 i)
545 if (m_caster->GetTypeId() != TYPEID_PLAYER)
546 return;
548 Player* player = (Player*)m_caster;
550 uint32 newitemid = m_spellInfo->EffectItemType[i];
551 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
552 if(!pProto)
554 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
555 return;
558 uint32 num_to_add;
560 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
561 num_to_add = max(m_spellInfo->EffectBasePoints[i]+1, 1);
562 else if(player->getLevel() >= m_spellInfo->spellLevel)
563 num_to_add = ((player->getLevel() - (m_spellInfo->spellLevel-1))*2);
564 else
565 num_to_add = 2;
567 uint16 dest;
568 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, false);
569 if( msg != EQUIP_ERR_OK )
571 player->SendEquipError( msg, NULL, NULL );
572 return;
575 Item *pItem = player->StoreNewItem( dest, newitemid, num_to_add, true);
577 if(!pItem)
579 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
580 return;
583 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE )
584 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
586 //should send message "create item" to client.-FIX ME
587 player->UpdateSkillPro(m_spellInfo->Id);
590 void Spell::EffectPersistentAA(uint32 i)
592 float radius = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
593 int32 duration = GetDuration(m_spellInfo);
594 DynamicObject* dynObj = new DynamicObject();
595 if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
597 delete dynObj;
598 return;
600 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
601 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
602 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
603 m_caster->AddDynObject(dynObj);
604 dynObj->AddToWorld();
605 MapManager::Instance().GetMap(dynObj->GetMapId())->Add(dynObj);
609 void Spell::EffectEnergize(uint32 i)
611 if(!unitTarget)
612 return;
613 if(!unitTarget->isAlive())
614 return;
616 if(m_spellInfo->EffectMiscValue[i] > 4)
617 return;
619 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
621 if(unitTarget->getPowerType() != power)
622 return;
624 unitTarget->ModifyPower(power,damage);
627 void Spell::EffectOpenLock(uint32 i)
630 if(!gameObjTarget)
632 sLog.outDebug( "WORLD: Open Lock - No GameObject Target!");
633 return;
636 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
638 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
639 return;
642 LootType loottype = LOOT_CORPSE;
643 uint32 lockId = gameObjTarget->GetGOInfo()->sound0;
644 LockEntry *lockInfo = sLockStore.LookupEntry(lockId);
645 if (!lockInfo)
647 sLog.outError( "Spell::EffectOpenLock: gameobject [guid = %u] has an unknown lockId: %u!", gameObjTarget->GetGUIDLow() , lockId);
648 return;
650 uint16 skill = 999;
652 if(m_spellInfo->EffectMiscValue[0]==LOCKTYPE_HERBALISM)
654 skill = ((Player*)m_caster)->GetSkillValue(SKILL_HERBALISM);
655 loottype = LOOT_SKINNING;
656 } else
657 if(m_spellInfo->EffectMiscValue[0]==LOCKTYPE_MINING)
659 skill = ((Player*)m_caster)->GetSkillValue(SKILL_MINING);
660 loottype = LOOT_SKINNING;
663 if((skill != 999) && (skill < lockInfo->requiredskill))
665 SendCastResult(CAST_FAIL_FAILED);
666 return;
669 if( skill >= (lockInfo->requiredskill +75) )
670 up_skillvalue = 4;
671 else if( skill >= (lockInfo->requiredskill +50) )
672 up_skillvalue = 3;
673 else if( skill >= (lockInfo->requiredskill +25) )
674 up_skillvalue = 2;
675 else if( skill >= lockInfo->requiredskill)
676 up_skillvalue = 1;
677 else up_skillvalue = 0;
679 if(loottype == LOOT_CORPSE && gameObjTarget->HaveLootSkill())
681 gameObjTarget->SetLootSkill(false);
682 ((Player*)m_caster)->UpdateSkillPro(m_spellInfo->Id);
685 ((Player*)m_caster)->SendLoot(gameObjTarget->GetGUID(),loottype);
688 void Spell::EffectSummonChangeItem(uint32 i)
690 if(m_caster->GetTypeId() != TYPEID_PLAYER)
691 return;
693 Player *player = (Player*)m_caster;
695 uint32 newitemid = m_spellInfo->EffectItemType[i];
696 if(!newitemid)
697 return;
699 uint16 dest;
700 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, 1, false);
702 if( msg == EQUIP_ERR_OK )
704 player->StoreNewItem( dest, newitemid, 1, true);
706 else
707 player->SendEquipError( msg, NULL, NULL );
710 void Spell::EffectOpenSecretSafe(uint32 i)
712 EffectOpenLock(i); //no difference for now
715 void Spell::EffectProficiency(uint32 i)
717 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
718 return;
719 Player *p_target = (Player*)unitTarget;
721 uint32 newflag = m_spellInfo->EquippedItemSubClass;
722 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & newflag))
724 p_target->AddWeaponProficiency(newflag);
725 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
727 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & newflag))
729 p_target->AddArmorProficiency(newflag);
730 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
734 void Spell::EffectApplyAA(uint32 i)
736 if(!unitTarget)
737 return;
738 if(!unitTarget->isAlive())
739 return;
741 AreaAura* Aur = new AreaAura(m_spellInfo, i, unitTarget, m_caster);
742 unitTarget->AddAura(Aur);
745 void Spell::EffectSummon(uint32 i)
747 if(m_caster->GetPetGUID())
748 return;
750 if(!unitTarget)
751 return;
752 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
753 if(!pet_entry)
754 return;
755 uint32 level = m_caster->getLevel();
756 Pet* spawnCreature = new Pet();
758 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
759 m_caster->GetMapId(),
760 m_caster->GetPositionX(),m_caster->GetPositionY(),
761 m_caster->GetPositionZ(),m_caster->GetOrientation(),
762 m_spellInfo->EffectMiscValue[i]))
764 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
765 delete spawnCreature;
766 return;
769 spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
770 spawnCreature->SetPower( POWER_MANA,28 + 10 * level);
771 spawnCreature->SetMaxPower(POWER_MANA,28 + 10 * level);
772 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
773 spawnCreature->setPowerType(POWER_MANA);
774 spawnCreature->SetHealth( 28 + 30*level);
775 spawnCreature->SetMaxHealth( 28 + 30*level);
776 spawnCreature->SetLevel( level);
777 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
778 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
779 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
780 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
781 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
782 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
783 spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
785 spawnCreature->SetStat(STAT_STRENGTH,int(20+level*1.55));
786 spawnCreature->SetStat(STAT_AGILITY,int(20+level*0.64));
787 spawnCreature->SetStat(STAT_STAMINA,int(20+level*1.27));
788 spawnCreature->SetStat(STAT_INTELLECT,int(20+level*0.18));
789 spawnCreature->SetStat(STAT_SPIRIT,int(20+level*0.36));
791 spawnCreature->SetArmor(level*50);
792 spawnCreature->AIM_Initialize();
794 std::string name;
795 if(m_caster->GetTypeId() == TYPEID_PLAYER)
796 name = ((Player*)m_caster)->GetName();
797 else
798 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
799 name.append("'s Pet");
800 spawnCreature->SetName( name );
802 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)spawnCreature);
804 if(m_caster->GetTypeId() == TYPEID_PLAYER)
806 m_caster->SetPet(spawnCreature);
807 ((Player*)m_caster)->PetSpellInitialize();
808 ((Player*)m_caster)->SavePet();
812 void Spell::EffectLearnSpell(uint32 i)
814 if(!unitTarget)
815 return;
817 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
819 if(m_caster->GetTypeId() == TYPEID_PLAYER)
821 Creature *pet = m_caster->GetPet();
823 if( !pet || !pet->isPet() || pet!=unitTarget )
824 return;
826 EffectLearnPetSpell(i);
828 return;
831 Player *player = (Player*)unitTarget;
833 uint32 spellToLearn = m_spellInfo->EffectTriggerSpell[i];
834 //data.Initialize(SMSG_LEARNED_SPELL);
835 //data << spellToLearn;
836 //player->GetSession()->SendPacket(&data);
837 player->learnSpell((uint16)spellToLearn);
838 //some addspell isn't needed if you have a good DB,FISHING && MINING && HERBALISM have to be needed.
839 switch(spellToLearn)
841 case 4036: //SKILL_ENGINERING
843 player->learnSpell(3918);
844 player->learnSpell(3919);
845 player->learnSpell(3920);
846 break;
848 case 3908: //SKILL_TAILORING
850 player->learnSpell(2387);
851 player->learnSpell(2963);
852 break;
854 case 7411: //SKILL_ENCHANTING
856 player->learnSpell(7418);
857 player->learnSpell(7421);
858 player->learnSpell(13262);
859 break;
861 case 2259: //SKILL_ALCHEMY
863 player->learnSpell(2329);
864 player->learnSpell(7183);
865 player->learnSpell(2330);
866 break;
868 case 2018: //SKILL_BLACKSMITHING
870 player->learnSpell(2663);
871 player->learnSpell(12260);
872 player->learnSpell(2660);
873 player->learnSpell(3115);
874 break;
876 case 2108: //SKILL_LEATHERWORKING
878 player->learnSpell(2152);
879 player->learnSpell(9058);
880 player->learnSpell(9059);
881 player->learnSpell(2149);
882 player->learnSpell(7126);
883 player->learnSpell(2881);
884 break;
886 case 2550: //SKILL_COOKING
888 player->learnSpell(818);
889 player->learnSpell(2540);
890 player->learnSpell(2538);
891 break;
893 case 3273: //SKILL_FIRST_AID
895 player->learnSpell(3275);
896 break;
898 case 7620: //SKILL_FISHING
900 player->learnSpell(7738);
901 break;
903 case 2575: //SKILL_MINING
905 player->learnSpell(2580);
906 player->learnSpell(2656);
907 player->learnSpell(2657);
908 break;
910 case 2366: //SKILL_HERBALISM
912 player->learnSpell(2383);
913 break;
915 case 264: //SKILL_BOWS
917 if(!player->HasSpell(75))
918 player->learnSpell(2480);
919 break;
921 case 266: //SKILL_GUNS
923 if(!player->HasSpell(75))
924 player->learnSpell(7918);
925 break;
927 case 5011: //SKILL_CROSSBOWS
929 if(!player->HasSpell(75))
930 player->learnSpell(7919);
931 break;
933 case 2567: //SKILL_THROWN
935 player->learnSpell(2764);
936 break;
938 default:break;
940 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
943 void Spell::EffectDispel(uint32 i)
945 m_caster->RemoveFirstAuraByDispel(m_spellInfo->EffectMiscValue[i]);
948 void Spell::EffectDualWield(uint32 i)
950 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
951 ((Player*)unitTarget)->SetCanDualWield(true);
954 void Spell::EffectPickPocket(uint32 i)
956 if( m_caster->GetTypeId() != TYPEID_PLAYER )
957 return;
959 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
960 return;
962 if( unitTarget->getDeathState() == ALIVE && //victim is alive
963 //victim have to be humanoid
964 ((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_HUMANOID )
966 int chance = 10 + m_caster->getLevel() - unitTarget->getLevel();
968 if ( ( rand() % 20 ) <= chance )
970 //Stealing successfull
971 //sLog.outDebug("Sending loot from pickpocket");
972 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOKETING);
974 else
976 //Reveal action + get attack
977 m_caster->RemoveAurasDueToSpell(1784);
978 ((Creature*)unitTarget)->AI().AttackStart(m_caster);
983 void Spell::EffectSummonWild(uint32 i)
985 if(!unitTarget)
986 return;
987 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
988 if(!pet_entry)
989 return;
990 uint32 level = m_caster->getLevel();
992 // level of pet summoned using engineering item based at engineering skill level
993 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
995 ItemPrototype const *proto = m_CastItem->GetProto();
996 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
998 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
999 if(skill202)
1001 level = skill202/5;
1006 Pet* spawnCreature = new Pet();
1008 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
1009 m_caster->GetMapId(),
1010 m_caster->GetPositionX(),m_caster->GetPositionY(),
1011 m_caster->GetPositionZ(),m_caster->GetOrientation(),
1012 m_spellInfo->EffectMiscValue[i]))
1014 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
1015 delete spawnCreature;
1016 return;
1019 spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
1020 spawnCreature->setPowerType(POWER_MANA);
1021 spawnCreature->SetPower( POWER_MANA,28 + 10 * level);
1022 spawnCreature->SetMaxPower(POWER_MANA,28 + 10 * level);
1023 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
1024 spawnCreature->SetHealth( 28 + 30*level);
1025 spawnCreature->SetMaxHealth( 28 + 30*level);
1026 spawnCreature->SetLevel(level);
1027 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1028 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
1029 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
1030 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
1031 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1032 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1033 spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1035 spawnCreature->SetArmor(level*50);
1036 spawnCreature->AIM_Initialize();
1038 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)spawnCreature);
1040 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1042 m_caster->SetPet(spawnCreature);
1043 ((Player*)m_caster)->PetSpellInitialize();
1044 ((Player*)m_caster)->SavePet();
1048 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
1050 if(!unitTarget)
1051 return;
1053 if(unitTarget->isInFlight())
1054 return;
1056 uint32 mapid = m_caster->GetMapId();
1057 float dis = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
1058 float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
1059 float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
1060 // teleport a bit above terrainlevel to avoid falling below it
1061 float fz = MapManager::Instance ().GetMap(mapid)->GetHeight(fx,fy) + 1.5;
1063 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1064 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), false);
1065 else
1066 MapManager::Instance().GetMap(mapid)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
1069 void Spell::EffectLearnSkill(uint32 i)
1071 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1072 return;
1074 uint32 skillid = m_spellInfo->EffectMiscValue[i];
1075 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
1076 ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,damage*75);
1079 void Spell::EffectTradeSkill(uint32 i)
1081 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1082 return;
1083 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
1084 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
1085 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
1088 void Spell::EffectEnchantItemPerm(uint32 i)
1090 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1091 return;
1092 if (!itemTarget)
1093 return;
1095 Player* p_caster = (Player*)m_caster;
1097 p_caster->UpdateSkillPro(m_spellInfo->Id);
1099 if (m_spellInfo->EffectMiscValue[i])
1101 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
1103 SpellItemEnchantmentEntry *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1104 if(!pEnchant)
1105 return;
1107 // remove old enchanting before appling new if equiped
1108 if(itemTarget->IsEquipped())
1110 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT))
1111 p_caster->AddItemEnchant(itemTarget,old_enchant_id,false);
1114 for(int x=0;x<3;x++)
1115 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+x,0);
1117 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, enchant_id);
1119 // add new enchanting if equiped
1120 if(itemTarget->IsEquipped())
1122 p_caster->AddItemEnchant(itemTarget,enchant_id,true);
1125 //p_caster->GetSession()->SendEnchantmentLog(itemTarget->GetGUID(),p_caster->GetGUID(),itemTarget->GetEntry(),m_spellInfo->Id);
1126 //p_caster->GetSession()->SendItemEnchantTimeUpdate(itemTarget->GetGUID(),pEnchant->display_type,duration);
1130 void Spell::EffectEnchantItemTmp(uint32 i)
1132 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1133 return;
1135 Player* p_caster = (Player*)m_caster;
1137 if(!itemTarget)
1138 return;
1140 if (m_spellInfo->EffectMiscValue[i])
1142 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
1143 int32 duration = GetDuration(m_spellInfo);
1144 if(duration == 0)
1145 duration = m_spellInfo->EffectBasePoints[i]+1;
1146 if(duration <= 1)
1147 duration = 300;
1148 SpellItemEnchantmentEntry *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1149 if(!pEnchant)
1150 return;
1152 // remove old enchanting before applying new if equipped
1153 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+1*3))
1155 if(itemTarget->IsEquipped())
1156 p_caster->AddItemEnchant(itemTarget,old_enchant_id,false);
1158 // duration == 0 will remove EnchantDuration
1159 p_caster->AddEnchantDuration(itemTarget,1,0);
1162 for(int x=0;x<3;x++)
1163 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3+x,0);
1165 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3, enchant_id);
1166 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3+1, duration*1000);
1167 if(m_spellInfo->SpellFamilyName == 8)
1168 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3+2, 45+FindSpellRank(m_spellInfo->Id)*15);
1170 // add new enchanting if equipped
1171 if(itemTarget->IsEquipped())
1173 p_caster->AddItemEnchant(itemTarget,enchant_id,true);
1176 // set duration
1177 p_caster->AddEnchantDuration(itemTarget,1,duration*1000);
1179 //p_caster->GetSession()->SendEnchantmentLog(itemTarget->GetGUID(),p_caster->GetGUID(),itemTarget->GetEntry(),m_spellInfo->Id);
1180 p_caster->GetSession()->SendItemEnchantTimeUpdate(itemTarget->GetGUID(),pEnchant->display_type,duration);
1184 void Spell::EffectTameCreature(uint32 i)
1186 if(m_caster->GetPetGUID())
1187 return;
1189 if(!unitTarget)
1190 return;
1192 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1193 return;
1195 Creature* creatureTarget = (Creature*)unitTarget;
1197 if(m_caster->getClass() == CLASS_HUNTER)
1199 creatureTarget->AttackStop();
1200 if(m_caster->getVictim()==creatureTarget)
1201 m_caster->AttackStop();
1203 uint32 petlevel = creatureTarget->getLevel();
1204 creatureTarget->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
1205 creatureTarget->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1206 creatureTarget->SetMaxPower(POWER_HAPPINESS,1000000);
1207 creatureTarget->SetPower( POWER_HAPPINESS,600000);
1208 creatureTarget->setPowerType(POWER_FOCUS);
1209 creatureTarget->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1210 creatureTarget->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
1211 creatureTarget->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1212 creatureTarget->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1213 creatureTarget->SetTamed(true);
1214 creatureTarget->AIM_Initialize();
1216 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1218 m_caster->SetPet(creatureTarget);
1219 ((Player*)m_caster)->PetSpellInitialize();
1220 ((Player*)m_caster)->SavePet();
1225 void Spell::EffectSummonPet(uint32 i)
1227 float px, py, pz;
1228 m_caster->GetClosePoint(NULL, px, py, pz);
1230 uint32 petentry = m_spellInfo->EffectMiscValue[i];
1232 Creature *OldSummon = m_caster->GetPet();
1234 // if pet requested type already exist
1235 if(OldSummon && OldSummon->isPet() && OldSummon->GetCreatureInfo()->Entry == petentry)
1237 if(OldSummon->isDead() )
1239 uint32 petlvl = OldSummon->getLevel();
1240 OldSummon->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
1241 OldSummon->SetHealth( 28 + 10 * petlvl );
1242 OldSummon->SetMaxHealth( 28 + 10 * petlvl );
1243 OldSummon->SetPower( POWER_MANA, 28 + 10 * petlvl);
1244 OldSummon->SetMaxPower(POWER_MANA, 28 + 10 * petlvl);
1245 OldSummon->setDeathState(ALIVE);
1246 OldSummon->clearUnitState(UNIT_STAT_ALL_STATE);
1247 (*OldSummon)->Clear();
1249 MapManager::Instance().GetMap(OldSummon->GetMapId())->Remove(OldSummon,false);
1250 OldSummon->SetMapId(m_caster->GetMapId());
1251 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
1252 MapManager::Instance().GetMap(m_caster->GetMapId())->Add(OldSummon);
1253 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1255 ((Player*)m_caster)->PetSpellInitialize();
1256 ((Player*)m_caster)->SavePet();
1258 return;
1261 if(OldSummon)
1263 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1264 ((Player*)m_caster)->UnsummonPet(OldSummon);
1265 else
1266 return;
1269 Pet* NewSummon = new Pet();
1271 uint32 ownerid = m_caster->GetGUIDLow();
1273 if(NewSummon->LoadPetFromDB(m_caster,petentry))
1275 ((Player*)m_caster)->SavePet();
1276 return;
1279 if( NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMapId(), px, py, pz+1, m_caster->GetOrientation(), petentry))
1281 uint32 petlevel=m_caster->getLevel();
1282 NewSummon->SetLevel(petlevel);
1283 NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
1284 NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1285 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0);
1286 NewSummon->SetHealth( 28 + 10 * petlevel);
1287 NewSummon->SetMaxHealth( 28 + 10 * petlevel);
1288 NewSummon->SetPower( POWER_MANA , 28 + 10 * petlevel);
1289 NewSummon->SetMaxPower(POWER_MANA, 28 + 10 * petlevel);
1290 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1291 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
1292 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,0);
1293 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
1294 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,5);
1295 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1296 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1297 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
1298 NewSummon->SetStat(STAT_STRENGTH,22);
1299 NewSummon->SetStat(STAT_AGILITY,22);
1300 NewSummon->SetStat(STAT_STAMINA,25);
1301 NewSummon->SetStat(STAT_INTELLECT,28);
1302 NewSummon->SetStat(STAT_SPIRIT,27);
1304 for(uint32 i=0; i < CREATURE_MAX_SPELLS; i++)
1305 NewSummon->m_spells[i] = 0;
1307 if(petentry == 416) //imp
1309 NewSummon->m_spells[0] = 3110; //3110---fire bolt 1
1310 NewSummon->AddActState(STATE_RA_SPELL1);
1313 NewSummon->SaveToDB();
1314 NewSummon->AIM_Initialize();
1315 MapManager::Instance().GetMap(NewSummon->GetMapId())->Add((Creature*)NewSummon);
1317 m_caster->SetPet(NewSummon);
1318 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
1320 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1322 ((Player*)m_caster)->PetSpellInitialize();
1323 ((Player*)m_caster)->SavePet();
1326 else
1327 delete NewSummon;
1330 void Spell::EffectLearnPetSpell(uint32 i)
1332 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1333 return;
1335 Player *_player = (Player*)m_caster;
1337 Creature *pet = _player->GetPet();
1338 if(!pet)
1339 return;
1340 if(!pet->isAlive())
1341 return;
1343 SpellEntry *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
1344 if(!learn_spellproto)
1345 return;
1346 SpellEntry *has_spellproto;
1347 for(int8 x=0;x<4;x++)
1349 has_spellproto = sSpellStore.LookupEntry(pet->m_spells[x]);
1350 if(!has_spellproto)
1352 pet->m_spells[x] = learn_spellproto->Id;
1353 break;
1355 else if(has_spellproto->SpellIconID == learn_spellproto->SpellIconID)
1357 pet->m_spells[x] = learn_spellproto->Id;
1358 break;
1361 _player->SavePet();
1362 _player->PetSpellInitialize();
1365 void Spell::EffectAttackMe(uint32 i)
1367 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1369 unitTarget->SetInFront(m_caster);
1370 ((Creature*)unitTarget)->AI().AttackStart(m_caster);
1374 void Spell::EffectWeaponDmg(uint32 i)
1376 if(!unitTarget)
1377 return;
1378 if(!unitTarget->isAlive())
1379 return;
1381 uint32 wp[4] = { SPELL_EFFECT_WEAPON_DAMAGE, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE, SPELL_EFFECT_NORMALIZED_WEAPON_DMG, SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL };
1383 // multiple weap dmg effect workaround
1384 // execute only the first weapon damage
1385 // and handle all effects at once
1386 uint8 j,k;
1387 int32 bonus = 0;
1389 for (j = 0; j < 3; j++)
1391 for (k = 0; k < 4; k++)
1392 if (m_spellInfo->Effect[j] == wp[k])
1393 break;
1394 if (k != 4)
1396 if (j < i)
1397 return;
1398 if (m_spellInfo->Effect[j] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE)
1399 bonus += m_spellInfo->EffectBasePoints[j]+1;
1403 WeaponAttackType attType = BASE_ATTACK;
1404 if(m_spellInfo->rangeIndex != 1 && m_spellInfo->rangeIndex != 2 && m_spellInfo->rangeIndex != 7)
1405 attType = RANGED_ATTACK;
1407 uint32 hitInfo = 0;
1408 uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
1409 uint32 damageType = NORMAL_DAMAGE;
1410 uint32 victimState = VICTIMSTATE_NORMAL;
1411 uint32 damage = 0;
1412 uint32 blocked_dmg = 0;
1413 uint32 absorbed_dmg = 0;
1414 uint32 resisted_dmg = 0;
1415 uint32 procflag = 0;
1417 m_caster->DoAttackDamage(unitTarget, &damage, &blocked_dmg, &damageType, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, attType);
1419 if (damage + bonus > 0)
1420 damage += bonus;
1421 else
1422 damage = 0;
1424 for (j = 0; j < 3; j++)
1425 if (m_spellInfo->Effect[j] == SPELL_EFFECT_WEAPON_PERCENT_DAMAGE)
1426 damage = uint32(damage * (m_spellInfo->EffectBasePoints[j]+1) / 100);
1428 if (hitInfo & nohitMask)
1429 m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellInfo->School, damage, absorbed_dmg, resisted_dmg, 1, blocked_dmg);
1431 m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage + absorbed_dmg + resisted_dmg + blocked_dmg, m_spellInfo->School, absorbed_dmg, resisted_dmg, true, blocked_dmg);
1432 m_caster->DealDamage(unitTarget, damage, 0, true);
1434 // take ammo
1435 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1437 if(m_spellInfo->rangeIndex != 1 && m_spellInfo->rangeIndex != 2 && m_spellInfo->rangeIndex != 7)
1439 Item *pItem = ((Player*)m_caster)->GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED );
1440 if(!pItem || pItem->IsBroken())
1441 return;
1443 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
1445 uint32 count = 1;
1446 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
1448 else
1449 ((Player*)m_caster)->DestroyItemCount( ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID) , 1, true);
1453 /*if(m_spellInfo->Effect[i] == 121)
1455 m_caster->resetAttackTimer(BASE_ATTACK);
1456 m_caster->resetAttackTimer(OFF_ATTACK);
1457 m_caster->resetAttackTimer(RANGED_ATTACK);
1461 void Spell::EffectThreat(uint32 i)
1463 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
1464 return;
1465 unitTarget->AddHostil(m_caster->GetGUID(),float(damage));
1468 void Spell::EffectHealMaxHealth(uint32 i)
1470 if(!unitTarget)
1471 return;
1472 if(!unitTarget->isAlive())
1473 return;
1475 uint32 heal = m_caster->GetMaxHealth();
1477 unitTarget->ModifyHealth(heal);
1479 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1480 SendHealSpellOnPlayer((Player*)unitTarget, m_spellInfo->Id, heal);
1483 void Spell::EffectInterruptCast(uint32 i)
1485 if(!unitTarget)
1486 return;
1487 if(!unitTarget->isAlive())
1488 return;
1490 unitTarget->InterruptSpell();
1493 void Spell::EffectScriptEffect(uint32 i)
1495 if(!m_spellInfo->Reagent[0])
1497 // paladin's holy light / flash of light
1498 if ((m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN) &&
1499 (m_spellInfo->SpellIconID == 70 || m_spellInfo->SpellIconID == 242))
1500 EffectHeal( i );
1502 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && (m_spellInfo->SpellFamilyFlags & (1<<23)))
1504 // paladin's judgement
1505 if(!unitTarget || !unitTarget->isAlive())
1506 return;
1507 uint32 spellId2 = 0;
1508 Unit::AuraMap& m_auras = m_caster->GetAuras();
1509 Unit::AuraMap::iterator itr,next;
1511 for(itr = m_auras.begin(); itr != m_auras.end(); itr = next)
1513 next = itr;
1514 next++;
1515 if (itr->second)
1517 SpellEntry *spellInfo = itr->second->GetSpellProto();
1518 if (!spellInfo) continue;
1519 if (spellInfo->SpellVisual != 5622 || spellInfo->SpellFamilyName != SPELLFAMILY_PALADIN) continue;
1520 spellId2 = spellInfo->EffectBasePoints[2]+1;
1521 if(spellId2 <= 1)
1522 continue;
1523 m_caster->RemoveAurasDueToSpell(spellInfo->Id);
1524 next = m_auras.begin();
1525 break;
1529 SpellEntry *spellInfo = sSpellStore.LookupEntry(spellId2);
1530 if(!spellInfo)
1531 return;
1532 Spell *p_spell = new Spell(m_caster,spellInfo,true,0);
1533 if(!p_spell)
1534 return;
1535 SpellCastTargets targets;
1536 Unit *ptarget = unitTarget;
1537 targets.setUnitTarget(ptarget);
1538 p_spell->prepare(&targets);
1541 else
1543 switch(m_spellInfo->Id)
1545 case 6201:
1546 m_spellInfo->EffectItemType[0] = 5512; //spell 6261; //primary healstone
1547 break;
1548 case 6202:
1549 m_spellInfo->EffectItemType[0] = 5511; //spell 6262; //inferior healstone
1550 break;
1551 case 5699:
1552 m_spellInfo->EffectItemType[0] = 5509; //spell 5720; //healstone
1553 break;
1554 case 11729:
1555 m_spellInfo->EffectItemType[0] = 5510; //spell 5723; //strong healstone
1556 break;
1557 case 11730:
1558 m_spellInfo->EffectItemType[0] = 9421; //spell 11732; //super healstone
1559 break;
1560 default:
1561 return;
1563 EffectCreateItem( i );
1567 void Spell::EffectAddComboPoints(uint32 i)
1569 if(!unitTarget)
1570 return;
1572 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1573 return;
1575 uint8 comboPoints = ((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & 0xFF00) >> 8);
1576 if(m_caster->GetUInt64Value(PLAYER_FIELD_COMBO_TARGET) != unitTarget->GetGUID())
1578 comboPoints = damage;
1579 m_caster->SetUInt64Value(PLAYER_FIELD_COMBO_TARGET,unitTarget->GetGUID());
1580 m_caster->SetUInt32Value(PLAYER_FIELD_BYTES,((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & ~(0xFF << 8)) | (comboPoints << 8)));
1582 else if(comboPoints < 5)
1584 comboPoints += damage;
1585 if(comboPoints > 5)
1586 comboPoints = 5;
1587 m_caster->SetUInt32Value(PLAYER_FIELD_BYTES,((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & ~(0xFF << 8)) | (comboPoints << 8)));
1592 void Spell::EffectDuel(uint32 i)
1594 WorldPacket data;
1596 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
1597 return;
1599 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
1600 return;
1602 Player *caster = (Player*)m_caster;
1603 Player *target = (Player*)unitTarget;
1605 // caster or target already have requested duel
1606 if( caster->isRequestedOrStartDuel() || target->isRequestedOrStartDuel() ) return;
1608 //CREATE DUEL FLAG OBJECT
1609 GameObject* pGameObj = new GameObject();
1611 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
1613 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,m_caster->GetMapId(),
1614 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
1615 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
1616 m_caster->GetPositionZ(),
1617 m_caster->GetOrientation(), 0, 0, 0, 0))
1619 delete pGameObj;
1620 return;
1622 pGameObj->SetFloatValue(OBJECT_FIELD_SCALE_X,1.0f);
1624 pGameObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 787 );
1625 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
1626 pGameObj->SetUInt32Value(GAMEOBJECT_TYPE_ID, 16 );
1627 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
1628 pGameObj->SetRespawnTimer(GetDuration(m_spellInfo));
1629 pGameObj->SetSpellId(m_spellInfo->Id);
1631 m_caster->AddGameObject(pGameObj);
1632 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
1633 //END
1635 //Send request to opositor
1636 data.Initialize(SMSG_DUEL_REQUESTED);
1637 data << pGameObj->GetGUID();
1638 data << caster->GetGUID();
1639 target->GetSession()->SendPacket(&data);
1640 //Set who are the oponents
1641 caster->SetDuelVs(target);
1642 target->SetDuelVs(caster);
1643 //Players are not in duel yet...
1644 caster->SetInDuel(false);
1645 target->SetInDuel(false);
1646 //Set who is the duel caster
1647 caster->SetDuelSender(caster);
1648 target->SetDuelSender(caster);
1650 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
1651 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
1655 void Spell::EffectSummonTotem(uint32 i)
1657 uint8 slot = 0;
1658 switch(m_spellInfo->Effect[i])
1660 case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: slot = 0; break;
1661 case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: slot = 1; break;
1662 case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: slot = 2; break;
1663 case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: slot = 3; break;
1664 default: return;
1667 uint64 guid = m_caster->m_TotemSlot[slot];
1668 if(guid != 0)
1670 Creature *OldTotem = ObjectAccessor::Instance().GetCreature(*m_caster, guid);
1671 if(OldTotem && OldTotem->isTotem()) ((Totem*)OldTotem)->UnSummon();
1672 m_caster->m_TotemSlot[slot] = 0;
1675 Totem* pTotem = new Totem();
1677 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),
1678 m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(),
1679 m_caster->GetPositionZ(),m_caster->GetOrientation(),
1680 m_spellInfo->EffectMiscValue[i] ))
1682 delete pTotem;
1683 return;
1686 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
1687 pTotem->SetOwner(m_caster->GetGUID());
1688 //pTotem->SetSpell(pTotem->GetCreatureInfo()->spell1);
1689 pTotem->SetSpell(m_spellInfo->Id); //use SummonTotem spellid
1690 pTotem->SetDuration(GetDuration(m_spellInfo));
1691 pTotem->SetHealth(5);
1692 pTotem->SetMaxHealth(5);
1693 pTotem->Summon();
1696 void Spell::EffectEnchantHeldItem(uint32 i)
1698 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1699 return;
1701 Player* p_caster = (Player*)m_caster;
1703 if(!itemTarget)
1704 return;
1706 // must be equipped
1707 if(!itemTarget->IsEquipped())
1708 return;
1710 if (m_spellInfo->EffectMiscValue[i])
1712 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
1713 int32 duration = GetDuration(m_spellInfo);
1714 if(duration == 0)
1715 duration = m_spellInfo->EffectBasePoints[i]+1;
1716 if(duration <= 1)
1717 duration = 300;
1718 SpellItemEnchantmentEntry *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1719 if(!pEnchant)
1720 return;
1722 // remove old enchanting before appling new
1723 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3))
1724 p_caster->AddItemEnchant(itemTarget,enchant_id,false);
1726 for(int x=0;x<3;x++)
1727 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+x,0);
1729 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3, enchant_id);
1730 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+1, duration*1000);
1732 // add new enchanting
1733 p_caster->AddItemEnchant(itemTarget,enchant_id,true);
1735 //p_caster->GetSession()->SendEnchantmentLog(itemTarget->GetGUID(),p_caster->GetGUID(),itemTarget->GetEntry(),m_spellInfo->Id);
1736 p_caster->GetSession()->SendItemEnchantTimeUpdate(itemTarget->GetGUID(),pEnchant->display_type,duration);
1740 void Spell::EffectDisEnchant(uint32 i)
1742 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1743 return;
1745 Player* p_caster = (Player*)m_caster;
1746 if(!itemTarget)
1747 return;
1748 uint32 item_level = itemTarget->GetProto()->ItemLevel;
1749 uint32 item_quality = itemTarget->GetProto()->Quality;
1751 uint32 item = 0;
1752 uint32 count = 0;
1753 if(item_level >= 51)
1755 if(item_quality == 4)
1757 count = urand(3,5);
1758 item = 14344;
1760 else if(item_quality == 3)
1762 count = 1;
1763 item = 14344;
1765 else if(item_quality == 2)
1767 count = urand(1,(item_level/10));
1768 if(urand(1,100)< 85)
1769 item = 16204;
1770 else
1771 item = 16203;
1774 else if(item_level >= 46 && item_level <= 50)
1776 if(item_quality == 4)
1778 count = urand(3,5);
1779 item = 14343;
1781 else if(item_quality == 3)
1783 count = 1;
1784 item = 14343;
1786 else if(item_quality == 2)
1788 count = urand(1,(item_level/10));
1789 if(urand(1,100)< 85)
1790 count = 11176;
1791 else
1792 count = 16202;
1795 else if(item_level >= 41 && item_level <= 45)
1797 if(item_quality == 4)
1799 count = urand(3,5);
1800 item = 11178;
1802 else if(item_quality == 3)
1804 count = 1;
1805 item = 11178;
1807 else if(item_quality == 2)
1809 count = urand(1,(item_level/10));
1810 if(urand(1,100)< 85)
1811 item = 11176;
1812 else
1813 item = 11175;
1816 else if(item_level >= 36 && item_level <= 40)
1818 if(item_quality == 4)
1820 count = urand(3,5);
1821 item = 11177;
1823 else if(item_quality == 3)
1825 count = 1;
1826 item = 11177;
1828 else if(item_quality == 2)
1830 count = urand(1,(item_level/10));
1831 if(urand(1,100)< 85)
1832 item = 11137;
1833 else
1834 item = 11174;
1837 else if(item_level >= 31 && item_level <= 35)
1839 if(item_quality == 4)
1841 count = urand(3,5);
1842 item = 11139;
1844 else if(item_quality == 3)
1846 count = 1;
1847 item = 11139;
1849 else if(item_quality == 2)
1851 count = (item_level/10);
1852 if(urand(1,100)< 85)
1853 item = 11137;
1854 else
1855 item = 11135;
1858 else if(item_level >= 25 && item_level <= 30)
1860 if(item_quality == 4)
1862 count = urand(3,5);
1863 item = 11138;
1865 else if(item_quality == 3)
1867 count = 1;
1868 item = 11138;
1870 else if(item_quality == 2)
1872 count = (item_level/10);
1873 if(urand(1,100)< 85)
1874 item = 11083;
1875 else
1876 item = 11134;
1879 else if(item_level >= 21 && item_level <= 25)
1881 if(item_quality == 4)
1883 count = urand(3,5);
1884 item = 11084;
1886 else if(item_quality == 3)
1888 count = 1;
1889 item = 11084;
1891 else if(item_quality == 2)
1893 count = (item_level/10);
1894 if(urand(1,100)< 85)
1895 item = 11083;
1896 else
1897 item = 11082;
1900 else if(item_level >= 1 && item_level <= 20)
1902 if(item_quality == 4)
1904 count = urand(3,5);
1905 item = 10978;
1907 else if(item_quality == 3 && item_level >=16)
1909 count = 1;
1910 item = 10978;
1912 else if(item_quality == 2)
1914 if(urand(1,100)< 70)
1916 count = urand(1,3);
1917 item = 10940;
1919 else if(item_level <=15 && urand(1,100)< 70 )
1921 count = urand(1,3);
1922 item = 10938;
1924 else if(urand(1,100)< 50)
1926 count = urand(1,3);
1927 item = 10939;
1929 else
1931 count = urand(1,3);
1932 item = 10998;
1937 if ( item == 0 || count == 0 )
1938 { //Fix crash
1939 SendCastResult(CAST_FAIL_CANT_BE_DISENCHANTED);
1940 //SendChannelUpdate(0);
1941 return;
1944 uint32 item_count = 1;
1945 p_caster->DestroyItemCount(itemTarget,item_count, true);
1946 p_caster->UpdateSkillPro(m_spellInfo->Id);
1948 uint16 dest;
1949 uint8 msg = p_caster->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item, count, false );
1950 if( msg == EQUIP_ERR_OK )
1951 p_caster->StoreNewItem( dest, item, count, true );
1952 else
1953 p_caster->SendEquipError( msg, NULL, NULL );
1954 return ;
1957 void Spell::EffectInebriate(uint32 i)
1959 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1960 return;
1962 Player *player = (Player*)m_caster;
1963 uint16 currentDrunk = player->GetDrunkValue();
1964 uint16 drunkMod = (m_spellInfo->EffectBasePoints[i]+1) * 0xFFFF / 100;
1965 if (currentDrunk + drunkMod > 0xFFFF)
1966 currentDrunk = 0xFFFF;
1967 else
1968 currentDrunk += drunkMod;
1969 player->SetDrunkValue(currentDrunk);
1972 void Spell::EffectFeedPet(uint32 i)
1974 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1975 return;
1977 Player *_player = (Player*)m_caster;
1979 Creature *pet = _player->GetPet();
1980 if(!pet)
1981 return;
1982 if(!pet->isAlive())
1983 return;
1985 pet->ModifyPower(POWER_HAPPINESS,damage);
1987 SpellEntry *spellinfo = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
1988 Spell _spell(m_caster, spellinfo, true, 0);
1989 SpellCastTargets targets;
1990 targets.setUnitTarget(m_caster);
1991 _spell.prepare(&targets);
1994 void Spell::EffectDismissPet(uint32 i)
1996 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1997 return;
1999 if(m_caster->GetPet()->isPet())
2000 ((Player*)m_caster)->UnsummonPet();
2001 else if(m_caster->GetPet()->isTamed())
2002 ((Player*)m_caster)->UnTamePet();
2005 void Spell::EffectSummonObject(uint32 i)
2007 WorldPacket data;
2008 uint8 slot = 0;
2009 switch(m_spellInfo->Effect[i])
2011 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
2012 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
2013 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
2014 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
2015 default: return;
2018 uint64 guid = m_caster->m_ObjectSlot[slot];
2019 if(guid != 0)
2021 GameObject* obj = NULL;
2022 if( m_caster )
2023 obj = ObjectAccessor::Instance().GetGameObject(*m_caster, guid);
2025 if(obj) obj->Delete();
2026 m_caster->m_ObjectSlot[slot] = 0;
2029 GameObject* pGameObj = new GameObject();
2030 uint32 display_id = m_spellInfo->EffectMiscValue[i];
2032 float rot2 = sin(m_caster->GetOrientation()/2);
2033 float rot3 = cos(m_caster->GetOrientation()/2);
2035 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), display_id,m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), m_caster->GetOrientation(), 0, 0, rot2, rot3))
2037 delete pGameObj;
2038 return;
2041 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
2042 pGameObj->SetRespawnTimer(GetDuration(m_spellInfo));
2043 pGameObj->SetSpellId(m_spellInfo->Id);
2044 pGameObj->SetLootState(GO_CLOSED);
2045 m_caster->AddGameObject(pGameObj);
2047 sLog.outError("AddObject at Spell.cpp 1100");
2049 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
2050 data.Initialize(SMSG_GAMEOBJECT_SPAWN_ANIM);
2051 data << pGameObj->GetGUID();
2052 m_caster->SendMessageToSet(&data,true);
2054 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
2057 void Spell::EffectResurrect(uint32 i)
2060 if(!unitTarget)
2061 return;
2062 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
2063 return;
2065 if(unitTarget->isAlive())
2066 return;
2067 if(!unitTarget->IsInWorld())
2068 return;
2070 Player* pTarget = ((Player*)unitTarget);
2072 uint32 health = m_spellInfo->EffectBasePoints[i]+1;
2073 uint32 mana = m_spellInfo->EffectMiscValue[i];
2075 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
2076 SendResurrectRequest(pTarget);
2079 void Spell::EffectParry(uint32 i)
2081 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
2083 ((Player*)unitTarget)->SetCanParry(true);
2087 void Spell::EffectMomentMove(uint32 i)
2089 if(unitTarget->isInFlight())
2090 return;
2092 if( m_spellInfo->rangeIndex== 1) //self range
2094 uint32 mapid = m_caster->GetMapId();
2095 float dis = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2096 float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
2097 float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
2098 // teleport a bit above terrainlevel to avoid falling below it
2099 float fz = MapManager::Instance ().GetMap(mapid)->GetHeight(fx,fy) + 1.5;
2101 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2102 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, m_caster->GetOrientation(), false);
2103 else
2104 MapManager::Instance().GetMap(mapid)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, m_caster->GetOrientation());
2108 void Spell::EffectReputation(uint32 i)
2110 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2111 return;
2113 Player *_player = (Player*)m_caster;
2115 int32 rep_change = m_spellInfo->EffectBasePoints[i]+1; // field store reputation change -1
2117 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
2119 FactionEntry* factionEntry = sFactionStore.LookupEntry(faction_id);
2121 if(!factionEntry)
2122 return;
2124 _player->ModifyFactionReputation(factionEntry,rep_change);
2127 void Spell::EffectQuestComplete(uint32 i)
2129 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2130 return;
2132 Player *_player = (Player*)m_caster;
2134 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
2136 if(_player->CanCompleteQuest( quest_id ) )
2137 _player->CompleteQuest( quest_id );
2138 else
2139 return;
2141 if(_player->GetQuestRewardStatus( quest_id ))
2142 return;
2144 _player->PlayerTalkClass->SendQuestReward( quest_id, _player->GetGUID(), true, NULL, 0 );
2147 void Spell::EffectSelfResurrect(uint32 i)
2149 if(!unitTarget) return;
2150 if(unitTarget->GetTypeId() != TYPEID_PLAYER) return;
2151 if(unitTarget->isAlive()) return;
2152 if(!unitTarget->IsInWorld()) return;
2154 uint32 health = 0;
2155 uint32 mana = 0;
2157 if(m_spellInfo->SpellVisual == 99 && m_spellInfo->SpellIconID ==1)
2159 health = m_spellInfo->EffectBasePoints[i]+1 > 0 ? m_spellInfo->EffectBasePoints[i]+1 :(-(m_spellInfo->EffectBasePoints[i]+1));
2160 if(unitTarget->getPowerType() == POWER_MANA)
2161 mana = m_spellInfo->EffectMiscValue[i];
2163 else
2165 health = uint32(damage/100*unitTarget->GetMaxHealth());
2166 if(unitTarget->getPowerType() == POWER_MANA)
2167 mana = uint32(damage/100*unitTarget->GetMaxPower(unitTarget->getPowerType()));
2169 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
2170 SendResurrectRequest((Player*)unitTarget);
2173 void Spell::EffectSkinning(uint32 i)
2175 if(unitTarget->GetTypeId() != TYPEID_UNIT )
2176 return;
2177 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2178 return;
2180 int32 skinningValue = ((Player*)m_caster)->GetSkillValue(SKILL_SKINNING);
2181 int32 targetLevel = unitTarget->getLevel();
2183 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_SKINNING);
2184 unitTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
2186 int32 reqValue = targetLevel<20 ? (targetLevel-10)*10 : targetLevel*5;
2188 if(skinningValue >= reqValue + 100)
2189 up_skillvalue = 4;
2190 else if(skinningValue >= reqValue + 50)
2191 up_skillvalue = 3;
2192 else if(skinningValue >= reqValue + 25)
2193 up_skillvalue = 2;
2194 else if(skinningValue >= reqValue)
2195 up_skillvalue = 1;
2196 else up_skillvalue = 0;
2198 uint8 minColorLevel = skinningValue<25 ? 1 : skinningValue<50 ? 2 : skinningValue<100 ? 3 : 4;
2199 if(up_skillvalue > minColorLevel)
2200 up_skillvalue = minColorLevel;
2202 if( ((Creature*)unitTarget)->isElite() && up_skillvalue > 1 && up_skillvalue < 4)
2203 up_skillvalue--;
2206 void Spell::EffectCharge(uint32 i)
2208 if(!unitTarget || !m_caster)
2209 return;
2211 float x, y, z;
2212 unitTarget->GetClosePoint(m_caster, x, y, z);
2213 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
2214 ((Creature *)unitTarget)->StopMoving();
2216 m_caster->SendMonsterMove(x, y, z, false,true,1);
2217 m_caster->Attack(unitTarget);
2220 void Spell::EffectSummonCritter(uint32 i)
2222 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
2223 if(!pet_entry)
2224 return;
2225 Pet* critter = new Pet();
2227 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
2228 m_caster->GetMapId(),
2229 m_caster->GetPositionX(),m_caster->GetPositionY(),
2230 m_caster->GetPositionZ(),m_caster->GetOrientation(),
2231 m_spellInfo->EffectMiscValue[i]))
2233 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
2234 delete critter;
2235 return;
2238 critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
2239 critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID());
2240 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
2242 critter->AIM_Initialize();
2244 std::string name;
2245 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2246 name = ((Player*)m_caster)->GetName();
2247 else
2248 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
2249 name.append("'s Pet");
2250 critter->SetName( name );
2251 m_caster->SetPet(critter);
2252 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)critter);
2253 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2255 ((Player*)m_caster)->PetSpellInitialize();
2256 ((Player*)m_caster)->SavePet();
2260 void Spell::EffectSummonDeadPet(uint32 i)
2262 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2263 return;
2264 Player *_player = (Player*)m_caster;
2265 Creature *_pet = _player->GetPet();
2266 if(!_pet)
2267 return;
2268 if(_pet->isAlive())
2269 return;
2270 Pet *pet = (Pet*)_pet;
2271 pet->setDeathState( ALIVE );
2272 pet->clearUnitState(UNIT_STAT_ALL_STATE);
2273 pet->SetHealth( uint32(pet->GetMaxHealth()*damage/100));
2275 pet->AIM_Initialize();
2277 _player->PetSpellInitialize();
2278 _player->SavePet();
2281 void Spell::EffectTransmitted(uint32 i)
2283 float fx,fy;
2284 WorldPacket data;
2286 float min_dis = GetMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
2287 float max_dis = GetMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
2288 float diff = max_dis - min_dis + 1;
2289 float dis = (float)(rand()%(uint32)diff + (uint32)min_dis);
2291 fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
2292 fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
2294 float fz = MapManager::Instance ().GetMap(m_caster->GetMapId())->GetHeight(fx,fy);
2296 if(m_spellInfo->EffectMiscValue[i] == 35591)
2298 Map* map = MapManager::Instance().GetMap(m_caster->GetMapId());
2299 if ( map->IsUnderWater(fx,fy,fz) )
2301 SendCastResult(CAST_FAIL_CANT_BE_CAST_HERE);
2302 up_skillvalue = 4;
2303 SendChannelUpdate(0);
2304 return;
2308 GameObject* pGameObj = new GameObject();
2309 uint32 name_id = m_spellInfo->EffectMiscValue[i];
2311 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id,m_caster->GetMapId(),
2312 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0))
2314 delete pGameObj;
2315 return;
2318 pGameObj->SetUInt64Value(OBJECT_FIELD_CREATED_BY, m_caster->GetGUID() );
2319 pGameObj->SetUInt32Value(12, 0x3F63BB3C );
2320 pGameObj->SetUInt32Value(13, 0xBEE9E017 );
2321 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
2322 pGameObj->SetRespawnTimer(GetDuration(m_spellInfo));
2323 pGameObj->SetSpellId(m_spellInfo->Id);
2325 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
2326 //m_caster->AddGameObject(pGameObj);
2327 //m_ObjToDel.push_back(pGameObj);
2329 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
2330 pGameObj->AddToWorld();
2332 data.Initialize(SMSG_GAMEOBJECT_SPAWN_ANIM);
2333 data << uint64(pGameObj->GetGUID());
2334 m_caster->SendMessageToSet(&data,true);
2336 if(m_spellInfo->EffectMiscValue[i] == 35591)
2338 if( m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->CheckFishingAble() > 0)
2340 //pGameObj->SetUInt32Value(GAMEOBJECT_STATE, 0);
2341 //Orientation3
2342 pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
2343 //Orientation4
2344 pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
2345 data.Initialize(SMSG_GAMEOBJECT_CUSTOM_ANIM);
2346 data<<uint64(pGameObj->GetGUID());
2347 data<<uint8(0);
2348 ((Player*)m_caster)->GetSession()->SendPacket(&data);
2349 //need fixed produre of fishing.
2350 ((Player*)m_caster)->SendLoot(pGameObj->GetGUID(),LOOT_FISHING);
2351 SendChannelUpdate(0);
2356 void Spell::EffectSkill(uint32 i)
2358 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2359 return;
2361 // This hack like code, but another way get GO for prevent effect skill applying for partly looted go not found
2362 if(m_spellInfo->Effect[0]==33 && !m_targetGOs[0].empty())
2364 GameObject* go = m_targetGOs[0].front();
2366 if(!go->HaveLootSkill())
2367 return;
2369 go->SetLootSkill(false);
2372 Player *player = (Player*)m_caster;
2374 uint32 skill_id = m_spellInfo->EffectMiscValue[i];
2376 if(skill_id == SKILL_FISHING && up_skillvalue != 4)
2377 up_skillvalue = player->CheckFishingAble();
2378 if(skill_id == SKILL_SKINNING || skill_id == SKILL_FISHING
2379 || skill_id == SKILL_HERBALISM || skill_id == SKILL_MINING)
2381 switch(up_skillvalue)
2383 case 0:
2384 return;
2385 case 1:
2387 if(urand(1,100) <= 10)
2388 return;
2389 else break;
2391 case 2:
2393 if(urand(1,100) <= 40)
2394 return;
2395 else break;
2397 case 3:
2399 if(urand(1,100) <= 70)
2400 return;
2401 else break;
2403 case 4:
2404 default:return;
2407 player->UpdateSkill(skill_id);
2408 }else
2409 player->UpdateSkillPro(m_spellInfo->Id);