[3216] - Applied MaNGOS coding style (see trunk/bcpp.cfg).
[mangos-git.git] / src / game / SpellEffects.cpp
blob6a0d9af15533ea3c333a9e866d3a3c8edc3b4543
1 /*
2 * Copyright (C) 2005,2006,2007 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"
47 #include "GridNotifiers.h"
48 #include "GridNotifiersImpl.h"
50 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
52 &Spell::EffectNULL, //nothing
53 &Spell::EffectInstaKill, //SPELL_EFFECT_INSTAKILL = 1
54 &Spell::EffectSchoolDMG, //SPELL_EFFECT_SCHOOL_DAMAGE = 2
55 &Spell::EffectDummy, //SPELL_EFFECT_DUMMY = 3
56 &Spell::EffectNULL, //SPELL_EFFECT_PORTAL_TELEPORT = 4
57 &Spell::EffectTeleportUnits, //SPELL_EFFECT_TELEPORT_UNITS = 5
58 &Spell::EffectApplyAura, //SPELL_EFFECT_APPLY_AURA = 6
59 &Spell::EffectSchoolDMG, //SPELL_EFFECT_ENVIRONMENTAL_DAMAGE =7
60 &Spell::EffectManaDrain, //SPELL_EFFECT_MANA_DRAIN = 8
61 &Spell::EffectHealthLeach, //SPELL_EFFECT_HEALTH_LEECH = 9
62 &Spell::EffectHeal, //SPELL_EFFECT_HEAL = 10
63 &Spell::EffectNULL, //SPELL_EFFECT_BIND = 11
64 &Spell::EffectNULL, //SPELL_EFFECT_PORTAL = 12
65 &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_BASE = 13
66 &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_SPECIALIZE = 14
67 &Spell::EffectNULL, //SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15
68 &Spell::EffectQuestComplete, //SPELL_EFFECT_QUEST_COMPLETE = 16
69 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17
70 &Spell::EffectResurrect, //SPELL_EFFECT_RESURRECT = 18
71 &Spell::EffectNULL, //SPELL_EFFECT_ADD_EXTRA_ATTACKS = 19
72 &Spell::EffectNULL, //SPELL_EFFECT_DODGE = 20
73 &Spell::EffectNULL, //SPELL_EFFECT_EVADE = 21
74 &Spell::EffectParry, //SPELL_EFFECT_PARRY = 22
75 &Spell::EffectNULL, //SPELL_EFFECT_BLOCK = 23
76 &Spell::EffectCreateItem, //SPELL_EFFECT_CREATE_ITEM = 24
77 &Spell::EffectNULL, //SPELL_EFFECT_WEAPON = 25
78 &Spell::EffectNULL, //SPELL_EFFECT_DEFENSE = 26
79 &Spell::EffectPersistentAA, //SPELL_EFFECT_PERSISTENT_AREA_AURA = 27
80 &Spell::EffectSummon, //SPELL_EFFECT_SUMMON = 28
81 &Spell::EffectMomentMove, //SPELL_EFFECT_LEAP = 29
82 &Spell::EffectEnergize, //SPELL_EFFECT_ENERGIZE = 30
83 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_PERCENT_DAMAGE = 31
84 &Spell::EffectNULL, //SPELL_EFFECT_TRIGGER_MISSILE = 32 //Useless
85 &Spell::EffectOpenLock, //SPELL_EFFECT_OPEN_LOCK = 33
86 &Spell::EffectSummonChangeItem, //SPELL_EFFECT_SUMMON_CHANGE_ITEM = 34
87 &Spell::EffectApplyAA, //SPELL_EFFECT_APPLY_AREA_AURA = 35
88 &Spell::EffectLearnSpell, //SPELL_EFFECT_LEARN_SPELL = 36
89 &Spell::EffectNULL, //SPELL_EFFECT_SPELL_DEFENSE = 37 //Useless
90 &Spell::EffectDispel, //SPELL_EFFECT_DISPEL = 38
91 &Spell::EffectNULL, //SPELL_EFFECT_LANGUAGE = 39
92 &Spell::EffectDualWield, //SPELL_EFFECT_DUAL_WIELD = 40
93 &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_WILD = 41
94 &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_GUARDIAN = 42
95 &Spell::EffectTeleUnitsFaceCaster, //SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER = 43
96 &Spell::EffectLearnSkill, //SPELL_EFFECT_SKILL_STEP = 44
97 &Spell::EffectNULL, //unknown45 = 45
98 &Spell::EffectNULL, //SPELL_EFFECT_SPAWN = 46
99 &Spell::EffectTradeSkill, //SPELL_EFFECT_TRADE_SKILL = 47
100 &Spell::EffectNULL, //SPELL_EFFECT_STEALTH = 48 //Useless
101 &Spell::EffectNULL, //SPELL_EFFECT_DETECT = 49
102 &Spell::EffectTransmitted, //SPELL_EFFECT_TRANS_DOOR = 50
103 &Spell::EffectNULL, //SPELL_EFFECT_FORCE_CRITICAL_HIT = 51 //Useless
104 &Spell::EffectNULL, //SPELL_EFFECT_GUARANTEE_HIT = 52
105 &Spell::EffectEnchantItemPerm, //SPELL_EFFECT_ENCHANT_ITEM = 53
106 &Spell::EffectEnchantItemTmp, //SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54
107 &Spell::EffectTameCreature, //SPELL_EFFECT_TAMECREATURE = 55
108 &Spell::EffectSummonPet, //SPELL_EFFECT_SUMMON_PET = 56
109 &Spell::EffectLearnPetSpell, //SPELL_EFFECT_LEARN_PET_SPELL = 57
110 &Spell::EffectWeaponDmg, //SPELL_EFFECT_WEAPON_DAMAGE = 58
111 &Spell::EffectOpenSecretSafe, //SPELL_EFFECT_OPEN_LOCK_ITEM = 59
112 &Spell::EffectProficiency, //SPELL_EFFECT_PROFICIENCY = 60
113 &Spell::EffectSendEvent, //SPELL_EFFECT_SEND_EVENT = 61
114 &Spell::EffectPowerDrain, //SPELL_EFFECT_POWER_BURN = 62
115 &Spell::EffectThreat, //SPELL_EFFECT_THREAT = 63
116 &Spell::EffectTriggerSpell, //SPELL_EFFECT_TRIGGER_SPELL = 64
117 &Spell::EffectNULL, //SPELL_EFFECT_HEALTH_FUNNEL = 65 //Useless
118 &Spell::EffectNULL, //SPELL_EFFECT_POWER_FUNNEL = 66 //Useless
119 &Spell::EffectHealMaxHealth, //SPELL_EFFECT_HEAL_MAX_HEALTH = 67
120 &Spell::EffectInterruptCast, //SPELL_EFFECT_INTERRUPT_CAST = 68
121 &Spell::EffectNULL, //SPELL_EFFECT_DISTRACT = 69
122 &Spell::EffectNULL, //SPELL_EFFECT_PULL = 70
123 &Spell::EffectPickPocket, //SPELL_EFFECT_PICKPOCKET = 71
124 &Spell::EffectNULL, //SPELL_EFFECT_ADD_FARSIGHT = 72
125 &Spell::EffectSummonWild, //SPELL_EFFECT_SUMMON_POSSESSED = 73
126 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_TOTEM = 74 //Useless
127 &Spell::EffectNULL, //SPELL_EFFECT_HEAL_MECHANICAL = 75
128 &Spell::EffectSummonObjectWild, //SPELL_EFFECT_SUMMON_OBJECT_WILD = 76
129 &Spell::EffectScriptEffect, //SPELL_EFFECT_SCRIPT_EFFECT = 77
130 &Spell::EffectNULL, //SPELL_EFFECT_ATTACK = 78 //Useless
131 &Spell::EffectSanctuary, //SPELL_EFFECT_SANCTUARY = 79
132 &Spell::EffectAddComboPoints, //SPELL_EFFECT_ADD_COMBO_POINTS = 80
133 &Spell::EffectNULL, //SPELL_EFFECT_CREATE_HOUSE = 81
134 &Spell::EffectNULL, //SPELL_EFFECT_BIND_SIGHT = 82
135 &Spell::EffectDuel, //SPELL_EFFECT_DUEL = 83
136 &Spell::EffectNULL, //SPELL_EFFECT_STUCK = 84
137 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_PLAYER = 85
138 &Spell::EffectNULL, //SPELL_EFFECT_ACTIVATE_OBJECT = 86
139 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87
140 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88
141 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89
142 &Spell::EffectSummonTotem, //SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90
143 &Spell::EffectNULL, //SPELL_EFFECT_THREAT_ALL = 91
144 &Spell::EffectEnchantHeldItem, //SPELL_EFFECT_ENCHANT_HELD_ITEM = 92
145 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_PHANTASM = 93
146 &Spell::EffectSelfResurrect, //SPELL_EFFECT_SELF_RESURRECT = 94
147 &Spell::EffectSkinning, //SPELL_EFFECT_SKINNING = 95
148 &Spell::EffectCharge, //SPELL_EFFECT_CHARGE = 96
149 &Spell::EffectSummonCritter, //SPELL_EFFECT_SUMMON_CRITTER = 97
150 &Spell::EffectKnockBack, //SPELL_EFFECT_KNOCK_BACK = 98
151 &Spell::EffectDisEnchant, //SPELL_EFFECT_DISENCHANT = 99
152 &Spell::EffectInebriate, //SPELL_EFFECT_INEBRIATE = 100
153 &Spell::EffectFeedPet, //SPELL_EFFECT_FEED_PET = 101
154 &Spell::EffectDismissPet, //SPELL_EFFECT_DISMISS_PET = 102
155 &Spell::EffectReputation, //SPELL_EFFECT_REPUTATION = 103
156 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104
157 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105
158 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106
159 &Spell::EffectSummonObject, //SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107
160 &Spell::EffectNULL, //SPELL_EFFECT_DISPEL_MECHANIC = 108
161 &Spell::EffectSummonDeadPet, //SPELL_EFFECT_SUMMON_DEAD_PET = 109
162 &Spell::EffectNULL, //SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110
163 &Spell::EffectNULL, //SPELL_EFFECT_DURABILITY_DAMAGE = 111
164 &Spell::EffectNULL, //SPELL_EFFECT_SUMMON_DEMON = 112
165 &Spell::EffectResurrectNew, //SPELL_EFFECT_RESURRECT_NEW = 113
166 &Spell::EffectAttackMe, //SPELL_EFFECT_ATTACK_ME = 114
167 &Spell::EffectNULL, //SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115
168 &Spell::EffectNULL, //SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116
169 &Spell::EffectNULL, //SPELL_EFFECT_SPIRIT_HEAL = 117
170 &Spell::EffectSkill, //SPELL_EFFECT_SKILL = 118 -- professions and more
171 &Spell::EffectNULL, //SPELL_EFFECT_APPLY_AURA_NEW = 119
172 &Spell::EffectNULL, //SPELL_EFFECT_TELEPORT_GRAVEYARD = 120
173 &Spell::EffectWeaponDmg //SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121
176 void Spell::EffectNULL(uint32 i)
178 sLog.outDebug("WORLD: Spell Effect DUMMY");
181 void Spell::EffectResurrectNew(uint32 i)
183 if(!unitTarget) return;
184 if(unitTarget->GetTypeId() != TYPEID_PLAYER) return;
185 if(unitTarget->isAlive()) return;
186 if(!unitTarget->IsInWorld()) return;
188 uint32 health = m_spellInfo->EffectBasePoints[i]+1;
189 uint32 mana = m_spellInfo->EffectMiscValue[i];
190 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
191 SendResurrectRequest((Player*)unitTarget);
194 void Spell::EffectInstaKill(uint32 i)
196 if( unitTarget && unitTarget->isAlive() )
198 uint32 health = unitTarget->GetHealth();
199 m_caster->DealDamage(unitTarget, health, DIRECT_DAMAGE, 0, NULL, 0, false);
203 void Spell::EffectSchoolDMG(uint32 i)
205 if( unitTarget && unitTarget->isAlive() && damage >= 0)
206 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell);
208 if (m_caster->GetTypeId()==TYPEID_PLAYER && m_spellInfo->Attributes == 0x150010)
209 m_caster->AttackStop();
212 void Spell::EffectDummy(uint32 i)
214 if(!unitTarget)
215 return;
217 // More spell specific code in begining
218 if( m_spellInfo->Id == SPELL_ID_AGGRO )
220 if( !unitTarget || !m_caster || !m_caster->getVictim() )
221 return;
223 // only creature to creature
224 if( unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_UNIT )
225 return;
227 // if creature not figthing currently
228 if( unitTarget->isInCombat() )
229 return;
231 // skip non hostile to caster enemy creatures
232 if( !((Creature*)unitTarget)->IsHostileTo(m_caster->getVictim()) )
233 return;
235 // only from same creature faction
236 if(unitTarget->getFaction() != m_caster->getFaction() )
237 return;
239 ((Creature*)m_caster)->SetNoCallAssistence(true);
240 ((Creature*)unitTarget)->SetNoCallAssistence(true);
241 ((Creature*)unitTarget)->AI().AttackStart(m_caster->getVictim());
242 return;
245 // Preparation Rogue - immediately finishes the cooldown on other Rogue abilities
246 if(m_spellInfo->Id == 14185)
248 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
249 return;
251 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
252 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
254 uint32 classspell = itr->first;
255 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
257 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->Id != 14185 &&
258 (spellInfo->RecoveryTime > 0 || spellInfo->CategoryRecoveryTime > 0))
260 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
262 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4));
263 data << classspell;
264 data << m_caster->GetGUID();
265 data << uint32(0);
266 ((Player*)m_caster)->GetSession()->SendPacket(&data);
269 return;
272 // Cold Snap - immediately finishes the cooldown on Frost spells
273 if(m_spellInfo->Id == 12472)
275 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
276 return;
278 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
279 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
281 if (itr->second->state == PLAYERSPELL_REMOVED) continue;
282 uint32 classspell = itr->first;
283 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
285 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && spellInfo->School == SPELL_SCHOOL_FROST && spellInfo->Id != 12472 &&
286 (spellInfo->RecoveryTime > 0 || spellInfo->CategoryRecoveryTime > 0))
288 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
290 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4));
291 data << classspell;
292 data << m_caster->GetGUID();
293 data << uint32(0);
294 ((Player*)m_caster)->GetSession()->SendPacket(&data);
297 return;
300 // If spell cannibalize and his casted, check special requirements and cast aura Cannibalize is all ok
301 if(m_spellInfo->Id == 20577)
303 // non-standard cast requirement check
304 SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
305 float max_range = GetMaxRange(srange);
307 CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
308 Cell cell = RedZone::GetZone(p);
309 cell.data.Part.reserved = ALL_DISTRICT;
310 cell.SetNoCreate();
312 Unit* result = NULL;
314 MaNGOS::CannibalizeUnitCheck u_check(m_caster, max_range);
315 MaNGOS::UnitSearcher<MaNGOS::CannibalizeUnitCheck> searcher(result, u_check);
317 TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::CannibalizeUnitCheck>, TypeMapContainer<AllObjectTypes> > unit_searcher(searcher);
318 CellLock<GridReadGuard> cell_lock(cell, p);
319 cell_lock->Visit(cell_lock, unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId()));
321 if (!result)
323 // clear cooldown at fail
324 if(m_caster->GetTypeId()==TYPEID_PLAYER)
326 ((Player*)m_caster)->RemoveSpellCooldown(20577);
328 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4));
329 data << uint32(20577); // spell id
330 data << m_caster->GetGUID();
331 data << uint32(0);
332 ((Player*)m_caster)->GetSession()->SendPacket(&data);
335 SendCastResult(CAST_FAIL_NO_NEARBY_CORPSES_TO_EAT);
336 return;
339 // ok, main function spell can be casted
341 finish(); // prepere to replacing this cpell cast to main function spell
343 // casting
344 SpellEntry const *spellInfo = sSpellStore.LookupEntry( 20578 );
345 Spell *spell = new Spell(m_caster, spellInfo, false, 0);
346 if(!spellInfo)
348 sLog.outError("WORLD: unknown spell id %i\n", 20578);
349 return;
352 SpellCastTargets targets;
353 targets.setUnitTarget(m_caster);
354 spell->prepare(&targets);
355 return;
358 // More generic code later
360 // starshards/curse of agony hack .. this applies to 1.10 only
361 if (m_triggeredByAura)
363 SpellEntry const *trig_info = m_triggeredByAura->GetSpellProto();
364 if ((trig_info->SpellIconID == 1485 && trig_info->SpellFamilyName == SPELLFAMILY_PRIEST) ||
365 (trig_info->SpellIconID == 544 && trig_info->SpellFamilyName == SPELLFAMILY_WARLOCK))
367 Unit *tmpTarget = unitTarget;
368 unitTarget = m_triggeredByAura->GetTarget();
369 damage = trig_info->EffectBasePoints[i]+1;
370 EffectSchoolDMG(i);
371 unitTarget = tmpTarget;
375 //Holy Shock For Paladins
376 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellIconID == 156)
378 int hurt = 0;
379 int heal = 0;
381 switch(m_spellInfo->Id)
383 case 20473:
384 hurt = 25912;
385 heal = 25914;
386 break;
387 case 20929:
388 hurt = 25911;
389 heal = 25913;
390 break;
391 case 20930:
392 hurt = 25902;
393 heal = 25903;
394 break;
395 default:
396 break;
399 if(m_caster->IsFriendlyTo(unitTarget))
400 m_caster->CastSpell(unitTarget, heal, true, 0);
401 else
402 m_caster->CastSpell(unitTarget, hurt, true, 0);
405 if(m_spellInfo->SpellIconID == 1648)
407 int32 dmg = damage;
408 dmg += int32(m_caster->GetPower(POWER_RAGE)/10 * objmgr.GetSpellRank(m_spellInfo->Id)*3);
409 SpellEntry const *tspellInfo = sSpellStore.LookupEntry(20647);
410 SpellEntry sInfo = *tspellInfo;
411 sInfo.EffectBasePoints[0] = dmg;
412 m_caster->CastSpell(unitTarget, &sInfo, true, 0);
413 m_caster->SetPower(POWER_RAGE,0);
416 //Life Tap
417 if(m_spellInfo->SpellVisual == 1225 && m_spellInfo->SpellIconID == 208)
419 int32 mod = m_spellInfo->EffectBasePoints[0]+1;
420 if(m_caster)
422 if(m_caster->GetHealth()>mod)
424 m_caster->ModifyHealth(-mod);
425 m_caster->ModifyPower(POWER_MANA,mod);
431 void Spell::EffectTriggerSpell(uint32 i)
433 SpellEntry const *spellInfo = sSpellStore.LookupEntry( m_spellInfo->EffectTriggerSpell[i] );
435 if(!spellInfo)
437 sLog.outError("WORLD: unknown spell id %i\n", m_spellInfo->EffectTriggerSpell[i]);
438 return;
441 m_TriggerSpell.push_back(spellInfo);
444 void Spell::EffectTeleportUnits(uint32 i)
446 if(!unitTarget)
447 return;
448 HandleTeleport(m_spellInfo->Id,unitTarget);
451 void Spell::EffectApplyAura(uint32 i)
453 if(!unitTarget)
454 return;
455 if(!unitTarget->isAlive())
456 return;
458 //If m_immuneToState type contain this aura type, IMMUNE aura.
459 if(unitTarget->IsImmunedToSpellEffect(m_spellInfo->EffectApplyAuraName[i]))
461 SendCastResult(CAST_FAIL_IMMUNE);
462 return;
465 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
467 Aura* Aur = new Aura(m_spellInfo, i, unitTarget,m_caster, m_CastItem);
469 if (!Aur->IsPositive() && Aur->GetCasterGUID() != Aur->GetTarget()->GetGUID())
471 switch (Aur->GetModifier()->m_auraname)
473 case SPELL_AURA_MOD_DETECT_RANGE:
474 case SPELL_AURA_AURAS_VISIBLE:
475 case SPELL_AURA_MOD_CHARM:
476 break;
477 default:
478 if(Aur->GetTarget()->GetTypeId() == TYPEID_UNIT && !Aur->GetTarget()->isInCombat())
479 ((Creature*)Aur->GetTarget())->AI().AttackStart(m_caster);
480 else
482 m_caster->Attack(Aur->GetTarget());
483 m_caster->SetInCombat();
484 Aur->GetTarget()->SetInCombat();
489 bool added = unitTarget->AddAura(Aur);
491 if (added)
493 // Check for Power Word: Shield
494 // TODO Make a way so it works for every related spell!
495 if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players
497 // This should cover all Power Word: Shield spells
498 if ((m_spellInfo->SpellVisual == 784) && (m_spellInfo->SpellIconID == 566))
500 // Weakened Soul
501 SpellEntry const *WeakenedSoulSpellInfo = sSpellStore.LookupEntry( 6788 );
502 Aura* WeakenedSoulAura = new Aura(WeakenedSoulSpellInfo, 0, unitTarget,m_caster, 0);
503 unitTarget->AddAura(WeakenedSoulAura, 0);
504 sLog.outDebug("Spell: Additinal Aura is: %u", WeakenedSoulSpellInfo->EffectApplyAuraName[i]);
508 if(Aur->IsTrigger())
510 // arcane missiles
511 SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
512 if (!spellInfo) return;
513 if (spellInfo->EffectImplicitTargetA[0] == TARGET_SINGLE_ENEMY && m_caster->GetTypeId() == TYPEID_PLAYER)
515 Unit *target = ObjectAccessor::Instance().GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
516 if (target)
518 if (!m_caster->IsFriendlyTo(target))
519 Aur->SetTarget(target);
520 else
521 cancel();
523 else
524 cancel();
530 void Spell::EffectManaDrain(uint32 i)
532 if(m_spellInfo->EffectMiscValue[i] > 4)
533 return;
535 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
537 if(!unitTarget)
538 return;
539 if(!unitTarget->isAlive())
540 return;
541 if(unitTarget->getPowerType() != drain_power)
542 return;
543 if(damage < 0)
544 return;
546 uint32 curPower = unitTarget->GetPower(drain_power);
547 float tmpvalue = m_spellInfo->EffectMultipleValue[i];
548 if(!tmpvalue)
549 tmpvalue = 1;
551 int32 new_damage;
552 if(curPower < uint32(damage))
553 new_damage = curPower;
554 else
555 new_damage = damage;
557 unitTarget->ModifyPower(drain_power,-new_damage);
559 if(drain_power == POWER_MANA)
560 m_caster->ModifyPower(POWER_MANA,uint32(new_damage*tmpvalue));
563 void Spell::EffectSendEvent(uint32 i)
565 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, focusObject);
568 void Spell::EffectPowerDrain(uint32 i)
570 if(!unitTarget)
571 return;
572 if(!unitTarget->isAlive())
573 return;
574 if(unitTarget->getPowerType()!=POWER_MANA)
575 return;
576 if(damage < 0)
577 return;
579 uint32 curPower = unitTarget->GetPower(POWER_MANA);
581 int32 new_damage;
582 if(curPower < uint32(damage))
583 new_damage = curPower;
584 else
585 new_damage = damage;
587 int32 tmpvalue = int32(new_damage*m_spellInfo->EffectMultipleValue[i]);
589 unitTarget->ModifyPower(POWER_MANA,-new_damage);
591 m_caster->ModifyPower(POWER_MANA,tmpvalue);
592 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage/2, m_IsTriggeredSpell);
596 void Spell::EffectHeal( uint32 i )
598 if( unitTarget && unitTarget->isAlive() && damage >= 0)
600 int32 addhealth = m_caster->SpellHealingBonus(m_spellInfo, uint32(damage));
601 bool crit = m_caster->SpellCriticalBonus(m_spellInfo, &addhealth);
602 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
603 SendHealSpellOnPlayer(((Player*)unitTarget), m_spellInfo->Id, addhealth, crit);
605 unitTarget->ModifyHealth( addhealth );
607 uint32 procHealer = PROC_FLAG_HEAL;
608 if (crit)
609 procHealer |= PROC_FLAG_CRIT_HEAL;
610 if (m_caster != unitTarget)
611 m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_NONE,addhealth,m_spellInfo,m_IsTriggeredSpell);
615 void Spell::EffectHealthLeach(uint32 i)
617 if(!unitTarget)
618 return;
619 if(!unitTarget->isAlive())
620 return;
622 if(damage < 0)
623 return;
625 sLog.outDebug("HealthLeach :%i", damage);
627 uint32 curHealth = unitTarget->GetHealth();
629 int32 new_damage;
630 if(curHealth < uint32(damage))
631 new_damage = curHealth;
632 else
633 new_damage = damage;
635 int32 tmpvalue = int32(new_damage*m_spellInfo->EffectMultipleValue[i]);
637 m_caster->ModifyHealth(tmpvalue);
639 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
640 SendHealSpellOnPlayer(((Player*)unitTarget), m_spellInfo->Id, uint32(tmpvalue));
642 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell);
645 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
647 if (m_caster->GetTypeId() != TYPEID_PLAYER)
648 return;
650 Player* player = (Player*)m_caster;
652 uint32 newitemid = itemtype;
653 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
654 if(!pProto)
656 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
657 return;
660 uint32 num_to_add;
662 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
663 num_to_add = max(m_spellInfo->EffectBasePoints[i]+1, 1);
664 else if(player->getLevel() >= m_spellInfo->spellLevel)
665 num_to_add = ((player->getLevel() - (m_spellInfo->spellLevel-1))*2);
666 else
667 num_to_add = 2;
669 uint16 dest;
670 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, false);
671 if( msg != EQUIP_ERR_OK )
673 player->SendEquipError( msg, NULL, NULL );
674 return;
677 Item *pItem = player->StoreNewItem( dest, newitemid, num_to_add, true);
679 if(!pItem)
681 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
682 return;
685 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE )
686 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
688 player->SendNewItem(pItem, num_to_add, true, true);
689 player->UpdateCraftSkill(m_spellInfo->Id);
692 void Spell::EffectCreateItem(uint32 i)
694 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
697 void Spell::EffectPersistentAA(uint32 i)
699 float radius = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
700 int32 duration = GetDuration(m_spellInfo);
701 DynamicObject* dynObj = new DynamicObject();
702 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))
704 delete dynObj;
705 return;
707 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
708 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
709 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
710 m_caster->AddDynObject(dynObj);
711 dynObj->AddToWorld();
712 MapManager::Instance().GetMap(dynObj->GetMapId())->Add(dynObj);
716 void Spell::EffectEnergize(uint32 i)
718 if(!unitTarget)
719 return;
720 if(!unitTarget->isAlive())
721 return;
723 if(m_spellInfo->EffectMiscValue[i] > 4)
724 return;
726 if(damage < 0)
727 return;
729 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
731 if(unitTarget->getPowerType() != power)
732 return;
734 unitTarget->ModifyPower(power,damage);
737 void Spell::EffectOpenLock(uint32 i)
740 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
742 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
743 return;
746 Player* player = (Player*)m_caster;
748 LootType loottype = LOOT_CORPSE;
749 uint32 lockId = 0;
750 uint64 guid = 0;
752 // Get lockId
753 if(gameObjTarget)
755 lockId = gameObjTarget->GetGOInfo()->sound0;
756 guid = gameObjTarget->GetGUID();
758 else if(itemTarget)
760 lockId = itemTarget->GetProto()->LockID;
761 guid = itemTarget->GetGUID();
763 else
765 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
766 return;
769 if(!lockId) // possible case for GO and maybe for items.
771 player->SendLoot(guid,loottype);
772 return;
775 // Get LockInfo
776 LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
778 if (!lockInfo)
780 sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
781 (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
782 SendCastResult(CAST_FAIL_INVALID_TARGET);
783 return;
786 // check key
787 if(lockInfo->key && m_CastItem && m_CastItem->GetEntry()==lockInfo->key)
789 player->SendLoot(guid,loottype);
790 return;
793 uint32 SkillId = 0;
794 // Check and skill-up skill
795 if(m_spellInfo->Effect[1]==SPELL_EFFECT_SKILL)
796 SkillId = m_spellInfo->EffectMiscValue[1];
797 else
798 if(m_spellInfo->EffectMiscValue[0]==1) // picklocking spells
799 SkillId = SKILL_LOCKPICKING;
801 // skill bonus provided by casting spell (mostly item spells)
802 uint32 spellSkillBonus = uint32(m_spellInfo->EffectBasePoints[0]+1);
804 uint32 reqSkillValue = lockInfo->requiredskill;
806 if(lockInfo->requiredlockskill) // required pick lock skill applying
808 if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
810 SendCastResult(CAST_FAIL_FIZZLED);
811 return;
814 reqSkillValue = lockInfo->requiredlockskill;
816 else
817 if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
819 SendCastResult(CAST_FAIL_INVALID_TARGET);
820 return;
823 if ( SkillId )
825 loottype = LOOT_SKINNING;
826 if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
828 SendCastResult(CAST_FAIL_SKILL_NOT_HIGH_ENOUGH);
829 return;
832 // update skill if really known
833 uint32 SkillValue = player->GetPureSkillValue(SkillId);
834 if(SkillValue) // non only item base skill
836 if(gameObjTarget)
838 // Allow one skill-up until respawned
839 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
840 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
841 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
843 else if(itemTarget)
845 // Do one skill-up
846 uint32 SkillValue = player->GetPureSkillValue(SkillId);
847 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
852 // Send loot
853 player->SendLoot(guid,loottype);
856 void Spell::EffectSummonChangeItem(uint32 i)
858 if(m_caster->GetTypeId() != TYPEID_PLAYER)
859 return;
861 Player *player = (Player*)m_caster;
863 // applied only to using item
864 if(!m_CastItem)
865 return;
867 // ... only to item in own inventory/bank/equip_slot
868 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
869 return;
871 uint32 newitemid = m_spellInfo->EffectItemType[i];
872 if(!newitemid)
873 return;
875 uint16 pos = (m_CastItem->GetBagSlot() << 8) | m_CastItem->GetSlot();
877 Item *pNewItem = player->CreateItem( newitemid, 1 );
878 if( !pNewItem )
879 return;
881 uint16 dest;
882 uint8 msg;
884 if( player->IsInventoryPos( pos ) )
886 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
887 if( msg == EQUIP_ERR_OK )
889 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
890 player->StoreItem( dest, pNewItem, true);
891 return;
894 else if( player->IsBankPos ( pos ) )
896 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
897 if( msg == EQUIP_ERR_OK )
899 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
900 player->BankItem( dest, pNewItem, true);
901 return;
904 else if( player->IsEquipmentPos ( pos ) )
906 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
907 if( msg == EQUIP_ERR_OK )
909 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
910 player->EquipItem( dest, pNewItem, true);
911 return;
915 // fail
916 delete pNewItem;
919 void Spell::EffectOpenSecretSafe(uint32 i)
921 EffectOpenLock(i); //no difference for now
924 void Spell::EffectProficiency(uint32 i)
926 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
927 return;
928 Player *p_target = (Player*)unitTarget;
930 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
931 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
933 p_target->AddWeaponProficiency(subClassMask);
934 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
936 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
938 p_target->AddArmorProficiency(subClassMask);
939 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
943 void Spell::EffectApplyAA(uint32 i)
945 if(!unitTarget)
946 return;
947 if(!unitTarget->isAlive())
948 return;
950 AreaAura* Aur = new AreaAura(m_spellInfo, i, unitTarget, m_caster);
951 unitTarget->AddAura(Aur);
954 void Spell::EffectSummon(uint32 i)
956 if(m_caster->GetPetGUID())
957 return;
959 if(!unitTarget)
960 return;
961 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
962 if(!pet_entry)
963 return;
964 uint32 level = m_caster->getLevel();
965 Pet* spawnCreature = new Pet(SUMMON_PET);
967 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
968 m_caster->GetMapId(),
969 m_caster->GetPositionX(),m_caster->GetPositionY(),
970 m_caster->GetPositionZ(),m_caster->GetOrientation(),
971 m_spellInfo->EffectMiscValue[i]))
973 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
974 delete spawnCreature;
975 return;
978 spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
979 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
980 spawnCreature->setPowerType(POWER_MANA);
981 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
982 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
983 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
984 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
985 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
986 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
987 spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
989 spawnCreature->InitStatsForLevel(level);
991 spawnCreature->AIM_Initialize();
993 std::string name;
994 if(m_caster->GetTypeId() == TYPEID_PLAYER)
995 name = ((Player*)m_caster)->GetName();
996 else
997 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
998 name.append(petTypeSuffix[spawnCreature->getPetType()]);
999 spawnCreature->SetName( name );
1001 spawnCreature->AddToWorld();
1002 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)spawnCreature);
1004 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1006 m_caster->SetPet(spawnCreature);
1007 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
1008 ((Player*)m_caster)->PetSpellInitialize();
1012 void Spell::EffectLearnSpell(uint32 i)
1014 if(!unitTarget)
1015 return;
1017 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1019 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1021 Creature *pet = m_caster->GetPet();
1023 if( !pet || !pet->isPet() || pet!=unitTarget || !pet->isAlive() )
1024 return;
1026 EffectLearnPetSpell(i);
1028 return;
1031 Player *player = (Player*)unitTarget;
1033 uint32 spellToLearn = m_spellInfo->EffectTriggerSpell[i];
1034 //data.Initialize(SMSG_LEARNED_SPELL);
1035 //data << spellToLearn;
1036 //player->GetSession()->SendPacket(&data);
1037 player->learnSpell((uint16)spellToLearn);
1038 //some addspell isn't needed if you have a good DB,FISHING && MINING && HERBALISM have to be needed.
1039 switch(spellToLearn)
1041 case 4036: //SKILL_ENGINERING
1043 player->learnSpell(3918);
1044 player->learnSpell(3919);
1045 player->learnSpell(3920);
1046 break;
1048 case 3908: //SKILL_TAILORING
1050 player->learnSpell(2387);
1051 player->learnSpell(2963);
1052 break;
1054 case 7411: //SKILL_ENCHANTING
1056 player->learnSpell(7418);
1057 player->learnSpell(7421);
1058 player->learnSpell(13262);
1059 break;
1061 case 2259: //SKILL_ALCHEMY
1063 player->learnSpell(2329);
1064 player->learnSpell(7183);
1065 player->learnSpell(2330);
1066 break;
1068 case 2018: //SKILL_BLACKSMITHING
1070 player->learnSpell(2663);
1071 player->learnSpell(12260);
1072 player->learnSpell(2660);
1073 player->learnSpell(3115);
1074 break;
1076 case 2108: //SKILL_LEATHERWORKING
1078 player->learnSpell(2152);
1079 player->learnSpell(9058);
1080 player->learnSpell(9059);
1081 player->learnSpell(2149);
1082 player->learnSpell(7126);
1083 player->learnSpell(2881);
1084 break;
1086 case 2550: //SKILL_COOKING
1088 player->learnSpell(818);
1089 player->learnSpell(2540);
1090 player->learnSpell(2538);
1091 player->learnSpell(8604);
1092 break;
1094 case 3273: //SKILL_FIRST_AID
1096 player->learnSpell(3275);
1097 break;
1099 case 7620: //SKILL_FISHING
1101 player->learnSpell(7738);
1102 break;
1104 case 2575: //SKILL_MINING
1106 player->learnSpell(2580);
1107 player->learnSpell(2656);
1108 player->learnSpell(2657);
1109 break;
1111 case 2366: //SKILL_HERBALISM
1113 player->learnSpell(2383);
1114 break;
1116 case 264: //SKILL_BOWS
1118 if(!player->HasSpell(75))
1119 player->learnSpell(2480);
1120 break;
1122 case 266: //SKILL_GUNS
1124 if(!player->HasSpell(75))
1125 player->learnSpell(7918);
1126 break;
1128 case 5011: //SKILL_CROSSBOWS
1130 if(!player->HasSpell(75))
1131 player->learnSpell(7919);
1132 break;
1134 case 2567: //SKILL_THROWN
1136 player->learnSpell(2764);
1137 break;
1139 case 2842: //SKILL_POISONS
1141 player->learnSpell(8681);
1142 break;
1144 default:break;
1146 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
1149 void Spell::EffectDispel(uint32 i)
1151 m_caster->RemoveFirstAuraByDispel(m_spellInfo->EffectMiscValue[i]);
1154 void Spell::EffectDualWield(uint32 i)
1156 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
1157 ((Player*)unitTarget)->SetCanDualWield(true);
1160 void Spell::EffectPickPocket(uint32 i)
1162 if( m_caster->GetTypeId() != TYPEID_PLAYER )
1163 return;
1165 //victim must be creature and attackable
1166 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
1167 return;
1169 //victim have to be alive and humanoid or undead
1170 if( unitTarget->isAlive() &&
1171 (((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_HUMANOID ||
1172 ((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_UNDEAD))
1174 int chance = 10 + m_caster->getLevel() - unitTarget->getLevel();
1176 if ( ( rand() % 20 ) <= chance )
1178 //Stealing successfull
1179 //sLog.outDebug("Sending loot from pickpocket");
1180 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOKETING);
1182 else
1184 //Reveal action + get attack
1185 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
1186 ((Creature*)unitTarget)->AI().AttackStart(m_caster);
1191 void Spell::EffectSummonWild(uint32 i)
1193 if(!unitTarget)
1194 return;
1195 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
1196 if(!pet_entry)
1197 return;
1199 Pet* old_wild = NULL;
1202 CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1203 Cell cell = RedZone::GetZone(p);
1204 cell.data.Part.reserved = ALL_DISTRICT;
1205 cell.SetNoCreate();
1207 PetWithIdCheck u_check(m_caster, pet_entry);
1208 MaNGOS::UnitSearcher<PetWithIdCheck> checker((Unit*&)old_wild, u_check);
1209 TypeContainerVisitor<MaNGOS::UnitSearcher<PetWithIdCheck>, TypeMapContainer<AllObjectTypes> > object_checker(checker);
1210 CellLock<GridReadGuard> cell_lock(cell, p);
1211 cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId()));
1214 if (old_wild) // find old critter, unsummon
1216 old_wild->Remove(PET_SAVE_AS_DELETED);
1217 return;
1219 else // in another case summon new
1222 uint32 level = m_caster->getLevel();
1224 // level of pet summoned using engineering item based at engineering skill level
1225 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
1227 ItemPrototype const *proto = m_CastItem->GetProto();
1228 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
1230 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
1231 if(skill202)
1233 level = skill202/5;
1238 Pet* spawnCreature = new Pet(GUARDIAN_PET);
1240 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
1241 m_caster->GetMapId(),
1242 m_caster->GetPositionX(),m_caster->GetPositionY(),
1243 m_caster->GetPositionZ(),m_caster->GetOrientation(),
1244 m_spellInfo->EffectMiscValue[i]))
1246 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
1247 delete spawnCreature;
1248 return;
1251 spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
1252 spawnCreature->setPowerType(POWER_MANA);
1253 spawnCreature->SetPower( POWER_MANA,28 + 10 * level);
1254 spawnCreature->SetMaxPower(POWER_MANA,28 + 10 * level);
1255 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
1256 spawnCreature->SetHealth( 28 + 30*level);
1257 spawnCreature->SetMaxHealth( 28 + 30*level);
1258 spawnCreature->SetLevel(level);
1259 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1260 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
1261 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
1262 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
1263 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1264 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1265 spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1267 spawnCreature->SetArmor(level*50);
1268 spawnCreature->AIM_Initialize();
1270 std::string name;
1271 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1272 name = ((Player*)m_caster)->GetName();
1273 else
1274 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
1275 name.append(petTypeSuffix[spawnCreature->getPetType()]);
1276 spawnCreature->SetName( name );
1278 spawnCreature->AddToWorld();
1279 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)spawnCreature);
1281 guardians and wilds can't be controled
1282 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1284 m_caster->SetPet(spawnCreature);
1285 ((Player*)m_caster)->PetSpellInitialize();
1286 ((Player*)m_caster)->SavePet();
1292 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
1294 if(!unitTarget)
1295 return;
1297 if(unitTarget->isInFlight())
1298 return;
1300 uint32 mapid = m_caster->GetMapId();
1301 float dis = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
1302 float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
1303 float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
1304 // teleport a bit above terrainlevel to avoid falling below it
1305 float fz = MapManager::Instance ().GetMap(mapid)->GetHeight(fx,fy) + 1.5;
1307 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1308 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), false);
1309 else
1310 MapManager::Instance().GetMap(mapid)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
1313 void Spell::EffectLearnSkill(uint32 i)
1315 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1316 return;
1317 if(damage < 0)
1318 return;
1320 uint32 skillid = m_spellInfo->EffectMiscValue[i];
1321 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
1322 ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,damage*75);
1325 void Spell::EffectTradeSkill(uint32 i)
1327 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1328 return;
1329 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
1330 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
1331 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
1334 void Spell::EffectEnchantItemPerm(uint32 i)
1336 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1337 return;
1338 if (!itemTarget)
1339 return;
1341 Player* p_caster = (Player*)m_caster;
1343 p_caster->UpdateCraftSkill(m_spellInfo->Id);
1345 if (m_spellInfo->EffectMiscValue[i])
1347 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
1349 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1350 if(!pEnchant)
1351 return;
1353 // item can be in trade slot and have owner diff. from caster
1354 Player* item_owner = itemTarget->GetOwner();
1355 if(!item_owner)
1356 return;
1358 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > 0 && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
1359 sLog.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1360 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
1361 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
1362 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
1364 // remove old enchanting before appling new if equiped
1365 if(itemTarget->IsEquipped())
1366 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT))
1367 item_owner->AddItemEnchant(itemTarget,old_enchant_id,0,false);
1369 for(int x=0;x<3;x++)
1370 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+x,0);
1372 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, enchant_id);
1374 // add new enchanting if equiped
1375 if(itemTarget->IsEquipped())
1376 item_owner->AddItemEnchant(itemTarget,enchant_id,0,true);
1378 itemTarget->SetState(ITEM_CHANGED);
1382 void Spell::EffectEnchantItemTmp(uint32 i)
1384 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1385 return;
1387 Player* p_caster = (Player*)m_caster;
1389 if(!itemTarget)
1390 return;
1392 if (m_spellInfo->EffectMiscValue[i])
1394 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
1395 int32 duration = GetDuration(m_spellInfo);
1396 if(duration == 0)
1397 duration = m_spellInfo->EffectBasePoints[i]+1;
1398 if(duration <= 1)
1399 duration = 300;
1400 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1401 if(!pEnchant)
1402 return;
1404 // item can be in trade slot and have owner diff. from caster
1405 Player* item_owner = itemTarget->GetOwner();
1406 if(!item_owner)
1407 return;
1409 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > 0 && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
1410 sLog.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1411 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
1412 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
1413 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
1415 // remove old enchanting before applying new if equipped
1416 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+1*3))
1418 if(itemTarget->IsEquipped())
1419 item_owner->AddItemEnchant(itemTarget,old_enchant_id,1,false);
1421 // duration == 0 will remove EnchantDuration
1422 item_owner->AddEnchantDuration(itemTarget,1,0);
1425 for(int x=0;x<3;x++)
1426 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1*3+x,0);
1428 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1*3, enchant_id);
1429 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1*3+1, duration*1000);
1430 if(m_spellInfo->SpellFamilyName == 8)
1431 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1*3+2, 45+objmgr.GetSpellRank(m_spellInfo->Id)*15);
1433 // add new enchanting if equipped
1434 if(itemTarget->IsEquipped())
1435 item_owner->AddItemEnchant(itemTarget,enchant_id,1,true);
1437 itemTarget->SetState(ITEM_CHANGED);
1439 // set duration
1440 item_owner->AddEnchantDuration(itemTarget,1,duration*1000);
1444 void Spell::EffectTameCreature(uint32 i)
1446 if(m_caster->GetPetGUID())
1447 return;
1449 if(!unitTarget)
1450 return;
1452 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1453 return;
1455 Creature* creatureTarget = (Creature*)unitTarget;
1457 if(creatureTarget->isPet())
1458 return;
1460 if(m_caster->getClass() == CLASS_HUNTER)
1462 creatureTarget->AttackStop();
1463 if(m_caster->getVictim()==creatureTarget)
1464 m_caster->AttackStop();
1466 creatureTarget->CombatStop();
1467 creatureTarget->StopMoving();
1469 // cast finish succesfully
1470 SendChannelUpdate(0);
1471 finish();
1473 Pet* pet = new Pet(HUNTER_PET);
1475 pet->CreateBaseAtCreature(creatureTarget);
1477 pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
1478 pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1479 pet->SetMaxPower(POWER_HAPPINESS,1000000);
1480 pet->SetPower( POWER_HAPPINESS,600000);
1481 pet->setPowerType(POWER_FOCUS);
1482 pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1483 pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
1484 pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1485 pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1486 pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN1 + UNIT_FLAG_RESTING + UNIT_FLAG_RENAME);
1487 // this enables popup window (pet detals, abandon, rename)
1488 pet->SetUInt32Value(UNIT_FIELD_PETNUMBER,1);
1489 // this enables pet detals window (Shift+P)
1490 pet->AIM_Initialize();
1492 pet->AddToWorld();
1493 MapManager::Instance().GetMap(pet->GetMapId())->Add((Creature*)pet);
1495 ObjectAccessor::Instance().RemoveCreatureCorpseFromPlayerView(creatureTarget);
1496 creatureTarget->setDeathState(JUST_DIED);
1498 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1500 m_caster->SetPet(pet);
1501 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
1502 ((Player*)m_caster)->PetSpellInitialize();
1507 void Spell::EffectSummonPet(uint32 i)
1509 float px, py, pz;
1510 m_caster->GetClosePoint(NULL, px, py, pz);
1512 uint32 petentry = m_spellInfo->EffectMiscValue[i];
1514 Pet *OldSummon = m_caster->GetPet();
1516 // if pet requested type already exist
1517 if( OldSummon )
1520 if(petentry == 0 || OldSummon->GetCreatureInfo()->Entry == petentry)
1522 // pet in corpse state can't be summoned
1523 if( OldSummon->isDead() )
1524 return;
1526 MapManager::Instance().GetMap(OldSummon->GetMapId())->Remove((Creature*)OldSummon,false);
1527 OldSummon->SetMapId(m_caster->GetMapId());
1528 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
1529 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)OldSummon);
1531 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
1533 ((Player*)m_caster)->PetSpellInitialize();
1535 return;
1538 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1539 ((Player*)m_caster)->RemovePet(OldSummon,PET_SAVE_AS_DELETED);
1540 else
1541 return;
1544 Pet* NewSummon = new Pet(m_caster->getClass() == CLASS_HUNTER ? HUNTER_PET : SUMMON_PET);
1546 // petentry==0 for hunter "call pet" (current pet summoned if any)
1547 if(NewSummon->LoadPetFromDB(m_caster,petentry))
1549 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
1550 return;
1553 // not error in case fail hunter call pet
1554 if(!petentry)
1555 return;
1557 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
1559 if(!cInfo)
1561 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
1562 return;
1565 if( NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMapId(), px, py, pz+1, m_caster->GetOrientation(), petentry))
1567 uint32 petlevel = m_caster->getLevel();
1569 NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
1570 NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1571 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0);
1572 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1573 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
1574 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
1575 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,5);
1576 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1577 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1578 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
1579 NewSummon->SetUInt32Value(UNIT_FIELD_PETNUMBER,1); // this enables pet detals window (Shift+P)
1581 // this enables popup window (pet dismiss, cancel), hunter pet additinal flags set later
1582 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_UNKNOWN1);
1584 NewSummon->InitStatsForLevel( petlevel);
1586 for(uint32 i=0; i < CREATURE_MAX_SPELLS; i++)
1587 NewSummon->m_spells[i] = 0;
1589 if(petentry == 416) //imp
1591 NewSummon->m_spells[0] = 3110; //3110---fire bolt 1
1592 NewSummon->AddActState(STATE_RA_SPELL1);
1595 // generate new name for summon pet
1596 if(NewSummon->getPetType()==SUMMON_PET)
1598 std::string new_name=objmgr.GeneratePetName(petentry);
1599 if(new_name!="")
1600 NewSummon->SetName(new_name);
1602 else if(NewSummon->getPetType()==HUNTER_PET)
1604 // this enables popup window (pet detals, abandon, rename)
1605 NewSummon->SetFlag(UNIT_FIELD_FLAGS,(UNIT_FLAG_RESTING | UNIT_FLAG_RENAME));
1608 NewSummon->AIM_Initialize();
1610 NewSummon->AddToWorld();
1611 MapManager::Instance().GetMap(NewSummon->GetMapId())->Add((Creature*)NewSummon);
1613 m_caster->SetPet(NewSummon);
1614 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
1616 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1618 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
1619 ((Player*)m_caster)->PetSpellInitialize();
1622 else
1623 delete NewSummon;
1626 void Spell::EffectLearnPetSpell(uint32 i)
1628 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1629 return;
1631 Player *_player = (Player*)m_caster;
1633 Pet *pet = _player->GetPet();
1634 if(!pet)
1635 return;
1636 if(!pet->isAlive())
1637 return;
1639 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
1640 if(!learn_spellproto)
1641 return;
1643 for(int8 x=0;x<4;x++)
1645 SpellEntry const *has_spellproto = sSpellStore.LookupEntry(pet->m_spells[x]);
1646 if(!has_spellproto)
1648 pet->m_spells[x] = learn_spellproto->Id;
1649 break;
1651 else if(has_spellproto->SpellIconID == learn_spellproto->SpellIconID)
1653 pet->m_spells[x] = learn_spellproto->Id;
1654 break;
1657 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
1658 _player->PetSpellInitialize();
1661 void Spell::EffectAttackMe(uint32 i)
1663 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1665 unitTarget->SetInFront(m_caster);
1666 ((Creature*)unitTarget)->AI().AttackStart(m_caster);
1670 void Spell::EffectWeaponDmg(uint32 i)
1672 if(!unitTarget)
1673 return;
1674 if(!unitTarget->isAlive())
1675 return;
1677 uint32 wp[4] = { SPELL_EFFECT_WEAPON_DAMAGE, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE, SPELL_EFFECT_NORMALIZED_WEAPON_DMG, SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL };
1679 // multiple weap dmg effect workaround
1680 // execute only the first weapon damage
1681 // and handle all effects at once
1682 uint8 j,k;
1683 int32 bonus = 0;
1685 for (j = 0; j < 3; j++)
1687 for (k = 0; k < 4; k++)
1688 if (m_spellInfo->Effect[j] == wp[k])
1689 break;
1690 if (k != 4)
1692 if (j < i)
1693 return;
1694 if (m_spellInfo->Effect[j] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE)
1695 bonus += m_spellInfo->EffectBasePoints[j]+1;
1699 WeaponAttackType attType = BASE_ATTACK;
1700 if(m_spellInfo->rangeIndex != 1 && m_spellInfo->rangeIndex != 2 && m_spellInfo->rangeIndex != 7)
1701 attType = RANGED_ATTACK;
1703 uint32 hitInfo = 0;
1704 uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
1705 uint32 damageType = NORMAL_DAMAGE;
1706 uint32 victimState = VICTIMSTATE_NORMAL;
1707 uint32 eff_damage = 0;
1708 uint32 blocked_dmg = 0;
1709 uint32 absorbed_dmg = 0;
1710 uint32 resisted_dmg = 0;
1711 bool criticalhit = false;
1713 if( unitTarget->IsImmunedToPhysicalDamage() )
1715 m_caster->SendAttackStateUpdate (HITINFO_MISS, unitTarget, 1, NORMAL_DAMAGE, 0, 0, 0, VICTIMSTATE_IS_IMMUNE, 0);
1716 return;
1719 m_caster->DoAttackDamage(unitTarget, &eff_damage, &blocked_dmg, &damageType, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, attType, m_spellInfo, m_IsTriggeredSpell);
1721 // not add bonus to 0 damage
1722 if( eff_damage > 0 && eff_damage + bonus > 0 )
1723 eff_damage += bonus;
1724 else
1725 eff_damage = 0;
1727 for (j = 0; j < 3; j++)
1728 if (m_spellInfo->Effect[j] == SPELL_EFFECT_WEAPON_PERCENT_DAMAGE)
1729 eff_damage = uint32(eff_damage * (m_spellInfo->EffectBasePoints[j]+1) / 100);
1731 if ((hitInfo & nohitMask) && attType != RANGED_ATTACK) // not send ranged miss/etc
1732 m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellInfo->School, eff_damage, absorbed_dmg, resisted_dmg, 1, blocked_dmg);
1734 if(hitInfo & HITINFO_CRITICALHIT)
1735 criticalhit = true;
1737 m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellInfo->School, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
1739 if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg))
1740 eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg);
1741 else
1742 eff_damage = 0;
1744 m_caster->DealDamage(unitTarget, eff_damage, SPELL_DIRECT_DAMAGE, 0, NULL, 0, true);
1746 // take ammo
1747 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1749 if(m_spellInfo->rangeIndex != 1 && m_spellInfo->rangeIndex != 2 && m_spellInfo->rangeIndex != 7)
1751 Item *pItem = ((Player*)m_caster)->GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED );
1752 if(!pItem || pItem->IsBroken())
1753 return;
1755 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
1757 uint32 count = 1;
1758 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
1760 else
1761 if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
1762 ((Player*)m_caster)->DestroyItemCount( ammo , 1, true);
1763 // wand not have ammo
1767 /*if(m_spellInfo->Effect[i] == 121)
1769 m_caster->resetAttackTimer(BASE_ATTACK);
1770 m_caster->resetAttackTimer(OFF_ATTACK);
1771 m_caster->resetAttackTimer(RANGED_ATTACK);
1775 void Spell::EffectThreat(uint32 i)
1777 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
1778 return;
1780 if(!unitTarget->CanHaveThreatList())
1781 return;
1783 unitTarget->AddThreat(m_caster, float(damage));
1786 void Spell::EffectHealMaxHealth(uint32 i)
1788 if(!unitTarget)
1789 return;
1790 if(!unitTarget->isAlive())
1791 return;
1793 uint32 heal = m_caster->GetMaxHealth();
1795 unitTarget->ModifyHealth(heal);
1797 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1798 SendHealSpellOnPlayer((Player*)unitTarget, m_spellInfo->Id, heal);
1801 void Spell::EffectInterruptCast(uint32 i)
1803 if(!unitTarget)
1804 return;
1805 if(!unitTarget->isAlive())
1806 return;
1808 // TODO: not all spells that used this effect apply cooldown at school spells
1809 // also exist case: apply cooldown to interupted cast only and to all spells
1810 if (unitTarget->m_currentSpell && unitTarget->m_currentSpell->m_spellInfo)
1812 unitTarget->ProhibitSpellScholl(unitTarget->m_currentSpell->m_spellInfo->School, GetDuration(m_spellInfo));
1813 unitTarget->InterruptSpell();
1817 void Spell::EffectSummonObjectWild(uint32 i)
1819 GameObject* pGameObj = new GameObject();
1821 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
1823 WorldObject* target = focusObject;
1824 if( !target )
1825 target = m_caster;
1827 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, target->GetMapId(),
1828 target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),
1829 target->GetOrientation(), 0, 0, 0, 0, 0, 0))
1831 delete pGameObj;
1832 return;
1835 int32 duration = GetDuration(m_spellInfo);
1836 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
1838 m_caster->AddGameObject(pGameObj);
1839 pGameObj->AddToWorld();
1840 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
1843 void Spell::EffectScriptEffect(uint32 i)
1845 if(!m_spellInfo->Reagent[0])
1847 // paladin's holy light / flash of light
1848 if ((m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN) &&
1849 (m_spellInfo->SpellIconID == 70 || m_spellInfo->SpellIconID == 242))
1850 EffectHeal( i );
1852 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && (m_spellInfo->SpellFamilyFlags & (1<<23)))
1854 // paladin's judgement
1855 if(!unitTarget || !unitTarget->isAlive())
1856 return;
1857 uint32 spellId2 = 0;
1858 Unit::AuraMap& m_auras = m_caster->GetAuras();
1859 Unit::AuraMap::iterator itr,next;
1861 for(itr = m_auras.begin(); itr != m_auras.end(); itr = next)
1863 next = itr;
1864 next++;
1865 if (itr->second)
1867 SpellEntry const *spellInfo = itr->second->GetSpellProto();
1868 if (!spellInfo) continue;
1869 if (spellInfo->SpellVisual != 5622 || spellInfo->SpellFamilyName != SPELLFAMILY_PALADIN) continue;
1870 spellId2 = spellInfo->EffectBasePoints[2]+1;
1871 if(spellId2 <= 1)
1872 continue;
1873 m_caster->RemoveAurasDueToSpell(spellInfo->Id);
1874 next = m_auras.begin();
1875 break;
1879 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId2);
1880 if(!spellInfo)
1881 return;
1882 Spell spell(m_caster,spellInfo,true,0);
1884 SpellCastTargets targets;
1885 Unit *ptarget = unitTarget;
1886 targets.setUnitTarget(ptarget);
1887 spell.prepare(&targets);
1890 else
1892 uint32 itemtype;
1893 switch(m_spellInfo->Id)
1895 case 6201:
1896 itemtype = 5512; //spell 6261; //primary healstone
1897 break;
1898 case 6202:
1899 itemtype = 5511; //spell 6262; //inferior healstone
1900 break;
1901 case 5699:
1902 itemtype = 5509; //spell 5720; //healstone
1903 break;
1904 case 11729:
1905 itemtype = 5510; //spell 5723; //strong healstone
1906 break;
1907 case 11730:
1908 itemtype = 9421; //spell 11732; //super healstone
1909 break;
1910 default:
1911 return;
1913 DoCreateItem( i, itemtype );
1917 void Spell::EffectSanctuary(uint32 i)
1919 if(!unitTarget)
1920 return;
1921 unitTarget->CombatStop();
1924 void Spell::EffectAddComboPoints(uint32 i)
1926 if(!unitTarget)
1927 return;
1929 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1930 return;
1932 if(damage < 0)
1933 return;
1935 uint8 comboPoints = ((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & 0xFF00) >> 8);
1936 if(m_caster->GetUInt64Value(PLAYER_FIELD_COMBO_TARGET) != unitTarget->GetGUID())
1938 comboPoints = damage;
1939 m_caster->SetUInt64Value(PLAYER_FIELD_COMBO_TARGET,unitTarget->GetGUID());
1940 m_caster->SetUInt32Value(PLAYER_FIELD_BYTES,((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & ~(0xFF << 8)) | (comboPoints << 8)));
1942 else if(comboPoints < 5)
1944 comboPoints += damage;
1945 if(comboPoints > 5)
1946 comboPoints = 5;
1947 m_caster->SetUInt32Value(PLAYER_FIELD_BYTES,((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & ~(0xFF << 8)) | (comboPoints << 8)));
1952 void Spell::EffectDuel(uint32 i)
1954 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
1955 return;
1957 Player *caster = (Player*)m_caster;
1958 Player *target = (Player*)unitTarget;
1960 // caster or target already have requested duel
1961 if( caster->duel || target->duel || target->HasInIgnoreList(caster->GetGUID()) )
1962 return;
1964 //CREATE DUEL FLAG OBJECT
1965 GameObject* pGameObj = new GameObject();
1967 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
1969 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,m_caster->GetMapId(),
1970 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
1971 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
1972 m_caster->GetPositionZ(),
1973 m_caster->GetOrientation(), 0, 0, 0, 0, 0, 0))
1975 delete pGameObj;
1976 return;
1978 pGameObj->SetFloatValue(OBJECT_FIELD_SCALE_X,1.0f);
1980 pGameObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 787 );
1981 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
1982 pGameObj->SetUInt32Value(GAMEOBJECT_TYPE_ID, 16 );
1983 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
1984 int32 duration = GetDuration(m_spellInfo);
1985 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
1986 pGameObj->SetSpellId(m_spellInfo->Id);
1988 m_caster->AddGameObject(pGameObj);
1989 pGameObj->AddToWorld();
1990 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
1991 //END
1993 //Send request
1994 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
1995 data << pGameObj->GetGUID();
1996 data << caster->GetGUID();
1997 caster->GetSession()->SendPacket(&data);
1998 target->GetSession()->SendPacket(&data);
2000 // create duel-info
2001 DuelInfo *duel = new DuelInfo;
2002 duel->initiator = caster;
2003 duel->opponent = target;
2004 duel->startTime = 0;
2005 duel->startTimer = 0;
2006 caster->duel = duel;
2008 DuelInfo *duel2 = new DuelInfo;
2009 duel2->initiator = caster;
2010 duel2->opponent = caster;
2011 duel2->startTime = 0;
2012 duel2->startTimer = 0;
2013 target->duel = duel2;
2015 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
2016 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
2020 void Spell::EffectSummonTotem(uint32 i)
2022 uint8 slot = 0;
2023 switch(m_spellInfo->Effect[i])
2025 case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: slot = 0; break;
2026 case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: slot = 1; break;
2027 case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: slot = 2; break;
2028 case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: slot = 3; break;
2029 default: return;
2032 float angle = m_caster->GetOrientation() + M_PI/4 - (slot*M_PI/2);
2033 float x = m_caster->GetPositionX() + 2 * cos(angle);
2034 float y = m_caster->GetPositionY() + 2 * sin(angle);
2035 float z = m_caster->GetPositionZ();
2037 Map* map = MapManager::Instance().GetMap(m_caster->GetMapId());
2038 float z2 = map->GetHeight(x,y);
2039 if( abs( z2 - z ) < 5 )
2040 z = z2;
2042 uint64 guid = m_caster->m_TotemSlot[slot];
2043 if(guid != 0)
2045 Creature *OldTotem = ObjectAccessor::Instance().GetCreature(*m_caster, guid);
2046 if(OldTotem && OldTotem->isTotem()) ((Totem*)OldTotem)->UnSummon();
2047 m_caster->m_TotemSlot[slot] = 0;
2050 Totem* pTotem = new Totem();
2052 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),
2053 m_caster->GetMapId(), x, y, z, m_caster->GetOrientation(),
2054 m_spellInfo->EffectMiscValue[i] ))
2056 delete pTotem;
2057 return;
2060 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
2061 pTotem->SetOwner(m_caster->GetGUID());
2062 //pTotem->SetSpell(pTotem->GetCreatureInfo()->spell1);
2063 pTotem->SetSpell(m_spellInfo->Id); //use SummonTotem spellid
2064 pTotem->SetDuration(GetDuration(m_spellInfo));
2065 pTotem->SetHealth(5);
2066 pTotem->SetMaxHealth(5);
2067 pTotem->Summon();
2070 void Spell::EffectEnchantHeldItem(uint32 i)
2072 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2073 return;
2075 Player* p_caster = (Player*)m_caster;
2077 if(!itemTarget)
2078 return;
2080 // must be equipped
2081 if(!itemTarget->IsEquipped())
2082 return;
2084 if (m_spellInfo->EffectMiscValue[i])
2086 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
2087 int32 duration = GetDuration(m_spellInfo);
2088 if(duration == 0)
2089 duration = m_spellInfo->EffectBasePoints[i]+1;
2090 if(duration <= 1)
2091 duration = 300;
2092 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
2093 if(!pEnchant)
2094 return;
2096 // can be held by another player and accessable to caster in trade slot
2097 Player* item_owner = itemTarget->GetOwner();
2098 if(!item_owner)
2099 return;
2101 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > 0 && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
2102 sLog.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
2103 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
2104 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
2105 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
2107 // remove old enchanting before appling new
2108 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3))
2109 item_owner->AddItemEnchant(itemTarget,old_enchant_id,pEnchant->display_type,false);
2111 for(int x=0;x<3;x++)
2112 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+x,0);
2114 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3, enchant_id);
2115 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+1, duration*1000);
2116 itemTarget->SetState(ITEM_CHANGED);
2118 // add new enchanting
2119 item_owner->AddItemEnchant(itemTarget,enchant_id,pEnchant->display_type,true);
2121 // set duration
2122 item_owner->AddEnchantDuration(itemTarget,1,duration*1000);
2126 void Spell::EffectDisEnchant(uint32 i)
2128 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2129 return;
2131 Player* p_caster = (Player*)m_caster;
2132 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
2133 return;
2135 p_caster->UpdateCraftSkill(m_spellInfo->Id);
2137 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
2139 // item will be removed at disenchanting end
2142 void Spell::EffectInebriate(uint32 i)
2144 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2145 return;
2147 Player *player = (Player*)m_caster;
2148 uint16 currentDrunk = player->GetDrunkValue();
2149 uint16 drunkMod = (m_spellInfo->EffectBasePoints[i]+1) * 0xFFFF / 100;
2150 if (currentDrunk + drunkMod > 0xFFFF)
2151 currentDrunk = 0xFFFF;
2152 else
2153 currentDrunk += drunkMod;
2154 player->SetDrunkValue(currentDrunk);
2157 void Spell::EffectFeedPet(uint32 i)
2159 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2160 return;
2162 Player *_player = (Player*)m_caster;
2164 if(!itemTarget)
2165 return;
2167 Creature *pet = _player->GetPet();
2168 if(!pet)
2169 return;
2171 if(!pet->isAlive())
2172 return;
2174 pet->ModifyPower(POWER_HAPPINESS,damage);
2176 uint32 count = 1;
2177 _player->DestroyItemCount(itemTarget,count,true);
2179 SpellEntry const *spellinfo = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
2180 Spell _spell(m_caster, spellinfo, true, 0);
2181 SpellCastTargets targets;
2182 targets.setUnitTarget(m_caster);
2183 _spell.prepare(&targets);
2186 void Spell::EffectDismissPet(uint32 i)
2188 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2189 return;
2191 Pet* pet = m_caster->GetPet();
2193 // not let dismiss dead pet
2194 if(!pet||!pet->isAlive())
2195 return;
2197 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_AS_CURRENT);
2200 void Spell::EffectSummonObject(uint32 i)
2202 uint8 slot = 0;
2203 switch(m_spellInfo->Effect[i])
2205 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
2206 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
2207 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
2208 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
2209 default: return;
2212 uint64 guid = m_caster->m_ObjectSlot[slot];
2213 if(guid != 0)
2215 GameObject* obj = NULL;
2216 if( m_caster )
2217 obj = ObjectAccessor::Instance().GetGameObject(*m_caster, guid);
2219 if(obj) obj->Delete();
2220 m_caster->m_ObjectSlot[slot] = 0;
2223 GameObject* pGameObj = new GameObject();
2224 uint32 display_id = m_spellInfo->EffectMiscValue[i];
2226 float rot2 = sin(m_caster->GetOrientation()/2);
2227 float rot3 = cos(m_caster->GetOrientation()/2);
2229 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, 0, 0))
2231 delete pGameObj;
2232 return;
2235 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
2236 int32 duration = GetDuration(m_spellInfo);
2237 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
2238 pGameObj->SetSpellId(m_spellInfo->Id);
2239 pGameObj->SetLootState(GO_CLOSED);
2240 m_caster->AddGameObject(pGameObj);
2242 pGameObj->AddToWorld();
2243 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
2244 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM, 8);
2245 data << pGameObj->GetGUID();
2246 m_caster->SendMessageToSet(&data,true);
2248 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
2251 void Spell::EffectResurrect(uint32 i)
2254 if(!unitTarget)
2255 return;
2256 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
2257 return;
2259 if(unitTarget->isAlive())
2260 return;
2261 if(!unitTarget->IsInWorld())
2262 return;
2264 Player* pTarget = ((Player*)unitTarget);
2266 uint32 health = m_spellInfo->EffectBasePoints[i]+1;
2267 uint32 mana = m_spellInfo->EffectMiscValue[i];
2269 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
2270 SendResurrectRequest(pTarget);
2273 void Spell::EffectParry(uint32 i)
2275 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
2277 ((Player*)unitTarget)->SetCanParry(true);
2281 void Spell::EffectMomentMove(uint32 i)
2283 if(unitTarget->isInFlight())
2284 return;
2286 if( m_spellInfo->rangeIndex== 1) //self range
2288 uint32 mapid = m_caster->GetMapId();
2289 float dis = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2290 float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
2291 float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
2292 // teleport a bit above terrainlevel to avoid falling below it
2293 float fz = MapManager::Instance ().GetMap(mapid)->GetHeight(fx,fy) + 1.5;
2295 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2296 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, m_caster->GetOrientation(), false);
2297 else
2298 MapManager::Instance().GetMap(mapid)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, m_caster->GetOrientation());
2302 void Spell::EffectReputation(uint32 i)
2304 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2305 return;
2307 Player *_player = (Player*)m_caster;
2309 int32 rep_change = m_spellInfo->EffectBasePoints[i]+1; // field store reputation change -1
2311 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
2313 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
2315 if(!factionEntry)
2316 return;
2318 _player->ModifyFactionReputation(factionEntry,rep_change);
2321 void Spell::EffectQuestComplete(uint32 i)
2323 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2324 return;
2326 Player *_player = (Player*)m_caster;
2328 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
2330 if(_player->CanCompleteQuest( quest_id ) )
2331 _player->CompleteQuest( quest_id );
2332 else
2333 return;
2335 if(_player->GetQuestRewardStatus( quest_id ))
2336 return;
2338 _player->PlayerTalkClass->SendQuestGiverOfferReward( quest_id, _player->GetGUID(), true, NULL, 0 );
2341 void Spell::EffectSelfResurrect(uint32 i)
2343 if(!unitTarget) return;
2344 if(unitTarget->GetTypeId() != TYPEID_PLAYER) return;
2345 if(unitTarget->isAlive()) return;
2346 if(!unitTarget->IsInWorld()) return;
2348 uint32 health = 0;
2349 uint32 mana = 0;
2351 if(m_spellInfo->SpellVisual == 99 && m_spellInfo->SpellIconID ==1)
2353 health = m_spellInfo->EffectBasePoints[i]+1 > 0 ? m_spellInfo->EffectBasePoints[i]+1 :(-(m_spellInfo->EffectBasePoints[i]+1));
2354 if(unitTarget->getPowerType() == POWER_MANA)
2355 mana = m_spellInfo->EffectMiscValue[i];
2357 else
2359 if(damage < 0) return;
2360 health = uint32(damage/100*unitTarget->GetMaxHealth());
2361 if(unitTarget->getPowerType() == POWER_MANA)
2362 mana = uint32(damage/100*unitTarget->GetMaxPower(unitTarget->getPowerType()));
2364 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
2365 SendResurrectRequest((Player*)unitTarget);
2368 void Spell::EffectSkinning(uint32 i)
2370 if(unitTarget->GetTypeId() != TYPEID_UNIT )
2371 return;
2372 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2373 return;
2375 int32 targetLevel = unitTarget->getLevel();
2377 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_SKINNING);
2378 unitTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
2380 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
2382 int32 skinningValue = ((Player*)m_caster)->GetPureSkillValue(SKILL_SKINNING);
2384 // Double chances for elites
2385 ((Player*)m_caster)->UpdateGatherSkill(SKILL_SKINNING, skinningValue, reqValue, ((Creature*)unitTarget)->isElite() ? 2 : 1 );
2388 void Spell::EffectCharge(uint32 i)
2390 if(!unitTarget || !m_caster)
2391 return;
2393 float x, y, z;
2394 unitTarget->GetClosePoint(m_caster, x, y, z);
2395 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
2396 ((Creature *)unitTarget)->StopMoving();
2398 m_caster->SendMonsterMove(x, y, z, false,true,1);
2399 m_caster->Attack(unitTarget);
2402 void Spell::EffectSummonCritter(uint32 i)
2404 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
2405 if(!pet_entry)
2406 return;
2408 Unit* old_critter = NULL;
2411 CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
2412 Cell cell = RedZone::GetZone(p);
2413 cell.data.Part.reserved = ALL_DISTRICT;
2414 cell.SetNoCreate();
2416 PetWithIdCheck u_check(m_caster, pet_entry);
2417 MaNGOS::UnitSearcher<PetWithIdCheck> checker(old_critter, u_check);
2418 TypeContainerVisitor<MaNGOS::UnitSearcher<PetWithIdCheck>, TypeMapContainer<AllObjectTypes> > object_checker(checker);
2419 CellLock<GridReadGuard> cell_lock(cell, p);
2420 cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId()));
2423 if (old_critter) // find old critter, unsummon
2425 // PetWithIdCheck return only Pets
2426 ((Pet*)old_critter)->Remove(PET_SAVE_AS_DELETED);
2427 return;
2429 else // in another case summon new
2431 Pet* critter = new Pet(MINI_PET);
2433 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
2434 m_caster->GetMapId(),
2435 m_caster->GetPositionX(),m_caster->GetPositionY(),
2436 m_caster->GetPositionZ(),m_caster->GetOrientation(),
2437 m_spellInfo->EffectMiscValue[i]))
2439 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
2440 delete critter;
2441 return;
2444 critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
2445 critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID());
2446 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
2448 critter->AIM_Initialize();
2450 std::string name;
2451 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2452 name = ((Player*)m_caster)->GetName();
2453 else
2454 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
2455 name.append(petTypeSuffix[critter->getPetType()]);
2456 critter->SetName( name );
2457 //m_caster->SetPet(critter);
2459 critter->AddToWorld();
2460 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)critter);
2464 void Spell::EffectKnockBack(uint32 i)
2466 if(!unitTarget || !m_caster)
2467 return;
2469 //Effect only works on players
2470 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
2471 return;
2473 float value = 0;
2474 int32 basePoints = m_spellInfo->EffectBasePoints[i];
2475 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2476 if (randomPoints) value = basePoints + rand()%randomPoints;
2477 else value = basePoints;
2479 //Only allowed to knock ourselves straight up to prevent exploiting
2480 if (unitTarget == m_caster)value = 0;
2482 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
2483 data.append(unitTarget->GetPackGUID());
2484 data << uint32(0); //Sequence
2485 data << cos(m_caster->GetAngle(unitTarget)); //xdirection
2486 data << sin(m_caster->GetAngle(unitTarget)); //ydirection
2487 data << value/10; //Horizontal speed
2488 data << float(m_spellInfo->EffectMiscValue[i])/-10; //Z Movement speed
2490 ((Player*)unitTarget)->SendMessageToSet(&data,true);
2493 void Spell::EffectSummonDeadPet(uint32 i)
2495 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2496 return;
2497 Player *_player = (Player*)m_caster;
2498 Pet *pet = _player->GetPet();
2499 if(!pet)
2500 return;
2501 if(pet->isAlive())
2502 return;
2503 if(damage < 0)
2504 return;
2505 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
2506 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
2507 pet->setDeathState( ALIVE );
2508 pet->clearUnitState(UNIT_STAT_ALL_STATE);
2509 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
2511 pet->AIM_Initialize();
2513 _player->PetSpellInitialize();
2514 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
2517 void Spell::EffectTransmitted(uint32 i)
2519 float fx,fy;
2521 float min_dis = GetMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
2522 float max_dis = GetMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
2523 float diff = max_dis - min_dis + 1;
2524 float dis = (float)(rand()%(uint32)diff + (uint32)min_dis);
2526 fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
2527 fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
2529 float fz = MapManager::Instance ().GetMap(m_caster->GetMapId())->GetHeight(fx,fy);
2531 if(m_spellInfo->EffectMiscValue[i] == 35591)
2533 Map* map = MapManager::Instance().GetMap(m_caster->GetMapId());
2534 if ( !map->IsUnderWater(fx,fy,fz) )
2536 SendCastResult(CAST_FAIL_CANT_BE_CAST_HERE);
2537 up_skillvalue = 4;
2538 SendChannelUpdate(0);
2539 return;
2542 // replace by water level in this case
2543 fz = MapManager::Instance ().GetMap(m_caster->GetMapId())->GetWaterLevel(fx,fy);
2547 GameObject* pGameObj = new GameObject();
2548 uint32 name_id = m_spellInfo->EffectMiscValue[i];
2550 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id,m_caster->GetMapId(),
2551 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 0))
2553 delete pGameObj;
2554 return;
2557 if(m_spellInfo->EffectMiscValue[i] == 35591)
2559 m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUIDLow());
2560 m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT+1,pGameObj->GetGUIDHigh());
2561 //Orientation3
2562 pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
2563 //Orientation4
2564 pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
2565 pGameObj->SetLootState(GO_NOT_READY); // bobber not move
2566 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
2568 // end time of range when posable catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
2569 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
2570 uint32 fish = urand(FISHING_BOBBER_READY_TIME,GetDuration(m_spellInfo)/1000);
2571 pGameObj->SetRespawnTime(fish);
2573 else
2575 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
2576 int32 duration = GetDuration(m_spellInfo);
2577 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
2580 pGameObj->SetUInt32Value(12, 0x3F63BB3C );
2581 pGameObj->SetUInt32Value(13, 0xBEE9E017 );
2582 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
2583 pGameObj->SetSpellId(m_spellInfo->Id);
2585 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
2586 //m_caster->AddGameObject(pGameObj);
2587 //m_ObjToDel.push_back(pGameObj);
2589 pGameObj->AddToWorld();
2590 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
2592 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM, 8);
2593 data << uint64(pGameObj->GetGUID());
2594 m_caster->SendMessageToSet(&data,true);
2597 void Spell::EffectSkill(uint32 i)
2599 sLog.outDebug("WORLD: SkillEFFECT");