[3120] - Applied MaNGOS coding style (see trunk/bcpp.cfg).
[mangos-git.git] / src / game / SpellEffects.cpp
blob4f989a1941222f1608536b85e52d20bf1d090575
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::EffectNULL, //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, false);
203 void Spell::EffectSchoolDMG(uint32 i)
205 if( unitTarget && unitTarget->isAlive() )
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 // skip non hostile to caster enemy creatures
228 if( !((Creature*)unitTarget)->IsHostileTo(m_caster->getVictim()) )
229 return;
231 // only from same creature faction
232 if(unitTarget->getFaction() != m_caster->getFaction() )
233 return;
235 // only if enimy is player or pet.
236 if( m_caster->getVictim()->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_caster->getVictim())->isPet() )
238 // and finally if creature not figthing currently
239 if( !unitTarget->isInCombat() )
241 ((Creature*)m_caster)->SetNoCallAssistence(true);
242 ((Creature*)unitTarget)->SetNoCallAssistence(true);
243 ((Creature*)unitTarget)->AI().AttackStart(m_caster->getVictim());
246 return;
249 // Preparation Rogue - immediately finishes the cooldown on other Rogue abilities
250 if(m_spellInfo->Id == 14185)
252 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
253 return;
255 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
256 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
258 uint32 classspell = itr->first;
259 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
261 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->Id != 14185 &&
262 (spellInfo->RecoveryTime > 0 || spellInfo->CategoryRecoveryTime > 0))
264 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
266 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4));
267 data << classspell;
268 data << m_caster->GetGUID();
269 data << uint32(0);
270 ((Player*)m_caster)->GetSession()->SendPacket(&data);
273 return;
276 // Cold Snap - immediately finishes the cooldown on Frost spells
277 if(m_spellInfo->Id == 12472)
279 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
280 return;
282 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
283 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
285 if (itr->second->state == PLAYERSPELL_REMOVED) continue;
286 uint32 classspell = itr->first;
287 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
289 if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && spellInfo->School == SPELL_SCHOOL_FROST && spellInfo->Id != 12472 &&
290 (spellInfo->RecoveryTime > 0 || spellInfo->CategoryRecoveryTime > 0))
292 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
294 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4));
295 data << classspell;
296 data << m_caster->GetGUID();
297 data << uint32(0);
298 ((Player*)m_caster)->GetSession()->SendPacket(&data);
301 return;
304 // If spell cannibalize and his casted, check special requirements and cast aura Cannibalize is all ok
305 if(m_spellInfo->Id == 20577)
307 // non-standard cast requirement check
308 SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
309 float max_range = GetMaxRange(srange);
311 CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
312 Cell cell = RedZone::GetZone(p);
313 cell.data.Part.reserved = ALL_DISTRICT;
314 cell.SetNoCreate();
316 Unit* result = NULL;
318 MaNGOS::CannibalizeUnitCheck u_check(m_caster, max_range);
319 MaNGOS::UnitSearcher<MaNGOS::CannibalizeUnitCheck> searcher(result, u_check);
321 TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::CannibalizeUnitCheck>, TypeMapContainer<AllObjectTypes> > unit_searcher(searcher);
322 CellLock<GridReadGuard> cell_lock(cell, p);
323 cell_lock->Visit(cell_lock, unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId()));
325 if (!result)
327 // clear cooldown at fail
328 if(m_caster->GetTypeId()==TYPEID_PLAYER)
330 ((Player*)m_caster)->RemoveSpellCooldown(20577);
332 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8+4));
333 data << uint32(20577); // spell id
334 data << m_caster->GetGUID();
335 data << uint32(0);
336 ((Player*)m_caster)->GetSession()->SendPacket(&data);
339 SendCastResult(CAST_FAIL_NO_NEARBY_CORPSES_TO_EAT);
340 return;
343 // ok, main function spell can be casted
345 finish(); // prepere to replacing this cpell cast to main function spell
347 // casting
348 SpellEntry const *spellInfo = sSpellStore.LookupEntry( 20578 );
349 Spell *spell = new Spell(m_caster, spellInfo, false, 0);
350 if(!spellInfo)
352 sLog.outError("WORLD: unknown spell id %i\n", 20578);
353 return;
356 SpellCastTargets targets;
357 targets.setUnitTarget(m_caster);
358 spell->prepare(&targets);
359 return;
362 // More generic code later
364 // starshards/curse of agony hack .. this applies to 1.10 only
365 if (m_triggeredByAura)
367 SpellEntry const *trig_info = m_triggeredByAura->GetSpellProto();
368 if ((trig_info->SpellIconID == 1485 && trig_info->SpellFamilyName == SPELLFAMILY_PRIEST) ||
369 (trig_info->SpellIconID == 544 && trig_info->SpellFamilyName == SPELLFAMILY_WARLOCK))
371 Unit *tmpTarget = unitTarget;
372 unitTarget = m_triggeredByAura->GetTarget();
373 damage = trig_info->EffectBasePoints[i]+1;
374 EffectSchoolDMG(i);
375 unitTarget = tmpTarget;
379 //Holy Shock For Paladins
380 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellIconID == 156)
382 int hurt = 0;
383 int heal = 0;
385 switch(m_spellInfo->Id)
387 case 20473:
388 hurt = 25912;
389 heal = 25914;
390 break;
391 case 20929:
392 hurt = 25911;
393 heal = 25913;
394 break;
395 case 20930:
396 hurt = 25902;
397 heal = 25903;
398 break;
399 default:
400 break;
403 if(m_caster->IsFriendlyTo(unitTarget))
404 m_caster->CastSpell(unitTarget, heal, true, 0);
405 else
406 m_caster->CastSpell(unitTarget, hurt, true, 0);
409 if(m_spellInfo->SpellIconID == 1648)
411 uint32 dmg = damage;
412 dmg += uint32(m_caster->GetPower(POWER_RAGE)/10 * objmgr.GetSpellRank(m_spellInfo->Id)*3);
413 SpellEntry const *tspellInfo = sSpellStore.LookupEntry(20647);
414 SpellEntry sInfo = *tspellInfo;
415 sInfo.EffectBasePoints[0] = dmg;
416 m_caster->CastSpell(unitTarget, &sInfo, true, 0);
417 m_caster->SetPower(POWER_RAGE,0);
420 //Life Tap
421 if(m_spellInfo->SpellVisual == 1225 && m_spellInfo->SpellIconID == 208)
423 int32 mod = m_spellInfo->EffectBasePoints[0]+1;
424 if(m_caster)
426 if(m_caster->GetHealth()>mod)
428 m_caster->ModifyHealth(-mod);
429 m_caster->ModifyPower(POWER_MANA,mod);
435 void Spell::EffectTriggerSpell(uint32 i)
437 SpellEntry const *spellInfo = sSpellStore.LookupEntry( m_spellInfo->EffectTriggerSpell[i] );
439 if(!spellInfo)
441 sLog.outError("WORLD: unknown spell id %i\n", m_spellInfo->EffectTriggerSpell[i]);
442 return;
445 m_TriggerSpell.push_back(spellInfo);
449 void Spell::EffectTeleportUnits(uint32 i)
451 if(!unitTarget)
452 return;
453 HandleTeleport(m_spellInfo->Id,unitTarget);
456 void Spell::EffectApplyAura(uint32 i)
458 if(!unitTarget)
459 return;
460 if(!unitTarget->isAlive())
461 return;
463 //If m_immuneToState type contain this aura type, IMMUNE aura.
464 if(unitTarget->IsImmunedToSpellEffect(m_spellInfo->EffectApplyAuraName[i]))
466 SendCastResult(CAST_FAIL_IMMUNE);
467 return;
470 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
472 Aura* Aur = new Aura(m_spellInfo, i, unitTarget,m_caster, m_CastItem);
474 if (!Aur->IsPositive() && Aur->GetCasterGUID() != Aur->GetTarget()->GetGUID())
476 switch (Aur->GetModifier()->m_auraname)
478 case SPELL_AURA_MOD_DETECT_RANGE:
479 case SPELL_AURA_AURAS_VISIBLE:
480 case SPELL_AURA_MOD_CHARM:
481 break;
482 default:
483 if(Aur->GetTarget()->GetTypeId() == TYPEID_UNIT)
484 ((Creature*)Aur->GetTarget())->AI().AttackStart(m_caster);
485 else
487 m_caster->Attack(Aur->GetTarget());
488 m_caster->SetInCombat();
489 Aur->GetTarget()->SetInCombat();
494 bool added = unitTarget->AddAura(Aur);
496 if (added)
498 // Check for Power Word: Shield
499 // TODO Make a way so it works for every related spell!
500 if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players
502 // This should cover all Power Word: Shield spells
503 if ((m_spellInfo->SpellVisual == 784) && (m_spellInfo->SpellIconID == 566))
505 // Weakened Soul
506 SpellEntry const *WeakenedSoulSpellInfo = sSpellStore.LookupEntry( 6788 );
507 Aura* WeakenedSoulAura = new Aura(WeakenedSoulSpellInfo, 0, unitTarget,m_caster, 0);
508 unitTarget->AddAura(WeakenedSoulAura, 0);
509 sLog.outDebug("Spell: Additinal Aura is: %u", WeakenedSoulSpellInfo->EffectApplyAuraName[i]);
513 if(Aur->IsTrigger())
515 // arcane missiles
516 SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
517 if (!spellInfo) return;
518 if (spellInfo->EffectImplicitTargetA[0] == TARGET_SINGLE_ENEMY && m_caster->GetTypeId() == TYPEID_PLAYER)
520 Unit *target = ObjectAccessor::Instance().GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
521 if (target)
523 if (!m_caster->IsFriendlyTo(target))
524 Aur->SetTarget(target);
525 else
526 cancel();
528 else
529 cancel();
535 void Spell::EffectManaDrain(uint32 i)
537 if(m_spellInfo->EffectMiscValue[i] > 4)
538 return;
540 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
542 if(!unitTarget)
543 return;
544 if(!unitTarget->isAlive())
545 return;
546 if(unitTarget->getPowerType() != drain_power)
547 return;
549 uint32 curPower = unitTarget->GetPower(drain_power);
550 float tmpvalue = m_spellInfo->EffectMultipleValue[i];
551 if(!tmpvalue)
552 tmpvalue = 1;
554 int32 new_damage;
555 if(curPower < damage)
556 new_damage = curPower;
557 else
558 new_damage = damage;
560 unitTarget->ModifyPower(drain_power,-new_damage);
562 if(drain_power == POWER_MANA)
563 m_caster->ModifyPower(POWER_MANA,uint32(new_damage*tmpvalue));
566 void Spell::EffectSendEvent(uint32 i)
568 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, focusObject);
571 void Spell::EffectPowerDrain(uint32 i)
573 if(!unitTarget)
574 return;
575 if(!unitTarget->isAlive())
576 return;
577 if(unitTarget->getPowerType()!=POWER_MANA)
578 return;
580 uint32 curPower = unitTarget->GetPower(POWER_MANA);
582 int32 new_damage;
583 if(curPower < damage)
584 new_damage = curPower;
585 else
586 new_damage = damage;
588 int32 tmpvalue = int32(new_damage*m_spellInfo->EffectMultipleValue[i]);
590 unitTarget->ModifyPower(POWER_MANA,-new_damage);
592 m_caster->ModifyPower(POWER_MANA,tmpvalue);
593 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage/2, m_IsTriggeredSpell);
597 void Spell::EffectHeal( uint32 i )
599 if( unitTarget && unitTarget->isAlive() )
601 int32 addhealth = m_caster->SpellHealingBonus(m_spellInfo, damage);
602 bool crit = m_caster->SpellCriticalBonus(m_spellInfo, &addhealth);
603 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
604 SendHealSpellOnPlayer(((Player*)unitTarget), m_spellInfo->Id, addhealth, crit);
606 unitTarget->ModifyHealth( addhealth );
608 uint32 procHealer = PROC_FLAG_HEAL;
609 if (crit)
610 procHealer |= PROC_FLAG_CRIT_HEAL;
611 if (m_caster != unitTarget)
612 m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_NONE,addhealth,m_spellInfo,m_IsTriggeredSpell);
616 void Spell::EffectHealthLeach(uint32 i)
618 if(!unitTarget)
619 return;
620 if(!unitTarget->isAlive())
621 return;
623 sLog.outDebug("HealthLeach :%u", damage);
625 uint32 curHealth = unitTarget->GetHealth();
627 int32 new_damage;
628 if(curHealth < damage)
629 new_damage = curHealth;
630 else
631 new_damage = damage;
633 int32 tmpvalue = int32(new_damage*m_spellInfo->EffectMultipleValue[i]);
635 m_caster->ModifyHealth(tmpvalue);
637 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
638 SendHealSpellOnPlayer(((Player*)unitTarget), m_spellInfo->Id, uint32(tmpvalue));
640 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell);
643 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
645 if (m_caster->GetTypeId() != TYPEID_PLAYER)
646 return;
648 Player* player = (Player*)m_caster;
650 uint32 newitemid = itemtype;
651 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
652 if(!pProto)
654 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
655 return;
658 uint32 num_to_add;
660 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
661 num_to_add = max(m_spellInfo->EffectBasePoints[i]+1, 1);
662 else if(player->getLevel() >= m_spellInfo->spellLevel)
663 num_to_add = ((player->getLevel() - (m_spellInfo->spellLevel-1))*2);
664 else
665 num_to_add = 2;
667 uint16 dest;
668 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, false);
669 if( msg != EQUIP_ERR_OK )
671 player->SendEquipError( msg, NULL, NULL );
672 return;
675 Item *pItem = player->StoreNewItem( dest, newitemid, num_to_add, true);
677 if(!pItem)
679 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
680 return;
683 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE )
684 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
686 //should send message "create item" to client.-FIX ME
687 player->UpdateCraftSkill(m_spellInfo->Id);
690 void Spell::EffectCreateItem(uint32 i)
692 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
695 void Spell::EffectPersistentAA(uint32 i)
697 float radius = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
698 int32 duration = GetDuration(m_spellInfo);
699 DynamicObject* dynObj = new DynamicObject();
700 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))
702 delete dynObj;
703 return;
705 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
706 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
707 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
708 m_caster->AddDynObject(dynObj);
709 dynObj->AddToWorld();
710 MapManager::Instance().GetMap(dynObj->GetMapId())->Add(dynObj);
714 void Spell::EffectEnergize(uint32 i)
716 if(!unitTarget)
717 return;
718 if(!unitTarget->isAlive())
719 return;
721 if(m_spellInfo->EffectMiscValue[i] > 4)
722 return;
724 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
726 if(unitTarget->getPowerType() != power)
727 return;
729 unitTarget->ModifyPower(power,damage);
732 void Spell::EffectOpenLock(uint32 i)
735 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
737 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
738 return;
741 Player* player = (Player*)m_caster;
743 LootType loottype = LOOT_CORPSE;
744 uint32 lockId = 0;
745 uint64 guid = 0;
747 // Get lockId
748 if(gameObjTarget)
750 lockId = gameObjTarget->GetGOInfo()->sound0;
751 guid = gameObjTarget->GetGUID();
753 else if(itemTarget)
755 lockId = itemTarget->GetProto()->LockID;
756 guid = itemTarget->GetGUID();
758 else
760 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
761 return;
764 if(!lockId) // possible case for GO and maybe for items.
766 player->SendLoot(guid,loottype);
767 return;
770 // Get LockInfo
771 LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
773 if (!lockInfo)
775 sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
776 (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
777 SendCastResult(CAST_FAIL_INVALID_TARGET);
778 return;
781 uint32 SkillId = 0;
782 // Check and skill-up skill
783 if(m_spellInfo->Effect[1]==SPELL_EFFECT_SKILL)
784 SkillId = m_spellInfo->EffectMiscValue[1];
785 else
786 if(m_spellInfo->EffectMiscValue[0]==1) // picklocking spells
787 SkillId = SKILL_LOCKPICKING;
789 // skill bonus provided by casting spell (mostly item spells)
790 uint32 spellSkillBonus = uint32(m_spellInfo->EffectBasePoints[0]+1);
792 uint32 reqSkillValue = lockInfo->requiredskill;
794 if(lockInfo->requiredlockskill) // required pick lock skill applying
796 if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
798 SendCastResult(CAST_FAIL_FIZZLED);
799 return;
802 reqSkillValue = lockInfo->requiredlockskill;
804 else
805 if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
807 SendCastResult(CAST_FAIL_INVALID_TARGET);
808 return;
811 if ( SkillId )
813 loottype = LOOT_SKINNING;
814 if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
816 SendCastResult(CAST_FAIL_SKILL_NOT_HIGH_ENOUGH);
817 return;
820 // update skill if really known
821 uint32 SkillValue = player->GetPureSkillValue(SkillId);
822 if(SkillValue) // non only item base skill
824 if(gameObjTarget)
826 // Allow one skill-up until respawned
827 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
828 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
829 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
831 else if(itemTarget)
833 // Do one skill-up
834 uint32 SkillValue = player->GetPureSkillValue(SkillId);
835 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
840 // Send loot
841 player->SendLoot(guid,loottype);
844 void Spell::EffectSummonChangeItem(uint32 i)
846 if(m_caster->GetTypeId() != TYPEID_PLAYER)
847 return;
849 Player *player = (Player*)m_caster;
851 // applied only to using item
852 if(!m_CastItem)
853 return;
855 // ... only to item in own inventory/bank/equip_slot
856 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
857 return;
859 uint32 newitemid = m_spellInfo->EffectItemType[i];
860 if(!newitemid)
861 return;
863 uint16 pos = (m_CastItem->GetBagSlot() << 8) | m_CastItem->GetSlot();
865 Item *pNewItem = player->CreateItem( newitemid, 1 );
866 if( !pNewItem )
867 return;
869 uint16 dest;
870 uint8 msg;
872 if( player->IsInventoryPos( pos ) )
874 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
875 if( msg == EQUIP_ERR_OK )
877 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
878 player->StoreItem( dest, pNewItem, true);
879 return;
882 else if( player->IsBankPos ( pos ) )
884 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
885 if( msg == EQUIP_ERR_OK )
887 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
888 player->BankItem( dest, pNewItem, true);
889 return;
892 else if( player->IsEquipmentPos ( pos ) )
894 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
895 if( msg == EQUIP_ERR_OK )
897 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
898 player->EquipItem( dest, pNewItem, true);
899 return;
903 // fail
904 delete pNewItem;
907 void Spell::EffectOpenSecretSafe(uint32 i)
909 EffectOpenLock(i); //no difference for now
912 void Spell::EffectProficiency(uint32 i)
914 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
915 return;
916 Player *p_target = (Player*)unitTarget;
918 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
919 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
921 p_target->AddWeaponProficiency(subClassMask);
922 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
924 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
926 p_target->AddArmorProficiency(subClassMask);
927 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
931 void Spell::EffectApplyAA(uint32 i)
933 if(!unitTarget)
934 return;
935 if(!unitTarget->isAlive())
936 return;
938 AreaAura* Aur = new AreaAura(m_spellInfo, i, unitTarget, m_caster);
939 unitTarget->AddAura(Aur);
942 void Spell::EffectSummon(uint32 i)
944 if(m_caster->GetPetGUID())
945 return;
947 if(!unitTarget)
948 return;
949 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
950 if(!pet_entry)
951 return;
952 uint32 level = m_caster->getLevel();
953 Pet* spawnCreature = new Pet(SUMMON_PET);
955 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
956 m_caster->GetMapId(),
957 m_caster->GetPositionX(),m_caster->GetPositionY(),
958 m_caster->GetPositionZ(),m_caster->GetOrientation(),
959 m_spellInfo->EffectMiscValue[i]))
961 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
962 delete spawnCreature;
963 return;
966 spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
967 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
968 spawnCreature->setPowerType(POWER_MANA);
969 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
970 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
971 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
972 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
973 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
974 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
975 spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
977 spawnCreature->InitStatsForLevel(level);
979 spawnCreature->AIM_Initialize();
981 std::string name;
982 if(m_caster->GetTypeId() == TYPEID_PLAYER)
983 name = ((Player*)m_caster)->GetName();
984 else
985 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
986 name.append(petTypeSuffix[spawnCreature->getPetType()]);
987 spawnCreature->SetName( name );
989 spawnCreature->AddToWorld();
990 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)spawnCreature);
992 if(m_caster->GetTypeId() == TYPEID_PLAYER)
994 m_caster->SetPet(spawnCreature);
995 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
996 ((Player*)m_caster)->PetSpellInitialize();
1000 void Spell::EffectLearnSpell(uint32 i)
1002 if(!unitTarget)
1003 return;
1005 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1007 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1009 Creature *pet = m_caster->GetPet();
1011 if( !pet || !pet->isPet() || pet!=unitTarget || !pet->isAlive() )
1012 return;
1014 EffectLearnPetSpell(i);
1016 return;
1019 Player *player = (Player*)unitTarget;
1021 uint32 spellToLearn = m_spellInfo->EffectTriggerSpell[i];
1022 //data.Initialize(SMSG_LEARNED_SPELL);
1023 //data << spellToLearn;
1024 //player->GetSession()->SendPacket(&data);
1025 player->learnSpell((uint16)spellToLearn);
1026 //some addspell isn't needed if you have a good DB,FISHING && MINING && HERBALISM have to be needed.
1027 switch(spellToLearn)
1029 case 4036: //SKILL_ENGINERING
1031 player->learnSpell(3918);
1032 player->learnSpell(3919);
1033 player->learnSpell(3920);
1034 break;
1036 case 3908: //SKILL_TAILORING
1038 player->learnSpell(2387);
1039 player->learnSpell(2963);
1040 break;
1042 case 7411: //SKILL_ENCHANTING
1044 player->learnSpell(7418);
1045 player->learnSpell(7421);
1046 player->learnSpell(13262);
1047 break;
1049 case 2259: //SKILL_ALCHEMY
1051 player->learnSpell(2329);
1052 player->learnSpell(7183);
1053 player->learnSpell(2330);
1054 break;
1056 case 2018: //SKILL_BLACKSMITHING
1058 player->learnSpell(2663);
1059 player->learnSpell(12260);
1060 player->learnSpell(2660);
1061 player->learnSpell(3115);
1062 break;
1064 case 2108: //SKILL_LEATHERWORKING
1066 player->learnSpell(2152);
1067 player->learnSpell(9058);
1068 player->learnSpell(9059);
1069 player->learnSpell(2149);
1070 player->learnSpell(7126);
1071 player->learnSpell(2881);
1072 break;
1074 case 2550: //SKILL_COOKING
1076 player->learnSpell(818);
1077 player->learnSpell(2540);
1078 player->learnSpell(2538);
1079 player->learnSpell(8604);
1080 break;
1082 case 3273: //SKILL_FIRST_AID
1084 player->learnSpell(3275);
1085 break;
1087 case 7620: //SKILL_FISHING
1089 player->learnSpell(7738);
1090 break;
1092 case 2575: //SKILL_MINING
1094 player->learnSpell(2580);
1095 player->learnSpell(2656);
1096 player->learnSpell(2657);
1097 break;
1099 case 2366: //SKILL_HERBALISM
1101 player->learnSpell(2383);
1102 break;
1104 case 264: //SKILL_BOWS
1106 if(!player->HasSpell(75))
1107 player->learnSpell(2480);
1108 break;
1110 case 266: //SKILL_GUNS
1112 if(!player->HasSpell(75))
1113 player->learnSpell(7918);
1114 break;
1116 case 5011: //SKILL_CROSSBOWS
1118 if(!player->HasSpell(75))
1119 player->learnSpell(7919);
1120 break;
1122 case 2567: //SKILL_THROWN
1124 player->learnSpell(2764);
1125 break;
1127 case 2842: //SKILL_POISONS
1129 player->learnSpell(8681);
1130 break;
1132 default:break;
1134 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
1137 void Spell::EffectDispel(uint32 i)
1139 m_caster->RemoveFirstAuraByDispel(m_spellInfo->EffectMiscValue[i]);
1142 void Spell::EffectDualWield(uint32 i)
1144 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
1145 ((Player*)unitTarget)->SetCanDualWield(true);
1148 void Spell::EffectPickPocket(uint32 i)
1150 if( m_caster->GetTypeId() != TYPEID_PLAYER )
1151 return;
1153 //victim must be creature and attackable
1154 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
1155 return;
1157 //victim have to be alive and humanoid or undead
1158 if( unitTarget->isAlive() &&
1159 (((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_HUMANOID ||
1160 ((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_UNDEAD))
1162 int chance = 10 + m_caster->getLevel() - unitTarget->getLevel();
1164 if ( ( rand() % 20 ) <= chance )
1166 //Stealing successfull
1167 //sLog.outDebug("Sending loot from pickpocket");
1168 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOKETING);
1170 else
1172 //Reveal action + get attack
1173 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
1174 ((Creature*)unitTarget)->AI().AttackStart(m_caster);
1179 void Spell::EffectSummonWild(uint32 i)
1181 if(!unitTarget)
1182 return;
1183 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
1184 if(!pet_entry)
1185 return;
1187 Pet* old_wild = NULL;
1190 CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1191 Cell cell = RedZone::GetZone(p);
1192 cell.data.Part.reserved = ALL_DISTRICT;
1193 cell.SetNoCreate();
1195 PetWithIdCheck u_check(m_caster, pet_entry);
1196 MaNGOS::UnitSearcher<PetWithIdCheck> checker((Unit*&)old_wild, u_check);
1197 TypeContainerVisitor<MaNGOS::UnitSearcher<PetWithIdCheck>, TypeMapContainer<AllObjectTypes> > object_checker(checker);
1198 CellLock<GridReadGuard> cell_lock(cell, p);
1199 cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId()));
1202 if (old_wild) // find old critter, unsummon
1204 old_wild->Remove(PET_SAVE_AS_DELETED);
1205 return;
1207 else // in another case summon new
1210 uint32 level = m_caster->getLevel();
1212 // level of pet summoned using engineering item based at engineering skill level
1213 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
1215 ItemPrototype const *proto = m_CastItem->GetProto();
1216 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
1218 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
1219 if(skill202)
1221 level = skill202/5;
1226 Pet* spawnCreature = new Pet(GUARDIAN_PET);
1228 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
1229 m_caster->GetMapId(),
1230 m_caster->GetPositionX(),m_caster->GetPositionY(),
1231 m_caster->GetPositionZ(),m_caster->GetOrientation(),
1232 m_spellInfo->EffectMiscValue[i]))
1234 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
1235 delete spawnCreature;
1236 return;
1239 spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
1240 spawnCreature->setPowerType(POWER_MANA);
1241 spawnCreature->SetPower( POWER_MANA,28 + 10 * level);
1242 spawnCreature->SetMaxPower(POWER_MANA,28 + 10 * level);
1243 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
1244 spawnCreature->SetHealth( 28 + 30*level);
1245 spawnCreature->SetMaxHealth( 28 + 30*level);
1246 spawnCreature->SetLevel(level);
1247 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1248 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
1249 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
1250 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
1251 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1252 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1253 spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1255 spawnCreature->SetArmor(level*50);
1256 spawnCreature->AIM_Initialize();
1258 std::string name;
1259 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1260 name = ((Player*)m_caster)->GetName();
1261 else
1262 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
1263 name.append(petTypeSuffix[spawnCreature->getPetType()]);
1264 spawnCreature->SetName( name );
1266 spawnCreature->AddToWorld();
1267 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)spawnCreature);
1269 guardians and wilds can't be controled
1270 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1272 m_caster->SetPet(spawnCreature);
1273 ((Player*)m_caster)->PetSpellInitialize();
1274 ((Player*)m_caster)->SavePet();
1280 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
1282 if(!unitTarget)
1283 return;
1285 if(unitTarget->isInFlight())
1286 return;
1288 uint32 mapid = m_caster->GetMapId();
1289 float dis = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
1290 float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
1291 float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
1292 // teleport a bit above terrainlevel to avoid falling below it
1293 float fz = MapManager::Instance ().GetMap(mapid)->GetHeight(fx,fy) + 1.5;
1295 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1296 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), false);
1297 else
1298 MapManager::Instance().GetMap(mapid)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
1301 void Spell::EffectLearnSkill(uint32 i)
1303 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1304 return;
1306 uint32 skillid = m_spellInfo->EffectMiscValue[i];
1307 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
1308 ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,damage*75);
1311 void Spell::EffectTradeSkill(uint32 i)
1313 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1314 return;
1315 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
1316 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
1317 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
1320 void Spell::EffectEnchantItemPerm(uint32 i)
1322 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1323 return;
1324 if (!itemTarget)
1325 return;
1327 Player* p_caster = (Player*)m_caster;
1329 p_caster->UpdateCraftSkill(m_spellInfo->Id);
1331 if (m_spellInfo->EffectMiscValue[i])
1333 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
1335 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1336 if(!pEnchant)
1337 return;
1339 // item can be in trade slot and have owner diff. from caster
1340 Player* item_owner = itemTarget->GetOwner();
1341 if(!item_owner)
1342 return;
1344 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > 0 && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
1345 sLog.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1346 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
1347 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
1348 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
1350 // remove old enchanting before appling new if equiped
1351 if(itemTarget->IsEquipped())
1352 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT))
1353 item_owner->AddItemEnchant(itemTarget,old_enchant_id,false);
1355 for(int x=0;x<3;x++)
1356 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+x,0);
1358 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, enchant_id);
1360 // add new enchanting if equiped
1361 if(itemTarget->IsEquipped())
1362 item_owner->AddItemEnchant(itemTarget,enchant_id,true);
1364 itemTarget->SetState(ITEM_CHANGED);
1368 void Spell::EffectEnchantItemTmp(uint32 i)
1370 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1371 return;
1373 Player* p_caster = (Player*)m_caster;
1375 if(!itemTarget)
1376 return;
1378 if (m_spellInfo->EffectMiscValue[i])
1380 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
1381 int32 duration = GetDuration(m_spellInfo);
1382 if(duration == 0)
1383 duration = m_spellInfo->EffectBasePoints[i]+1;
1384 if(duration <= 1)
1385 duration = 300;
1386 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1387 if(!pEnchant)
1388 return;
1390 // item can be in trade slot and have owner diff. from caster
1391 Player* item_owner = itemTarget->GetOwner();
1392 if(!item_owner)
1393 return;
1395 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > 0 && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
1396 sLog.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
1397 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
1398 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
1399 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
1401 // remove old enchanting before applying new if equipped
1402 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+1*3))
1404 if(itemTarget->IsEquipped())
1405 item_owner->AddItemEnchant(itemTarget,old_enchant_id,false);
1407 // duration == 0 will remove EnchantDuration
1408 item_owner->AddEnchantDuration(itemTarget,1,0);
1411 for(int x=0;x<3;x++)
1412 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3+x,0);
1414 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3, enchant_id);
1415 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3+1, duration*1000);
1416 if(m_spellInfo->SpellFamilyName == 8)
1417 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+3+2, 45+objmgr.GetSpellRank(m_spellInfo->Id)*15);
1419 // add new enchanting if equipped
1420 if(itemTarget->IsEquipped())
1421 item_owner->AddItemEnchant(itemTarget,enchant_id,true);
1423 itemTarget->SetState(ITEM_CHANGED);
1425 // set duration
1426 item_owner->AddEnchantDuration(itemTarget,1,duration*1000);
1430 void Spell::EffectTameCreature(uint32 i)
1432 if(m_caster->GetPetGUID())
1433 return;
1435 if(!unitTarget)
1436 return;
1438 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1439 return;
1441 Creature* creatureTarget = (Creature*)unitTarget;
1443 if(creatureTarget->isPet())
1444 return;
1446 if(m_caster->getClass() == CLASS_HUNTER)
1448 creatureTarget->AttackStop();
1449 if(m_caster->getVictim()==creatureTarget)
1450 m_caster->AttackStop();
1452 creatureTarget->CombatStop();
1453 creatureTarget->StopMoving();
1455 // cast finish succesfully
1456 SendChannelUpdate(0);
1457 finish();
1459 Pet* pet = new Pet(HUNTER_PET);
1461 pet->CreateBaseAtCreature(creatureTarget);
1463 ObjectAccessor::Instance().RemoveCreatureCorpseFromPlayerView(creatureTarget);
1464 creatureTarget->setDeathState(JUST_DIED);
1466 pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
1467 pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1468 pet->SetMaxPower(POWER_HAPPINESS,1000000);
1469 pet->SetPower( POWER_HAPPINESS,600000);
1470 pet->setPowerType(POWER_FOCUS);
1471 pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1472 pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
1473 pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1474 pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1475 pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN1 + UNIT_FLAG_RESTING + UNIT_FLAG_RENAME);
1476 // this enables popup window (pet detals, abandon, rename)
1477 pet->SetUInt32Value(UNIT_FIELD_PETNUMBER,1);
1478 // this enables pet detals window (Shift+P)
1479 pet->AIM_Initialize();
1481 pet->AddToWorld();
1482 MapManager::Instance().GetMap(pet->GetMapId())->Add((Creature*)pet);
1484 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1486 m_caster->SetPet(pet);
1487 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
1488 ((Player*)m_caster)->PetSpellInitialize();
1493 void Spell::EffectSummonPet(uint32 i)
1495 float px, py, pz;
1496 m_caster->GetClosePoint(NULL, px, py, pz);
1498 uint32 petentry = m_spellInfo->EffectMiscValue[i];
1500 Pet *OldSummon = m_caster->GetPet();
1502 // if pet requested type already exist
1503 if( OldSummon )
1506 if(petentry == 0 || OldSummon->GetCreatureInfo()->Entry == petentry)
1508 // pet in corpse state can't be summoned
1509 if( OldSummon->isDead() )
1510 return;
1512 MapManager::Instance().GetMap(OldSummon->GetMapId())->Remove((Creature*)OldSummon,false);
1513 OldSummon->SetMapId(m_caster->GetMapId());
1514 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
1515 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)OldSummon);
1517 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
1519 ((Player*)m_caster)->PetSpellInitialize();
1521 return;
1524 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1525 ((Player*)m_caster)->RemovePet(OldSummon,PET_SAVE_AS_DELETED);
1526 else
1527 return;
1530 Pet* NewSummon = new Pet(m_caster->getClass() == CLASS_HUNTER ? HUNTER_PET : SUMMON_PET);
1532 // petentry==0 for hunter "call pet" (current pet summoned if any)
1533 if(NewSummon->LoadPetFromDB(m_caster,petentry))
1535 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
1536 return;
1539 // not error in case fail hunter call pet
1540 if(!petentry)
1541 return;
1543 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
1545 if(!cInfo)
1547 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
1548 return;
1551 if( NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMapId(), px, py, pz+1, m_caster->GetOrientation(), petentry))
1553 uint32 petlevel = m_caster->getLevel();
1555 NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
1556 NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
1557 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0);
1558 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
1559 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
1560 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
1561 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,5);
1562 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
1563 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
1564 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
1565 NewSummon->SetUInt32Value(UNIT_FIELD_PETNUMBER,1); // this enables pet detals window (Shift+P)
1567 // this enables popup window (pet dismiss, cancel), hunter pet additinal flags set later
1568 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_UNKNOWN1);
1570 NewSummon->InitStatsForLevel( petlevel);
1572 for(uint32 i=0; i < CREATURE_MAX_SPELLS; i++)
1573 NewSummon->m_spells[i] = 0;
1575 if(petentry == 416) //imp
1577 NewSummon->m_spells[0] = 3110; //3110---fire bolt 1
1578 NewSummon->AddActState(STATE_RA_SPELL1);
1581 // generate new name for summon pet
1582 if(NewSummon->getPetType()==SUMMON_PET)
1584 std::string new_name=objmgr.GeneratePetName(petentry);
1585 if(new_name!="")
1586 NewSummon->SetName(new_name);
1588 else if(NewSummon->getPetType()==HUNTER_PET)
1590 // this enables popup window (pet detals, abandon, rename)
1591 NewSummon->SetFlag(UNIT_FIELD_FLAGS,(UNIT_FLAG_RESTING | UNIT_FLAG_RENAME));
1594 NewSummon->AIM_Initialize();
1596 NewSummon->AddToWorld();
1597 MapManager::Instance().GetMap(NewSummon->GetMapId())->Add((Creature*)NewSummon);
1599 m_caster->SetPet(NewSummon);
1600 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
1602 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1604 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
1605 ((Player*)m_caster)->PetSpellInitialize();
1608 else
1609 delete NewSummon;
1612 void Spell::EffectLearnPetSpell(uint32 i)
1614 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1615 return;
1617 Player *_player = (Player*)m_caster;
1619 Pet *pet = _player->GetPet();
1620 if(!pet)
1621 return;
1622 if(!pet->isAlive())
1623 return;
1625 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
1626 if(!learn_spellproto)
1627 return;
1629 for(int8 x=0;x<4;x++)
1631 SpellEntry const *has_spellproto = sSpellStore.LookupEntry(pet->m_spells[x]);
1632 if(!has_spellproto)
1634 pet->m_spells[x] = learn_spellproto->Id;
1635 break;
1637 else if(has_spellproto->SpellIconID == learn_spellproto->SpellIconID)
1639 pet->m_spells[x] = learn_spellproto->Id;
1640 break;
1643 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
1644 _player->PetSpellInitialize();
1647 void Spell::EffectAttackMe(uint32 i)
1649 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
1651 unitTarget->SetInFront(m_caster);
1652 ((Creature*)unitTarget)->AI().AttackStart(m_caster);
1656 void Spell::EffectWeaponDmg(uint32 i)
1658 if(!unitTarget)
1659 return;
1660 if(!unitTarget->isAlive())
1661 return;
1663 uint32 wp[4] = { SPELL_EFFECT_WEAPON_DAMAGE, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE, SPELL_EFFECT_NORMALIZED_WEAPON_DMG, SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL };
1665 // multiple weap dmg effect workaround
1666 // execute only the first weapon damage
1667 // and handle all effects at once
1668 uint8 j,k;
1669 int32 bonus = 0;
1671 for (j = 0; j < 3; j++)
1673 for (k = 0; k < 4; k++)
1674 if (m_spellInfo->Effect[j] == wp[k])
1675 break;
1676 if (k != 4)
1678 if (j < i)
1679 return;
1680 if (m_spellInfo->Effect[j] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE)
1681 bonus += m_spellInfo->EffectBasePoints[j]+1;
1685 WeaponAttackType attType = BASE_ATTACK;
1686 if(m_spellInfo->rangeIndex != 1 && m_spellInfo->rangeIndex != 2 && m_spellInfo->rangeIndex != 7)
1687 attType = RANGED_ATTACK;
1689 uint32 hitInfo = 0;
1690 uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
1691 uint32 damageType = NORMAL_DAMAGE;
1692 uint32 victimState = VICTIMSTATE_NORMAL;
1693 uint32 damage = 0;
1694 uint32 blocked_dmg = 0;
1695 uint32 absorbed_dmg = 0;
1696 uint32 resisted_dmg = 0;
1697 bool criticalhit = false;
1699 if( unitTarget->IsImmunedToPhysicalDamage() )
1701 m_caster->SendAttackStateUpdate (HITINFO_MISS, unitTarget, 1, NORMAL_DAMAGE, 0, 0, 0, VICTIMSTATE_IS_IMMUNE, 0);
1702 return;
1705 m_caster->DoAttackDamage(unitTarget, &damage, &blocked_dmg, &damageType, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, attType, m_spellInfo, m_IsTriggeredSpell);
1707 // not add bonus to 0 damage
1708 if( damage > 0 && damage + bonus > 0 )
1709 damage += bonus;
1710 else
1711 damage = 0;
1713 for (j = 0; j < 3; j++)
1714 if (m_spellInfo->Effect[j] == SPELL_EFFECT_WEAPON_PERCENT_DAMAGE)
1715 damage = uint32(damage * (m_spellInfo->EffectBasePoints[j]+1) / 100);
1717 if (hitInfo & nohitMask)
1718 m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellInfo->School, damage, absorbed_dmg, resisted_dmg, 1, blocked_dmg);
1720 if(hitInfo & HITINFO_CRITICALHIT)
1721 criticalhit = true;
1723 m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage + absorbed_dmg + resisted_dmg + blocked_dmg, m_spellInfo->School, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
1724 m_caster->DealDamage(unitTarget, damage, SPELL_DIRECT_DAMAGE, 0, true);
1726 // take ammo
1727 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1729 if(m_spellInfo->rangeIndex != 1 && m_spellInfo->rangeIndex != 2 && m_spellInfo->rangeIndex != 7)
1731 Item *pItem = ((Player*)m_caster)->GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED );
1732 if(!pItem || pItem->IsBroken())
1733 return;
1735 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
1737 uint32 count = 1;
1738 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
1740 else
1741 if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
1742 ((Player*)m_caster)->DestroyItemCount( ammo , 1, true);
1743 // wand not have ammo
1747 /*if(m_spellInfo->Effect[i] == 121)
1749 m_caster->resetAttackTimer(BASE_ATTACK);
1750 m_caster->resetAttackTimer(OFF_ATTACK);
1751 m_caster->resetAttackTimer(RANGED_ATTACK);
1755 void Spell::EffectThreat(uint32 i)
1757 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
1758 return;
1759 unitTarget->AddHostil(m_caster->GetGUID(),float(damage));
1762 void Spell::EffectHealMaxHealth(uint32 i)
1764 if(!unitTarget)
1765 return;
1766 if(!unitTarget->isAlive())
1767 return;
1769 uint32 heal = m_caster->GetMaxHealth();
1771 unitTarget->ModifyHealth(heal);
1773 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1774 SendHealSpellOnPlayer((Player*)unitTarget, m_spellInfo->Id, heal);
1777 void Spell::EffectInterruptCast(uint32 i)
1779 if(!unitTarget)
1780 return;
1781 if(!unitTarget->isAlive())
1782 return;
1784 // TODO: not all spells that used this effect apply cooldown at school spells
1785 // also exist case: apply cooldown to interupted cast only and to all spells
1786 if (unitTarget->m_currentSpell && unitTarget->m_currentSpell->m_spellInfo)
1788 unitTarget->ProhibitSpellScholl(unitTarget->m_currentSpell->m_spellInfo->School, GetDuration(m_spellInfo));
1789 unitTarget->InterruptSpell();
1793 void Spell::EffectSummonObjectWild(uint32 i)
1795 GameObject* pGameObj = new GameObject();
1797 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
1799 WorldObject* target = focusObject;
1800 if( !target )
1801 target = m_caster;
1803 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, target->GetMapId(),
1804 target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),
1805 target->GetOrientation(), 0, 0, 0, 0, 0, 0))
1807 delete pGameObj;
1808 return;
1810 pGameObj->SetRespawnTime(GetDuration(m_spellInfo)/1000);
1812 m_caster->AddGameObject(pGameObj);
1813 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
1816 void Spell::EffectScriptEffect(uint32 i)
1818 if(!m_spellInfo->Reagent[0])
1820 // paladin's holy light / flash of light
1821 if ((m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN) &&
1822 (m_spellInfo->SpellIconID == 70 || m_spellInfo->SpellIconID == 242))
1823 EffectHeal( i );
1825 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && (m_spellInfo->SpellFamilyFlags & (1<<23)))
1827 // paladin's judgement
1828 if(!unitTarget || !unitTarget->isAlive())
1829 return;
1830 uint32 spellId2 = 0;
1831 Unit::AuraMap& m_auras = m_caster->GetAuras();
1832 Unit::AuraMap::iterator itr,next;
1834 for(itr = m_auras.begin(); itr != m_auras.end(); itr = next)
1836 next = itr;
1837 next++;
1838 if (itr->second)
1840 SpellEntry const *spellInfo = itr->second->GetSpellProto();
1841 if (!spellInfo) continue;
1842 if (spellInfo->SpellVisual != 5622 || spellInfo->SpellFamilyName != SPELLFAMILY_PALADIN) continue;
1843 spellId2 = spellInfo->EffectBasePoints[2]+1;
1844 if(spellId2 <= 1)
1845 continue;
1846 m_caster->RemoveAurasDueToSpell(spellInfo->Id);
1847 next = m_auras.begin();
1848 break;
1852 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId2);
1853 if(!spellInfo)
1854 return;
1855 Spell *p_spell = new Spell(m_caster,spellInfo,true,0);
1857 SpellCastTargets targets;
1858 Unit *ptarget = unitTarget;
1859 targets.setUnitTarget(ptarget);
1860 p_spell->prepare(&targets);
1862 delete p_spell; // triggered spell not self deleted
1865 else
1867 uint32 itemtype;
1868 switch(m_spellInfo->Id)
1870 case 6201:
1871 itemtype = 5512; //spell 6261; //primary healstone
1872 break;
1873 case 6202:
1874 itemtype = 5511; //spell 6262; //inferior healstone
1875 break;
1876 case 5699:
1877 itemtype = 5509; //spell 5720; //healstone
1878 break;
1879 case 11729:
1880 itemtype = 5510; //spell 5723; //strong healstone
1881 break;
1882 case 11730:
1883 itemtype = 9421; //spell 11732; //super healstone
1884 break;
1885 default:
1886 return;
1888 DoCreateItem( i, itemtype );
1892 void Spell::EffectAddComboPoints(uint32 i)
1894 if(!unitTarget)
1895 return;
1897 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1898 return;
1900 uint8 comboPoints = ((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & 0xFF00) >> 8);
1901 if(m_caster->GetUInt64Value(PLAYER_FIELD_COMBO_TARGET) != unitTarget->GetGUID())
1903 comboPoints = damage;
1904 m_caster->SetUInt64Value(PLAYER_FIELD_COMBO_TARGET,unitTarget->GetGUID());
1905 m_caster->SetUInt32Value(PLAYER_FIELD_BYTES,((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & ~(0xFF << 8)) | (comboPoints << 8)));
1907 else if(comboPoints < 5)
1909 comboPoints += damage;
1910 if(comboPoints > 5)
1911 comboPoints = 5;
1912 m_caster->SetUInt32Value(PLAYER_FIELD_BYTES,((m_caster->GetUInt32Value(PLAYER_FIELD_BYTES) & ~(0xFF << 8)) | (comboPoints << 8)));
1917 void Spell::EffectDuel(uint32 i)
1919 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
1920 return;
1922 Player *caster = (Player*)m_caster;
1923 Player *target = (Player*)unitTarget;
1925 // caster or target already have requested duel
1926 if( caster->duel || target->duel || target->HasInIgnoreList(caster->GetGUID()) )
1927 return;
1929 //CREATE DUEL FLAG OBJECT
1930 GameObject* pGameObj = new GameObject();
1932 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
1934 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,m_caster->GetMapId(),
1935 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
1936 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
1937 m_caster->GetPositionZ(),
1938 m_caster->GetOrientation(), 0, 0, 0, 0, 0, 0))
1940 delete pGameObj;
1941 return;
1943 pGameObj->SetFloatValue(OBJECT_FIELD_SCALE_X,1.0f);
1945 pGameObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 787 );
1946 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
1947 pGameObj->SetUInt32Value(GAMEOBJECT_TYPE_ID, 16 );
1948 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
1949 pGameObj->SetRespawnTime(GetDuration(m_spellInfo)/1000);
1950 pGameObj->SetSpellId(m_spellInfo->Id);
1952 m_caster->AddGameObject(pGameObj);
1953 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
1954 //END
1956 //Send request
1957 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
1958 data << pGameObj->GetGUID();
1959 data << caster->GetGUID();
1960 caster->GetSession()->SendPacket(&data);
1961 target->GetSession()->SendPacket(&data);
1963 // create duel-info
1964 DuelInfo *duel = new DuelInfo;
1965 duel->initiator = caster;
1966 duel->opponent = target;
1967 duel->startTime = 0;
1968 duel->startTimer = 0;
1969 caster->duel = duel;
1971 DuelInfo *duel2 = new DuelInfo;
1972 duel2->initiator = caster;
1973 duel2->opponent = caster;
1974 duel2->startTime = 0;
1975 duel2->startTimer = 0;
1976 target->duel = duel2;
1978 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
1979 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
1983 void Spell::EffectSummonTotem(uint32 i)
1985 uint8 slot = 0;
1986 switch(m_spellInfo->Effect[i])
1988 case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: slot = 0; break;
1989 case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: slot = 1; break;
1990 case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: slot = 2; break;
1991 case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: slot = 3; break;
1992 default: return;
1995 float angle = m_caster->GetOrientation() + M_PI/4 - (slot*M_PI/2);
1996 float x = m_caster->GetPositionX() + 2 * cos(angle);
1997 float y = m_caster->GetPositionY() + 2 * sin(angle);
1998 float z = m_caster->GetPositionZ();
2000 Map* map = MapManager::Instance().GetMap(m_caster->GetMapId());
2001 float z2 = map->GetHeight(x,y);
2002 if( abs( z2 - z ) < 5 )
2003 z = z2;
2005 uint64 guid = m_caster->m_TotemSlot[slot];
2006 if(guid != 0)
2008 Creature *OldTotem = ObjectAccessor::Instance().GetCreature(*m_caster, guid);
2009 if(OldTotem && OldTotem->isTotem()) ((Totem*)OldTotem)->UnSummon();
2010 m_caster->m_TotemSlot[slot] = 0;
2013 Totem* pTotem = new Totem();
2015 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),
2016 m_caster->GetMapId(), x, y, z, m_caster->GetOrientation(),
2017 m_spellInfo->EffectMiscValue[i] ))
2019 delete pTotem;
2020 return;
2023 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
2024 pTotem->SetOwner(m_caster->GetGUID());
2025 //pTotem->SetSpell(pTotem->GetCreatureInfo()->spell1);
2026 pTotem->SetSpell(m_spellInfo->Id); //use SummonTotem spellid
2027 pTotem->SetDuration(GetDuration(m_spellInfo));
2028 pTotem->SetHealth(5);
2029 pTotem->SetMaxHealth(5);
2030 pTotem->Summon();
2033 void Spell::EffectEnchantHeldItem(uint32 i)
2035 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2036 return;
2038 Player* p_caster = (Player*)m_caster;
2040 if(!itemTarget)
2041 return;
2043 // must be equipped
2044 if(!itemTarget->IsEquipped())
2045 return;
2047 if (m_spellInfo->EffectMiscValue[i])
2049 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
2050 int32 duration = GetDuration(m_spellInfo);
2051 if(duration == 0)
2052 duration = m_spellInfo->EffectBasePoints[i]+1;
2053 if(duration <= 1)
2054 duration = 300;
2055 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
2056 if(!pEnchant)
2057 return;
2059 // can be held by another player and accessable to caster in trade slot
2060 Player* item_owner = itemTarget->GetOwner();
2061 if(!item_owner)
2062 return;
2064 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > 0 && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
2065 sLog.outCommand("GM Enchanting: %s (Entry: %d) GM: %s (Account: %u) Player: %s (Account: %u)",
2066 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
2067 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
2068 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
2070 // remove old enchanting before appling new
2071 if(uint32 old_enchant_id = itemTarget->GetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3))
2072 item_owner->AddItemEnchant(itemTarget,old_enchant_id,false);
2074 for(int x=0;x<3;x++)
2075 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+x,0);
2077 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3, enchant_id);
2078 itemTarget->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+pEnchant->display_type*3+1, duration*1000);
2079 itemTarget->SetState(ITEM_CHANGED);
2081 // add new enchanting
2082 item_owner->AddItemEnchant(itemTarget,enchant_id,true);
2084 // set duration
2085 item_owner->AddEnchantDuration(itemTarget,1,duration*1000);
2089 void Spell::EffectDisEnchant(uint32 i)
2091 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2092 return;
2094 Player* p_caster = (Player*)m_caster;
2095 if(!itemTarget)
2096 return;
2097 uint32 item_level = itemTarget->GetProto()->ItemLevel;
2098 uint32 item_quality = itemTarget->GetProto()->Quality;
2100 uint32 item = 0;
2101 uint32 count = 0;
2102 if(item_level >= 66)
2105 count = 1;
2106 item = 20725;
2109 else if(item_level >= 51 && item_level <= 65)
2111 if(item_quality == 4)
2113 count = urand(3,5);
2114 item = 14344;
2116 else if(item_quality == 3)
2118 count = 1;
2119 item = 14344;
2121 else if(item_quality == 2)
2123 count = urand(1,(item_level/10));
2124 if(urand(1,100)< 85)
2125 item = 16204;
2126 else
2127 item = 16203;
2130 else if(item_level >= 46 && item_level <= 50)
2132 if(item_quality == 4)
2134 count = urand(3,5);
2135 item = 14343;
2137 else if(item_quality == 3)
2139 count = 1;
2140 item = 14343;
2142 else if(item_quality == 2)
2144 count = urand(1,(item_level/10));
2145 if(urand(1,100)< 85)
2146 item = 11176;
2147 else
2148 item = 16202;
2151 else if(item_level >= 41 && item_level <= 45)
2153 if(item_quality == 4)
2155 count = urand(3,5);
2156 item = 11178;
2158 else if(item_quality == 3)
2160 count = 1;
2161 item = 11178;
2163 else if(item_quality == 2)
2165 count = urand(1,(item_level/10));
2166 if(urand(1,100)< 85)
2167 item = 11176;
2168 else
2169 item = 11175;
2172 else if(item_level >= 36 && item_level <= 40)
2174 if(item_quality == 4)
2176 count = urand(3,5);
2177 item = 11177;
2179 else if(item_quality == 3)
2181 count = 1;
2182 item = 11177;
2184 else if(item_quality == 2)
2186 count = urand(1,(item_level/10));
2187 if(urand(1,100)< 85)
2188 item = 11137;
2189 else
2190 item = 11174;
2193 else if(item_level >= 31 && item_level <= 35)
2195 if(item_quality == 4)
2197 count = urand(3,5);
2198 item = 11139;
2200 else if(item_quality == 3)
2202 count = 1;
2203 item = 11139;
2205 else if(item_quality == 2)
2207 count = (item_level/10);
2208 if(urand(1,100)< 85)
2209 item = 11137;
2210 else
2211 item = 11135;
2214 else if(item_level >= 25 && item_level <= 30)
2216 if(item_quality == 4)
2218 count = urand(3,5);
2219 item = 11138;
2221 else if(item_quality == 3)
2223 count = 1;
2224 item = 11138;
2226 else if(item_quality == 2)
2228 count = (item_level/10);
2229 if(urand(1,100)< 85)
2230 item = 11083;
2231 else
2232 item = 11134;
2235 else if(item_level >= 21 && item_level <= 25)
2237 if(item_quality == 4)
2239 count = urand(3,5);
2240 item = 11084;
2242 else if(item_quality == 3)
2244 count = 1;
2245 item = 11084;
2247 else if(item_quality == 2)
2249 count = (item_level/10);
2250 if(urand(1,100)< 85)
2251 item = 11083;
2252 else
2253 item = 11082;
2256 else if(item_level >= 1 && item_level <= 20)
2258 if(item_quality == 4)
2260 count = urand(3,5);
2261 item = 10978;
2263 else if(item_quality == 3 && item_level >=16)
2265 count = 1;
2266 item = 10978;
2268 else if(item_quality == 2)
2270 if(urand(1,100)< 70)
2272 count = urand(1,3);
2273 item = 10940;
2275 else if(item_level <=15 && urand(1,100)< 70 )
2277 count = urand(1,3);
2278 item = 10938;
2280 else if(urand(1,100)< 50)
2282 count = urand(1,3);
2283 item = 10939;
2285 else
2287 count = urand(1,3);
2288 item = 10998;
2293 if ( item == 0 || count == 0 )
2294 { //Fix crash
2295 SendCastResult(CAST_FAIL_CANT_BE_DISENCHANTED);
2296 //SendChannelUpdate(0);
2297 return;
2300 uint32 item_count = 1;
2301 p_caster->DestroyItemCount(itemTarget,item_count, true);
2302 p_caster->UpdateCraftSkill(m_spellInfo->Id);
2304 uint16 dest;
2305 uint8 msg = p_caster->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item, count, false );
2306 if( msg == EQUIP_ERR_OK )
2307 p_caster->StoreNewItem( dest, item, count, true );
2308 else
2309 p_caster->SendEquipError( msg, NULL, NULL );
2310 return ;
2313 void Spell::EffectInebriate(uint32 i)
2315 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2316 return;
2318 Player *player = (Player*)m_caster;
2319 uint16 currentDrunk = player->GetDrunkValue();
2320 uint16 drunkMod = (m_spellInfo->EffectBasePoints[i]+1) * 0xFFFF / 100;
2321 if (currentDrunk + drunkMod > 0xFFFF)
2322 currentDrunk = 0xFFFF;
2323 else
2324 currentDrunk += drunkMod;
2325 player->SetDrunkValue(currentDrunk);
2328 void Spell::EffectFeedPet(uint32 i)
2330 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2331 return;
2333 Player *_player = (Player*)m_caster;
2335 if(!itemTarget)
2336 return;
2338 Creature *pet = _player->GetPet();
2339 if(!pet)
2340 return;
2341 if(!pet->isAlive())
2342 return;
2344 pet->ModifyPower(POWER_HAPPINESS,damage);
2346 uint32 count = 1;
2347 _player->DestroyItemCount(itemTarget,count,true);
2349 SpellEntry const *spellinfo = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
2350 Spell _spell(m_caster, spellinfo, true, 0);
2351 SpellCastTargets targets;
2352 targets.setUnitTarget(m_caster);
2353 _spell.prepare(&targets);
2356 void Spell::EffectDismissPet(uint32 i)
2358 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2359 return;
2361 Pet* pet = m_caster->GetPet();
2363 // not let dismiss dead pet
2364 if(!pet||!pet->isAlive())
2365 return;
2367 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_AS_CURRENT);
2370 void Spell::EffectSummonObject(uint32 i)
2372 uint8 slot = 0;
2373 switch(m_spellInfo->Effect[i])
2375 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
2376 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
2377 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
2378 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
2379 default: return;
2382 uint64 guid = m_caster->m_ObjectSlot[slot];
2383 if(guid != 0)
2385 GameObject* obj = NULL;
2386 if( m_caster )
2387 obj = ObjectAccessor::Instance().GetGameObject(*m_caster, guid);
2389 if(obj) obj->Delete();
2390 m_caster->m_ObjectSlot[slot] = 0;
2393 GameObject* pGameObj = new GameObject();
2394 uint32 display_id = m_spellInfo->EffectMiscValue[i];
2396 float rot2 = sin(m_caster->GetOrientation()/2);
2397 float rot3 = cos(m_caster->GetOrientation()/2);
2399 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))
2401 delete pGameObj;
2402 return;
2405 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
2406 pGameObj->SetRespawnTime(GetDuration(m_spellInfo)/1000);
2407 pGameObj->SetSpellId(m_spellInfo->Id);
2408 pGameObj->SetLootState(GO_CLOSED);
2409 m_caster->AddGameObject(pGameObj);
2411 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
2412 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM, 8);
2413 data << pGameObj->GetGUID();
2414 m_caster->SendMessageToSet(&data,true);
2416 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
2419 void Spell::EffectResurrect(uint32 i)
2422 if(!unitTarget)
2423 return;
2424 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
2425 return;
2427 if(unitTarget->isAlive())
2428 return;
2429 if(!unitTarget->IsInWorld())
2430 return;
2432 Player* pTarget = ((Player*)unitTarget);
2434 uint32 health = m_spellInfo->EffectBasePoints[i]+1;
2435 uint32 mana = m_spellInfo->EffectMiscValue[i];
2437 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
2438 SendResurrectRequest(pTarget);
2441 void Spell::EffectParry(uint32 i)
2443 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
2445 ((Player*)unitTarget)->SetCanParry(true);
2449 void Spell::EffectMomentMove(uint32 i)
2451 if(unitTarget->isInFlight())
2452 return;
2454 if( m_spellInfo->rangeIndex== 1) //self range
2456 uint32 mapid = m_caster->GetMapId();
2457 float dis = GetRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2458 float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
2459 float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
2460 // teleport a bit above terrainlevel to avoid falling below it
2461 float fz = MapManager::Instance ().GetMap(mapid)->GetHeight(fx,fy) + 1.5;
2463 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2464 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, m_caster->GetOrientation(), false);
2465 else
2466 MapManager::Instance().GetMap(mapid)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, m_caster->GetOrientation());
2470 void Spell::EffectReputation(uint32 i)
2472 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2473 return;
2475 Player *_player = (Player*)m_caster;
2477 int32 rep_change = m_spellInfo->EffectBasePoints[i]+1; // field store reputation change -1
2479 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
2481 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
2483 if(!factionEntry)
2484 return;
2486 _player->ModifyFactionReputation(factionEntry,rep_change);
2489 void Spell::EffectQuestComplete(uint32 i)
2491 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2492 return;
2494 Player *_player = (Player*)m_caster;
2496 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
2498 if(_player->CanCompleteQuest( quest_id ) )
2499 _player->CompleteQuest( quest_id );
2500 else
2501 return;
2503 if(_player->GetQuestRewardStatus( quest_id ))
2504 return;
2506 _player->PlayerTalkClass->SendQuestGiverOfferReward( quest_id, _player->GetGUID(), true, NULL, 0 );
2509 void Spell::EffectSelfResurrect(uint32 i)
2511 if(!unitTarget) return;
2512 if(unitTarget->GetTypeId() != TYPEID_PLAYER) return;
2513 if(unitTarget->isAlive()) return;
2514 if(!unitTarget->IsInWorld()) return;
2516 uint32 health = 0;
2517 uint32 mana = 0;
2519 if(m_spellInfo->SpellVisual == 99 && m_spellInfo->SpellIconID ==1)
2521 health = m_spellInfo->EffectBasePoints[i]+1 > 0 ? m_spellInfo->EffectBasePoints[i]+1 :(-(m_spellInfo->EffectBasePoints[i]+1));
2522 if(unitTarget->getPowerType() == POWER_MANA)
2523 mana = m_spellInfo->EffectMiscValue[i];
2525 else
2527 health = uint32(damage/100*unitTarget->GetMaxHealth());
2528 if(unitTarget->getPowerType() == POWER_MANA)
2529 mana = uint32(damage/100*unitTarget->GetMaxPower(unitTarget->getPowerType()));
2531 ((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
2532 SendResurrectRequest((Player*)unitTarget);
2535 void Spell::EffectSkinning(uint32 i)
2537 if(unitTarget->GetTypeId() != TYPEID_UNIT )
2538 return;
2539 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2540 return;
2542 int32 targetLevel = unitTarget->getLevel();
2544 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_SKINNING);
2545 unitTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
2547 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
2549 int32 skinningValue = ((Player*)m_caster)->GetPureSkillValue(SKILL_SKINNING);
2551 // Double chances for elites
2552 ((Player*)m_caster)->UpdateGatherSkill(SKILL_SKINNING, skinningValue, reqValue, ((Creature*)unitTarget)->isElite() ? 2 : 1 );
2555 void Spell::EffectCharge(uint32 i)
2557 if(!unitTarget || !m_caster)
2558 return;
2560 float x, y, z;
2561 unitTarget->GetClosePoint(m_caster, x, y, z);
2562 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
2563 ((Creature *)unitTarget)->StopMoving();
2565 m_caster->SendMonsterMove(x, y, z, false,true,1);
2566 m_caster->Attack(unitTarget);
2569 void Spell::EffectSummonCritter(uint32 i)
2571 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
2572 if(!pet_entry)
2573 return;
2575 Unit* old_critter = NULL;
2578 CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
2579 Cell cell = RedZone::GetZone(p);
2580 cell.data.Part.reserved = ALL_DISTRICT;
2581 cell.SetNoCreate();
2583 PetWithIdCheck u_check(m_caster, pet_entry);
2584 MaNGOS::UnitSearcher<PetWithIdCheck> checker(old_critter, u_check);
2585 TypeContainerVisitor<MaNGOS::UnitSearcher<PetWithIdCheck>, TypeMapContainer<AllObjectTypes> > object_checker(checker);
2586 CellLock<GridReadGuard> cell_lock(cell, p);
2587 cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId()));
2590 if (old_critter) // find old critter, unsummon
2592 // PetWithIdCheck return only Pets
2593 ((Pet*)old_critter)->Remove(PET_SAVE_AS_DELETED);
2594 return;
2596 else // in another case summon new
2598 Pet* critter = new Pet(MINI_PET);
2600 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),
2601 m_caster->GetMapId(),
2602 m_caster->GetPositionX(),m_caster->GetPositionY(),
2603 m_caster->GetPositionZ(),m_caster->GetOrientation(),
2604 m_spellInfo->EffectMiscValue[i]))
2606 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
2607 delete critter;
2608 return;
2611 critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
2612 critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID());
2613 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
2615 critter->AIM_Initialize();
2617 std::string name;
2618 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2619 name = ((Player*)m_caster)->GetName();
2620 else
2621 name = ((Creature*)m_caster)->GetCreatureInfo()->Name;
2622 name.append(petTypeSuffix[critter->getPetType()]);
2623 critter->SetName( name );
2624 //m_caster->SetPet(critter);
2626 critter->AddToWorld();
2627 MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)critter);
2631 void Spell::EffectKnockBack(uint32 i)
2633 if(!unitTarget || !m_caster)
2634 return;
2636 //Effect only works on players
2637 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
2638 return;
2640 float value = 0;
2641 int32 basePoints = m_spellInfo->EffectBasePoints[i];
2642 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2643 if (randomPoints) value = basePoints + rand()%randomPoints;
2644 else value = basePoints;
2646 //Only allowed to knock ourselves straight up to prevent exploiting
2647 if (unitTarget == m_caster)value = 0;
2649 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
2650 data.append(unitTarget->GetPackGUID());
2651 data << uint32(0); //Sequence
2652 data << cos(m_caster->GetAngle(unitTarget)); //xdirection
2653 data << sin(m_caster->GetAngle(unitTarget)); //ydirection
2654 data << value/10; //Horizontal speed
2655 data << float(m_spellInfo->EffectMiscValue[i])/-10; //Z Movement speed
2657 ((Player*)unitTarget)->SendMessageToSet(&data,true);
2660 void Spell::EffectSummonDeadPet(uint32 i)
2662 if(m_caster->GetTypeId() != TYPEID_PLAYER)
2663 return;
2664 Player *_player = (Player*)m_caster;
2665 Pet *pet = _player->GetPet();
2666 if(!pet)
2667 return;
2668 if(pet->isAlive())
2669 return;
2670 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
2671 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
2672 pet->setDeathState( ALIVE );
2673 pet->clearUnitState(UNIT_STAT_ALL_STATE);
2674 pet->SetHealth( uint32(pet->GetMaxHealth()*damage/100));
2676 pet->AIM_Initialize();
2678 _player->PetSpellInitialize();
2679 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
2682 void Spell::EffectTransmitted(uint32 i)
2684 float fx,fy;
2686 float min_dis = GetMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
2687 float max_dis = GetMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
2688 float diff = max_dis - min_dis + 1;
2689 float dis = (float)(rand()%(uint32)diff + (uint32)min_dis);
2691 fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
2692 fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
2694 float fz = MapManager::Instance ().GetMap(m_caster->GetMapId())->GetHeight(fx,fy);
2696 if(m_spellInfo->EffectMiscValue[i] == 35591)
2698 Map* map = MapManager::Instance().GetMap(m_caster->GetMapId());
2699 if ( !map->IsUnderWater(fx,fy,fz) )
2701 SendCastResult(CAST_FAIL_CANT_BE_CAST_HERE);
2702 up_skillvalue = 4;
2703 SendChannelUpdate(0);
2704 return;
2707 // replace by water level in this case
2708 fz = MapManager::Instance ().GetMap(m_caster->GetMapId())->GetWaterLevel(fx,fy);
2712 GameObject* pGameObj = new GameObject();
2713 uint32 name_id = m_spellInfo->EffectMiscValue[i];
2715 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id,m_caster->GetMapId(),
2716 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 0))
2718 delete pGameObj;
2719 return;
2722 if(m_spellInfo->EffectMiscValue[i] == 35591)
2724 m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUIDLow());
2725 m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_OBJECT+1,pGameObj->GetGUIDHigh());
2726 //Orientation3
2727 pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
2728 //Orientation4
2729 pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
2730 pGameObj->SetLootState(GO_NOT_READY); // bobber not move
2731 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
2733 // end time of range when posable catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
2734 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
2735 uint32 fish = urand(FISHING_BOBBER_READY_TIME,GetDuration(m_spellInfo)/1000);
2736 pGameObj->SetRespawnTime(fish);
2738 else
2740 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
2741 pGameObj->SetRespawnTime(GetDuration(m_spellInfo)/1000);
2744 pGameObj->SetUInt32Value(12, 0x3F63BB3C );
2745 pGameObj->SetUInt32Value(13, 0xBEE9E017 );
2746 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
2747 pGameObj->SetSpellId(m_spellInfo->Id);
2749 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
2750 //m_caster->AddGameObject(pGameObj);
2751 //m_ObjToDel.push_back(pGameObj);
2753 MapManager::Instance().GetMap(pGameObj->GetMapId())->Add(pGameObj);
2754 pGameObj->AddToWorld();
2756 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM, 8);
2757 data << uint64(pGameObj->GetGUID());
2758 m_caster->SendMessageToSet(&data,true);
2761 void Spell::EffectSkill(uint32 i)
2763 sLog.outDebug("WORLD: SkillEFFECT");