Merge commit 'origin/master' into 308
[getmangos.git] / src / game / SpellEffects.cpp
blobda33aa8ccd53e42ddb25e90964f22225b3e8d8a5
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "SharedDefines.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
24 #include "Opcodes.h"
25 #include "Log.h"
26 #include "UpdateMask.h"
27 #include "World.h"
28 #include "ObjectMgr.h"
29 #include "SpellMgr.h"
30 #include "Player.h"
31 #include "SkillExtraItems.h"
32 #include "Unit.h"
33 #include "CreatureAI.h"
34 #include "Spell.h"
35 #include "DynamicObject.h"
36 #include "SpellAuras.h"
37 #include "Group.h"
38 #include "UpdateData.h"
39 #include "MapManager.h"
40 #include "ObjectAccessor.h"
41 #include "SharedDefines.h"
42 #include "Pet.h"
43 #include "GameObject.h"
44 #include "GossipDef.h"
45 #include "Creature.h"
46 #include "Totem.h"
47 #include "CreatureAI.h"
48 #include "BattleGround.h"
49 #include "BattleGroundEY.h"
50 #include "BattleGroundWS.h"
51 #include "VMapFactory.h"
52 #include "Language.h"
53 #include "SocialMgr.h"
54 #include "Util.h"
55 #include "TemporarySummon.h"
56 #include "ScriptCalls.h"
57 #include "SkillDiscovery.h"
59 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
61 &Spell::EffectNULL, // 0
62 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
63 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
64 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
65 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
66 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
67 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
68 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
69 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
70 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
71 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
72 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
73 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
74 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
75 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
76 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
77 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
78 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
79 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
80 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
81 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
82 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
83 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
84 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
85 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
86 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
87 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
88 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
89 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
90 &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
91 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
92 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
93 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
94 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
95 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
96 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
97 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
98 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
99 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
100 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
101 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
102 &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
103 &Spell::EffectUnused, // 42 SPELL_EFFECT_JUMP2
104 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
105 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
106 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
107 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
108 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
109 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
110 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
111 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
112 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
113 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
114 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
115 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
116 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
117 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
118 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
119 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
120 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
121 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
122 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
123 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
124 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
125 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
126 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
127 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
128 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
129 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
130 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
131 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
132 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
133 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
134 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
135 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
136 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
137 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
138 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
139 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
140 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
141 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
142 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
143 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
144 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
145 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
146 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
147 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
148 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
149 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
150 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
151 &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
152 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
153 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
154 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
155 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
156 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
157 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
158 &Spell::EffectUnused, // 97 SPELL_EFFECT_97
159 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
160 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
161 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
162 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
163 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
164 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
165 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
166 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
167 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
168 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
169 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
170 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
171 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
172 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
173 &Spell::EffectUnused, //112 SPELL_EFFECT_112
174 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
175 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
176 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
177 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
178 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
179 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
180 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
181 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
182 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
183 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
184 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
185 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
186 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
187 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
188 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
189 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
190 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
191 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
192 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
193 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
194 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
195 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
196 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
197 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
198 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
199 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
200 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
201 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
202 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
203 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
204 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
205 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
206 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
207 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
208 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
209 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
210 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
211 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
212 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
213 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
214 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
215 &Spell::EffectNULL, //154 unused
216 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
217 &Spell::EffectNULL, //156 Add Socket
218 &Spell::EffectCreateItem, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
219 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
220 &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
223 void Spell::EffectNULL(uint32 /*i*/)
225 sLog.outDebug("WORLD: Spell Effect DUMMY");
228 void Spell::EffectUnused(uint32 /*i*/)
230 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
233 void Spell::EffectResurrectNew(uint32 i)
235 if(!unitTarget || unitTarget->isAlive())
236 return;
238 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
239 return;
241 if(!unitTarget->IsInWorld())
242 return;
244 Player* pTarget = ((Player*)unitTarget);
246 if(pTarget->isRessurectRequested()) // already have one active request
247 return;
249 uint32 health = damage;
250 uint32 mana = m_spellInfo->EffectMiscValue[i];
251 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
252 SendResurrectRequest(pTarget);
255 void Spell::EffectInstaKill(uint32 /*i*/)
257 if( !unitTarget || !unitTarget->isAlive() )
258 return;
260 // Demonic Sacrifice
261 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
263 uint32 entry = unitTarget->GetEntry();
264 uint32 spellID;
265 switch(entry)
267 case 416: spellID=18789; break; //imp
268 case 417: spellID=18792; break; //fellhunter
269 case 1860: spellID=18790; break; //void
270 case 1863: spellID=18791; break; //succubus
271 case 17252: spellID=35701; break; //fellguard
272 default:
273 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
274 return;
277 m_caster->CastSpell(m_caster,spellID,true);
280 if(m_caster==unitTarget) // prevent interrupt message
281 finish();
283 uint32 health = unitTarget->GetHealth();
284 m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
287 void Spell::EffectEnvirinmentalDMG(uint32 i)
289 uint32 absorb = 0;
290 uint32 resist = 0;
292 // Note: this hack with damage replace required until GO casting not implemented
293 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
294 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
295 damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i];
297 m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
299 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
300 if(m_caster->GetTypeId() == TYPEID_PLAYER)
301 ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage);
304 void Spell::EffectSchoolDMG(uint32 effect_idx)
306 if( unitTarget && unitTarget->isAlive())
308 switch(m_spellInfo->SpellFamilyName)
310 case SPELLFAMILY_GENERIC:
312 //Gore
313 if(m_spellInfo->SpellIconID == 2269 )
315 damage+= rand()%2 ? damage : 0;
318 switch(m_spellInfo->Id) // better way to check unknown
320 // Meteor like spells (divided damage to targets)
321 case 24340: case 26558: case 28884: // Meteor
322 case 36837: case 38903: case 41276: // Meteor
323 case 26789: // Shard of the Fallen Star
324 case 31436: // Malevolent Cleave
325 case 35181: // Dive Bomb
326 case 40810: case 43267: case 43268: // Saber Lash
327 case 42384: // Brutal Swipe
328 case 45150: // Meteor Slash
330 uint32 count = 0;
331 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
332 if(ihit->effectMask & (1<<effect_idx))
333 ++count;
335 damage /= count; // divide to all targets
336 break;
338 // percent from health with min
339 case 25599: // Thundercrash
341 damage = unitTarget->GetHealth() / 2;
342 if(damage < 200)
343 damage = 200;
344 break;
346 // Intercept (warrior spell trigger)
347 case 20253:
348 case 61491:
350 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
351 break;
354 break;
357 case SPELLFAMILY_MAGE:
359 // Arcane Blast
360 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
362 m_caster->CastSpell(m_caster,36032,true);
364 break;
366 case SPELLFAMILY_WARRIOR:
368 // Bloodthirst
369 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
371 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
373 // Shield Slam
374 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
375 damage += int32(m_caster->GetShieldBlockValue());
376 // Victory Rush
377 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
379 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
380 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
382 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
383 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL)
384 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
385 // Heroic Throw ${$m1+$AP*.50}
386 else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL)
387 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
388 // Shockwave ${$m3/100*$AP}
389 else if(m_spellInfo->SpellFamilyFlags & 0x0000800000000000LL)
391 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
392 if (pct > 0)
393 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
394 break;
396 break;
398 case SPELLFAMILY_WARLOCK:
400 // Incinerate Rank 1 & 2
401 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
403 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
404 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
405 damage += int32(damage*0.25f);
407 break;
409 case SPELLFAMILY_PRIEST:
411 // Shadow Word: Death - deals damage equal to damage done to caster
412 if (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
413 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
414 break;
416 case SPELLFAMILY_DRUID:
418 // Ferocious Bite
419 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
421 // converts each extra point of energy into ($f1+$AP/410) additional damage
422 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
423 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
424 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
425 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
426 m_caster->SetPower(POWER_ENERGY,0);
428 // Rake
429 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
431 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
433 // Swipe
434 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
436 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
438 // Starfire
439 else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL )
441 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
442 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
444 // Starfire Bonus (caster)
445 switch((*i)->GetModifier()->m_miscvalue)
447 case 5481: // Nordrassil Regalia - bonus
449 Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
450 for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr)
452 // Moonfire or Insect Swarm (target debuff from any casters)
453 if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL )
455 int32 mod = (*i)->GetModifier()->m_amount;
456 damage += damage*mod/100;
457 break;
460 break;
462 case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
464 damage += (*i)->GetModifier()->m_amount;
465 break;
470 //Mangle Bonus for the initial damage of Lacerate and Rake
471 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
472 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
474 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
475 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
476 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
478 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
479 break;
482 break;
484 case SPELLFAMILY_ROGUE:
486 // Envenom
487 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
489 // consume from stack dozes not more that have combo-points
490 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
492 Aura *poison = 0;
493 // Lookup for Deadly poison (only attacker applied)
494 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
495 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
496 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
497 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
498 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
500 poison = *itr;
501 break;
503 // count consumed deadly poison doses at target
504 if (poison)
506 uint32 spellId = poison->GetId();
507 uint32 doses = poison->GetStackAmount();
508 if (doses > combo)
509 doses = combo;
510 for (int i=0; i< doses; i++)
511 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
512 damage *= doses;
513 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
515 // Eviscerate and Envenom Bonus Damage (item set effect)
516 if(m_caster->GetDummyAura(37169))
517 damage += ((Player*)m_caster)->GetComboPoints()*40;
520 // Eviscerate
521 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
523 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
525 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
526 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
528 // Eviscerate and Envenom Bonus Damage (item set effect)
529 if(m_caster->GetDummyAura(37169))
530 damage += combo*40;
533 // Gouge
534 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL)
536 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
538 // Instant Poison
539 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
541 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
543 // Wound Poison
544 else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL)
546 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
548 break;
550 case SPELLFAMILY_HUNTER:
552 // Mongoose Bite
553 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
555 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
557 // Counterattack
558 else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL)
560 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
562 // Arcane Shot
563 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
565 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
567 // Steady Shot
568 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
570 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
571 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
573 // Explosive Trap Effect
574 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
576 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
578 break;
580 case SPELLFAMILY_PALADIN:
582 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
583 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
585 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
586 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
587 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
588 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
589 // Get stack of Holy Vengeance on the target added by caster
590 uint32 stacks = 0;
591 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
592 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
593 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
595 stacks = (*itr)->GetStackAmount();
596 break;
598 // + 10% for each application of Holy Vengeance on the target
599 if(stacks)
600 damage += damage * stacks * 10 /100;
602 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP)
603 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
605 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
606 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
607 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
608 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
610 // Exorcism ($m1+0.15*$SPH+0.15*$AP)
611 else if(m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
613 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
614 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
615 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
616 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
618 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP)
619 else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL)
621 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
622 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
623 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
624 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
626 // Holy Wrath ($m1+0.07*$SPH+0.07*$AP)
627 else if(m_spellInfo->SpellFamilyFlags & 0x0020000000000000LL)
629 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
630 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
631 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
632 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
634 break;
638 if(damage >= 0)
639 m_damage+= damage;
643 void Spell::EffectDummy(uint32 i)
645 if(!unitTarget && !gameObjTarget && !itemTarget)
646 return;
648 // selection by spell family
649 switch(m_spellInfo->SpellFamilyName)
651 case SPELLFAMILY_GENERIC:
653 switch(m_spellInfo->Id )
655 case 8063: // Deviate Fish
657 if(m_caster->GetTypeId() != TYPEID_PLAYER)
658 return;
660 uint32 spell_id = 0;
661 switch(urand(1,5))
663 case 1: spell_id = 8064; break; // Sleepy
664 case 2: spell_id = 8065; break; // Invigorate
665 case 3: spell_id = 8066; break; // Shrink
666 case 4: spell_id = 8067; break; // Party Time!
667 case 5: spell_id = 8068; break; // Healthy Spirit
669 m_caster->CastSpell(m_caster,spell_id,true,NULL);
670 return;
672 case 8213: // Savory Deviate Delight
674 if(m_caster->GetTypeId() != TYPEID_PLAYER)
675 return;
677 uint32 spell_id = 0;
678 switch(urand(1,2))
680 // Flip Out - ninja
681 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
682 // Yaaarrrr - pirate
683 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
685 m_caster->CastSpell(m_caster,spell_id,true,NULL);
686 return;
688 case 8593: // Symbol of life (restore creature to life)
689 case 31225: // Shimmering Vessel (restore creature to life)
691 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
692 return;
693 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
694 return;
696 case 12162: // Deep wounds
697 case 12850: // (now good common check for this spells)
698 case 12868:
700 if(!unitTarget)
701 return;
703 float damage;
704 // DW should benefit of attack power, damage percent mods etc.
705 // TODO: check if using offhand damage is correct and if it should be divided by 2
706 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
707 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
708 else
709 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
711 switch (m_spellInfo->Id)
713 case 12850: damage *= 0.2f; break;
714 case 12162: damage *= 0.4f; break;
715 case 12868: damage *= 0.6f; break;
716 default:
717 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
718 return;
721 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
722 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
723 return;
725 case 13120: // net-o-matic
727 if(!unitTarget)
728 return;
730 uint32 spell_id = 0;
732 uint32 roll = urand(0, 99);
734 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
735 spell_id = 16566;
736 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
737 spell_id = 13119;
738 else // normal root
739 spell_id = 13099;
741 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
742 return;
744 case 13567: // Dummy Trigger
746 // can be used for different aura triggering, so select by aura
747 if(!m_triggeredByAuraSpell || !unitTarget)
748 return;
750 switch(m_triggeredByAuraSpell->Id)
752 case 26467: // Persistent Shield
753 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
754 break;
755 default:
756 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
757 break;
759 return;
761 case 15998: // Capture Worg Pup
762 case 29435: // Capture Female Kaliri Hatchling
764 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
765 return;
767 Creature* creatureTarget = (Creature*)unitTarget;
768 creatureTarget->setDeathState(JUST_DIED);
769 creatureTarget->RemoveCorpse();
770 creatureTarget->SetHealth(0); // just for nice GM-mode view
771 return;
773 case 16589: // Noggenfogger Elixir
775 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
776 return;
778 uint32 spell_id = 0;
779 switch(urand(1,3))
781 case 1: spell_id = 16595; break;
782 case 2: spell_id = 16593; break;
783 default:spell_id = 16591; break;
786 m_caster->CastSpell(m_caster,spell_id,true,NULL);
787 return;
789 case 17251: // Spirit Healer Res
791 if(!unitTarget || !m_originalCaster)
792 return;
794 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
796 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
797 data << unitTarget->GetGUID();
798 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
800 return;
802 case 17271: // Test Fetid Skull
804 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
805 return;
807 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
809 m_caster->CastSpell(m_caster,spell_id,true,NULL);
810 return;
812 case 20577: // Cannibalize
813 if (unitTarget)
814 m_caster->CastSpell(m_caster,20578,false,NULL);
815 return;
816 case 23019: // Crystal Prison Dummy DND
818 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
819 return;
821 Creature* creatureTarget = (Creature*)unitTarget;
822 if(creatureTarget->isPet())
823 return;
825 creatureTarget->setDeathState(JUST_DIED);
826 creatureTarget->RemoveCorpse();
827 creatureTarget->SetHealth(0); // just for nice GM-mode view
829 GameObject* pGameObj = new GameObject;
831 Map *map = creatureTarget->GetMap();
833 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map,
834 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
835 creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) )
837 delete pGameObj;
838 return;
841 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
842 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
843 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
844 pGameObj->SetSpellId(m_spellInfo->Id);
846 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
847 map->Add(pGameObj);
849 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
850 data << uint64(pGameObj->GetGUID());
851 m_caster->SendMessageToSet(&data,true);
853 return;
855 case 23074: // Arcanite Dragonling
856 if (!m_CastItem) return;
857 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
858 return;
859 case 23075: // Mithril Mechanical Dragonling
860 if (!m_CastItem) return;
861 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
862 return;
863 case 23076: // Mechanical Dragonling
864 if (!m_CastItem) return;
865 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
866 return;
867 case 23133: // Gnomish Battle Chicken
868 if (!m_CastItem) return;
869 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
870 return;
871 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
873 int32 r = irand(0, 119);
874 if ( r < 20 ) // 1/6 polymorph
875 m_caster->CastSpell(m_caster,23444,true);
876 else if ( r < 100 ) // 4/6 evil twin
877 m_caster->CastSpell(m_caster,23445,true);
878 else // 1/6 miss the target
879 m_caster->CastSpell(m_caster,36902,true);
880 return;
882 case 23453: // Ultrasafe Transporter: Gadgetzan
883 if ( roll_chance_i(50) ) // success
884 m_caster->CastSpell(m_caster,23441,true);
885 else // failure
886 m_caster->CastSpell(m_caster,23446,true);
887 return;
888 case 23645: // Hourglass Sand
889 m_caster->RemoveAurasDueToSpell(23170);
890 return;
891 case 23725: // Gift of Life (warrior bwl trinket)
892 m_caster->CastSpell(m_caster,23782,true);
893 m_caster->CastSpell(m_caster,23783,true);
894 return;
895 case 25860: // Reindeer Transformation
897 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
898 return;
900 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
901 float speed = m_caster->GetSpeedRate(MOVE_RUN);
903 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
905 //5 different spells used depending on mounted speed and if mount can fly or not
906 if (flyspeed >= 4.1f)
907 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
908 else if (flyspeed >= 3.8f)
909 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
910 else if (flyspeed >= 1.6f)
911 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
912 else if (speed >= 2.0f)
913 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
914 else
915 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
917 return;
919 //case 26074: // Holiday Cheer
920 // return; -- implemented at client side
921 case 28006: // Arcane Cloaking
923 if( unitTarget->GetTypeId() == TYPEID_PLAYER )
924 m_caster->CastSpell(unitTarget,29294,true);
925 return;
927 case 28730: // Arcane Torrent (Mana)
929 Aura * dummy = m_caster->GetDummyAura(28734);
930 if (dummy)
932 int32 bp = damage * dummy->GetStackAmount();
933 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
934 m_caster->RemoveAurasDueToSpell(28734);
936 return;
938 case 29200: // Purify Helboar Meat
940 if( m_caster->GetTypeId() != TYPEID_PLAYER )
941 return;
943 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
945 m_caster->CastSpell(m_caster,spell_id,true,NULL);
946 return;
948 case 29858: // Soulshatter
949 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
950 m_caster->CastSpell(unitTarget,32835,true);
951 return;
952 case 30458: // Nigh Invulnerability
953 if (!m_CastItem) return;
954 if(roll_chance_i(86)) // success
955 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
956 else // backfire in 14% casts
957 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
958 return;
959 case 30507: // Poultryizer
960 if (!m_CastItem) return;
961 if(roll_chance_i(80)) // success
962 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
963 else // backfire 20%
964 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
965 return;
966 case 33060: // Make a Wish
968 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
969 return;
971 uint32 spell_id = 0;
973 switch(urand(1,5))
975 case 1: spell_id = 33053; break;
976 case 2: spell_id = 33057; break;
977 case 3: spell_id = 33059; break;
978 case 4: spell_id = 33062; break;
979 case 5: spell_id = 33064; break;
982 m_caster->CastSpell(m_caster,spell_id,true,NULL);
983 return;
985 case 35745:
987 uint32 spell_id;
988 switch(m_caster->GetAreaId())
990 case 3900: spell_id = 35743; break;
991 case 3742: spell_id = 35744; break;
992 default: return;
995 m_caster->CastSpell(m_caster,spell_id,true);
996 return;
998 case 37674: // Chaos Blast
1000 if(!unitTarget)
1001 return;
1003 int32 basepoints0 = 100;
1004 m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true);
1005 return;
1007 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1009 // selecting one from Bloodstained Fortune item
1010 uint32 newitemid;
1011 switch(urand(1,20))
1013 case 1: newitemid = 32688; break;
1014 case 2: newitemid = 32689; break;
1015 case 3: newitemid = 32690; break;
1016 case 4: newitemid = 32691; break;
1017 case 5: newitemid = 32692; break;
1018 case 6: newitemid = 32693; break;
1019 case 7: newitemid = 32700; break;
1020 case 8: newitemid = 32701; break;
1021 case 9: newitemid = 32702; break;
1022 case 10: newitemid = 32703; break;
1023 case 11: newitemid = 32704; break;
1024 case 12: newitemid = 32705; break;
1025 case 13: newitemid = 32706; break;
1026 case 14: newitemid = 32707; break;
1027 case 15: newitemid = 32708; break;
1028 case 16: newitemid = 32709; break;
1029 case 17: newitemid = 32710; break;
1030 case 18: newitemid = 32711; break;
1031 case 19: newitemid = 32712; break;
1032 case 20: newitemid = 32713; break;
1033 default:
1034 return;
1037 DoCreateItem(i,newitemid);
1038 return;
1040 // Demon Broiled Surprise
1041 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1042 case 43723:
1044 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1045 return;
1047 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1048 return;
1051 case 44875: // Complete Raptor Capture
1053 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1054 return;
1056 Creature* creatureTarget = (Creature*)unitTarget;
1058 creatureTarget->setDeathState(JUST_DIED);
1059 creatureTarget->RemoveCorpse();
1060 creatureTarget->SetHealth(0); // just for nice GM-mode view
1062 //cast spell Raptor Capture Credit
1063 m_caster->CastSpell(m_caster,42337,true,NULL);
1064 return;
1066 case 37573: //Temporal Phase Modulator
1068 if(!unitTarget)
1069 return;
1071 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1072 if(!tempSummon)
1073 return;
1075 uint32 health = tempSummon->GetHealth();
1076 const uint32 entry_list[6] = {21821, 21820, 21817};
1078 float x = tempSummon->GetPositionX();
1079 float y = tempSummon->GetPositionY();
1080 float z = tempSummon->GetPositionZ();
1081 float o = tempSummon->GetOrientation();
1083 tempSummon->UnSummon();
1085 Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1086 if (!pCreature)
1087 return;
1089 pCreature->SetHealth(health);
1091 if(pCreature->AI())
1092 pCreature->AI()->AttackStart(m_caster);
1094 return;
1096 case 34665: //Administer Antidote
1098 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1099 return;
1101 if(!unitTarget)
1102 return;
1104 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1105 if(!tempSummon)
1106 return;
1108 uint32 health = tempSummon->GetHealth();
1110 float x = tempSummon->GetPositionX();
1111 float y = tempSummon->GetPositionY();
1112 float z = tempSummon->GetPositionZ();
1113 float o = tempSummon->GetOrientation();
1114 tempSummon->UnSummon();
1116 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1117 if (!pCreature)
1118 return;
1120 pCreature->SetHealth(health);
1121 ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
1123 if (pCreature->AI())
1124 pCreature->AI()->AttackStart(m_caster);
1126 return;
1128 case 44997: // Converting Sentry
1130 //Converted Sentry Credit
1131 m_caster->CastSpell(m_caster, 45009, true);
1132 return;
1134 case 45030: // Impale Emissary
1136 // Emissary of Hate Credit
1137 m_caster->CastSpell(m_caster, 45088, true);
1138 return;
1140 case 50243: // Teach Language
1142 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1143 return;
1145 // spell has a 1/3 chance to trigger one of the below
1146 if(roll_chance_i(66))
1147 return;
1148 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1150 // 1000001 - gnomish binary
1151 m_caster->CastSpell(m_caster, 50242, true);
1153 else
1155 // 01001000 - goblin binary
1156 m_caster->CastSpell(m_caster, 50246, true);
1159 return;
1161 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1163 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1164 return;
1166 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1167 bg->EventPlayerDroppedFlag((Player*)m_caster);
1169 m_caster->CastSpell(m_caster, 30452, true, NULL);
1170 return;
1172 case 53341:
1173 case 53343:
1175 m_caster->CastSpell(m_caster,54586,true);
1176 return;
1180 //All IconID Check in there
1181 switch(m_spellInfo->SpellIconID)
1183 // Berserking (troll racial traits)
1184 case 1661:
1186 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1187 int32 melee_mod = 10;
1188 if (healthPerc <= 40)
1189 melee_mod = 30;
1190 if (healthPerc < 100 && healthPerc > 40)
1191 melee_mod = 10+(100-healthPerc)/3;
1193 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1194 int32 hasteModBasePoints1 = (5-melee_mod);
1195 int32 hasteModBasePoints2 = 5;
1197 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1198 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1199 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1200 return;
1203 break;
1205 case SPELLFAMILY_MAGE:
1206 switch(m_spellInfo->Id )
1208 case 11958: // Cold Snap
1210 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1211 return;
1213 // immediately finishes the cooldown on Frost spells
1214 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1215 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1217 if (itr->second->state == PLAYERSPELL_REMOVED)
1218 continue;
1220 uint32 classspell = itr->first;
1221 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1223 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1224 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1225 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1227 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1229 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1230 data << uint32(classspell);
1231 data << uint64(m_caster->GetGUID());
1232 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1235 return;
1237 case 32826:
1239 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1241 //Polymorph Cast Visual Rank 1
1242 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1243 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1245 return;
1248 break;
1249 case SPELLFAMILY_WARRIOR:
1250 // Charge
1251 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1253 int32 chargeBasePoints0 = damage;
1254 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1255 return;
1257 // Execute
1258 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1260 if(!unitTarget)
1261 return;
1263 uint32 rage = m_caster->GetPower(POWER_RAGE);
1264 // Glyph of Execution bonus
1265 if (Aura *aura = m_caster->GetDummyAura(58367))
1266 rage+=aura->GetModifier()->m_amount;
1268 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1269 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1270 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1271 m_caster->SetPower(POWER_RAGE,0);
1272 return;
1274 switch(m_spellInfo->Id)
1276 // Warrior's Wrath
1277 case 21977:
1279 if(!unitTarget)
1280 return;
1281 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1282 return;
1284 // Last Stand
1285 case 12975:
1287 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1288 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1289 return;
1291 // Bloodthirst
1292 case 23881:
1294 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1295 return;
1298 break;
1299 case SPELLFAMILY_WARLOCK:
1300 // Life Tap
1301 if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL)
1303 // In 303 exist spirit depend
1304 uint32 spirit = m_caster->GetStat(STAT_SPIRIT);
1305 switch (m_spellInfo->Id)
1307 case 1454: damage+=spirit; break;
1308 case 1455: damage+=spirit*15/10; break;
1309 case 1456: damage+=spirit*2; break;
1310 case 11687: damage+=spirit*25/10; break;
1311 case 11688:
1312 case 11689:
1313 case 27222:
1314 case 57946: damage+=spirit*3; break;
1315 default:
1316 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1317 return;
1319 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1320 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1321 if(int32(unitTarget->GetHealth()) > damage)
1323 // Shouldn't Appear in Combat Log
1324 unitTarget->ModifyHealth(-damage);
1326 int32 mana = damage;
1327 // Improved Life Tap mod
1328 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1329 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1331 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1332 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1334 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1336 // Mana Feed
1337 int32 manaFeedVal = 0;
1338 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1339 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1341 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1342 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1344 if(manaFeedVal > 0)
1346 manaFeedVal = manaFeedVal * mana / 100;
1347 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1350 else
1351 SendCastResult(SPELL_FAILED_FIZZLE);
1352 return;
1354 break;
1355 case SPELLFAMILY_PRIEST:
1356 // Penance
1357 if (m_spellInfo->SpellFamilyFlags & 0x0080000000000000LL)
1359 if (!unitTarget)
1360 return;
1362 int hurt = 0;
1363 int heal = 0;
1364 switch(m_spellInfo->Id)
1366 case 47540: hurt = 47758; heal = 47757; break;
1367 case 53005: hurt = 53001; heal = 52986; break;
1368 case 53006: hurt = 53002; heal = 52987; break;
1369 case 53007: hurt = 53003; heal = 52988; break;
1370 default:
1371 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1372 return;
1374 if (m_caster->IsFriendlyTo(unitTarget))
1375 m_caster->CastSpell(unitTarget, heal, true, 0);
1376 else
1377 m_caster->CastSpell(unitTarget, hurt, true, 0);
1378 return;
1380 switch(m_spellInfo->Id )
1382 case 28598: // Touch of Weakness triggered spell
1384 if(!unitTarget || !m_triggeredByAuraSpell)
1385 return;
1387 uint32 spellid = 0;
1388 switch(m_triggeredByAuraSpell->Id)
1390 case 2652: spellid = 2943; break; // Rank 1
1391 case 19261: spellid = 19249; break; // Rank 2
1392 case 19262: spellid = 19251; break; // Rank 3
1393 case 19264: spellid = 19252; break; // Rank 4
1394 case 19265: spellid = 19253; break; // Rank 5
1395 case 19266: spellid = 19254; break; // Rank 6
1396 case 25461: spellid = 25460; break; // Rank 7
1397 default:
1398 sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id);
1399 return;
1401 m_caster->CastSpell(unitTarget, spellid, true, NULL);
1402 return;
1405 break;
1406 case SPELLFAMILY_DRUID:
1407 break;
1408 case SPELLFAMILY_ROGUE:
1409 switch(m_spellInfo->Id )
1411 case 5938: // Shiv
1413 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1414 return;
1416 Player *pCaster = ((Player*)m_caster);
1418 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1419 if(!item)
1420 return;
1422 // all poison enchantments is temporary
1423 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1424 if(!enchant_id)
1425 return;
1427 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1428 if(!pEnchant)
1429 return;
1431 for (int s=0;s<3;s++)
1433 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1434 continue;
1436 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1437 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1438 continue;
1440 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1443 m_caster->CastSpell(unitTarget, 5940, true);
1444 return;
1446 case 14185: // Preparation Rogue
1448 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1449 return;
1451 //immediately finishes the cooldown on certain Rogue abilities
1452 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1453 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1455 uint32 classspell = itr->first;
1456 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1458 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL))
1460 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1462 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1463 data << uint32(classspell);
1464 data << uint64(m_caster->GetGUID());
1465 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1468 return;
1470 case 31231: // Cheat Death
1472 m_caster->CastSpell(m_caster,45182,true);
1473 return;
1476 break;
1477 case SPELLFAMILY_HUNTER:
1478 // Steady Shot
1479 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1481 if( !unitTarget || !unitTarget->isAlive())
1482 return;
1484 bool found = false;
1486 // check dazed affect
1487 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1488 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1490 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1492 found = true;
1493 break;
1497 if(found)
1498 m_damage+= damage;
1499 return;
1502 switch(m_spellInfo->Id)
1504 case 23989: //Readiness talent
1506 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1507 return;
1509 //immediately finishes the cooldown for hunter abilities
1510 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1511 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1513 uint32 classspell = itr->first;
1514 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1516 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1518 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1520 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1521 data << uint32(classspell);
1522 data << uint64(m_caster->GetGUID());
1523 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1526 return;
1528 case 37506: // Scatter Shot
1530 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1531 return;
1533 // break Auto Shot and autohit
1534 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1535 m_caster->AttackStop();
1536 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1537 return;
1540 break;
1541 case SPELLFAMILY_PALADIN:
1542 switch(m_spellInfo->SpellIconID)
1544 case 156: // Holy Shock
1546 if(!unitTarget)
1547 return;
1549 int hurt = 0;
1550 int heal = 0;
1552 switch(m_spellInfo->Id)
1554 case 20473: hurt = 25912; heal = 25914; break;
1555 case 20929: hurt = 25911; heal = 25913; break;
1556 case 20930: hurt = 25902; heal = 25903; break;
1557 case 27174: hurt = 27176; heal = 27175; break;
1558 case 33072: hurt = 33073; heal = 33074; break;
1559 case 48824: hurt = 48822; heal = 48820; break;
1560 case 48825: hurt = 48823; heal = 48821; break;
1561 default:
1562 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1563 return;
1566 if(m_caster->IsFriendlyTo(unitTarget))
1567 m_caster->CastSpell(unitTarget, heal, true, 0);
1568 else
1569 m_caster->CastSpell(unitTarget, hurt, true, 0);
1571 return;
1573 case 561: // Judgement of command
1575 if(!unitTarget)
1576 return;
1578 uint32 spell_id = m_currentBasePoints[i]+1;
1579 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1580 if(!spell_proto)
1581 return;
1583 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1585 // decreased damage (/2) for non-stunned target.
1586 SpellModifier *mod = new SpellModifier;
1587 mod->op = SPELLMOD_DAMAGE;
1588 mod->value = -50;
1589 mod->type = SPELLMOD_PCT;
1590 mod->spellId = m_spellInfo->Id;
1591 mod->mask = 0x0000020000000000LL;
1592 mod->mask2= 0LL;
1594 ((Player*)m_caster)->AddSpellMod(mod, true);
1595 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1596 // mod deleted
1597 ((Player*)m_caster)->AddSpellMod(mod, false);
1599 else
1600 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1602 return;
1606 switch(m_spellInfo->Id)
1608 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1609 case 20187:
1611 if (!unitTarget)
1612 return;
1613 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1614 return;
1616 case 31789: // Righteous Defense (step 1)
1618 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1620 // non-standard cast requirement check
1621 if (!unitTarget || unitTarget->getAttackers().empty())
1623 // clear cooldown at fail
1624 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1626 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1628 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1629 data << uint32(m_spellInfo->Id);
1630 data << uint64(m_caster->GetGUID());
1631 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1634 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1635 return;
1638 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1639 // Clear targets for eff 1
1640 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1641 ihit->effectMask &= ~(1<<1);
1643 // not empty (checked)
1644 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1646 // chance to be selected from list
1647 float chance = 100.0f/attackers.size();
1648 uint32 count=0;
1649 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1651 if(!roll_chance_f(chance))
1652 continue;
1653 ++count;
1654 AddUnitTarget((*aItr), 1);
1657 // now let next effect cast spell at each target.
1658 return;
1660 case 37877: // Blessing of Faith
1662 if(!unitTarget)
1663 return;
1665 uint32 spell_id = 0;
1666 switch(unitTarget->getClass())
1668 case CLASS_DRUID: spell_id = 37878; break;
1669 case CLASS_PALADIN: spell_id = 37879; break;
1670 case CLASS_PRIEST: spell_id = 37880; break;
1671 case CLASS_SHAMAN: spell_id = 37881; break;
1672 default: return; // ignore for not healing classes
1675 m_caster->CastSpell(m_caster,spell_id,true);
1676 return;
1679 break;
1680 case SPELLFAMILY_SHAMAN:
1681 //Shaman Rockbiter Weapon
1682 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1684 // TODO: use expect spell for enchant (if exist talent)
1685 // In 3.0.3 no mods present for rockbiter
1686 uint32 spell_id = 0;
1687 switch(m_spellInfo->Id)
1689 case 8017: spell_id = 36494; break; // Rank 1
1690 case 8018: spell_id = 36750; break; // Rank 2
1691 case 8019: spell_id = 36755; break; // Rank 3
1692 case 10399: spell_id = 36759; break; // Rank 4
1693 default:
1694 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1695 return;
1698 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1700 if(!spellInfo)
1702 sLog.outError("WORLD: unknown spell id %i\n", spell_id);
1703 return;
1706 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1707 return;
1709 for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1711 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1713 if(item->IsFitToSpellRequirements(m_spellInfo))
1715 Spell *spell = new Spell(m_caster, spellInfo, true);
1717 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1718 // at calculation applied affect from Elemental Weapons talent
1719 // real enchantment damage-1
1720 spell->m_currentBasePoints[1] = damage-1;
1722 SpellCastTargets targets;
1723 targets.setItemTarget( item );
1724 spell->prepare(&targets);
1728 return;
1731 if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect
1733 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1734 return;
1736 // Regenerate 6% of Total Mana Every 3 secs
1737 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1738 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1739 return;
1741 // Lava Lash
1742 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1744 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1745 return;
1746 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1747 if (item)
1749 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1750 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1751 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1753 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1754 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000200000LL &&
1755 (*itr)->GetCastItemGUID() == item->GetGUID())
1757 m_damage += m_damage * damage / 100;
1758 return;
1762 return;
1764 break;
1767 // pet auras
1768 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1770 m_caster->AddPetAura(petSpell);
1771 return;
1775 void Spell::EffectTriggerSpellWithValue(uint32 i)
1777 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1779 // normal case
1780 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1782 if(!spellInfo)
1784 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id);
1785 return;
1788 int32 bp = damage;
1789 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1792 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1794 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1795 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1797 if(!spellInfo)
1799 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1800 return;
1803 finish();
1804 Spell *spell = new Spell(m_caster, spellInfo, true);
1806 SpellCastTargets targets;
1807 targets.setUnitTarget( unitTarget);
1808 spell->prepare(&targets);
1810 m_caster->SetCurrentCastedSpell(spell);
1811 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1815 void Spell::EffectForceCast(uint32 i)
1817 if( !unitTarget )
1818 return;
1820 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1822 // normal case
1823 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1825 if(!spellInfo)
1827 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1828 return;
1831 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1834 void Spell::EffectTriggerSpell(uint32 i)
1836 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1838 // special cases
1839 switch(triggered_spell_id)
1841 // Vanish
1842 case 18461:
1844 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1845 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1846 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1848 // if this spell is given to NPC it must handle rest by it's own AI
1849 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1850 return;
1852 // get highest rank of the Stealth spell
1853 uint32 spellId = 0;
1854 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1855 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1857 // only highest rank is shown in spell book, so simply check if shown in spell book
1858 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1859 continue;
1861 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1862 if (!spellInfo)
1863 continue;
1865 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1867 spellId = spellInfo->Id;
1868 break;
1872 // no Stealth spell found
1873 if (!spellId)
1874 return;
1876 // reset cooldown on it if needed
1877 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1878 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1880 m_caster->CastSpell(m_caster, spellId, true);
1881 return;
1883 // just skip
1884 case 23770: // Sayge's Dark Fortune of *
1885 // not exist, common cooldown can be implemented in scripts if need.
1886 return;
1887 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1888 case 29284:
1890 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1891 if (!spell)
1892 return;
1894 for (int i=0; i < spell->StackAmount; ++i)
1895 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1896 return;
1898 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1899 case 29286:
1901 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1902 if (!spell)
1903 return;
1905 for (int i=0; i < spell->StackAmount; ++i)
1906 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1907 return;
1909 // Righteous Defense
1910 case 31980:
1912 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1913 return;
1915 // Cloak of Shadows
1916 case 35729 :
1918 Unit::AuraMap& Auras = m_caster->GetAuras();
1919 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1921 // remove all harmful spells on you...
1922 if( // ignore positive and passive auras
1923 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1924 // ignore physical auras
1925 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
1927 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1928 iter = Auras.begin();
1931 return;
1933 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1934 case 41967:
1936 if (Unit *pet = m_caster->GetPet())
1937 pet->CastSpell(pet, 28305, true);
1938 return;
1942 // normal case
1943 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1945 if(!spellInfo)
1947 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1948 return;
1951 // some triggered spells require specific equipment
1952 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1954 // main hand weapon required
1955 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1957 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1959 // skip spell if no weapon in slot or broken
1960 if(!item || item->IsBroken() )
1961 return;
1963 // skip spell if weapon not fit to triggered spell
1964 if(!item->IsFitToSpellRequirements(spellInfo))
1965 return;
1968 // offhand hand weapon required
1969 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1971 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1973 // skip spell if no weapon in slot or broken
1974 if(!item || item->IsBroken() )
1975 return;
1977 // skip spell if weapon not fit to triggered spell
1978 if(!item->IsFitToSpellRequirements(spellInfo))
1979 return;
1983 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1984 bool instant = false;
1985 for(uint32 j = i+1; j < 3; ++j)
1987 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
1989 instant = true;
1990 break;
1994 if(instant)
1996 if (unitTarget)
1997 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
1999 else
2000 m_TriggerSpells.push_back(spellInfo);
2003 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2005 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2007 // normal case
2008 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2010 if(!spellInfo)
2012 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2013 m_spellInfo->Id,effect_idx,triggered_spell_id);
2014 return;
2017 if (m_CastItem)
2018 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2020 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2023 void Spell::EffectTeleportUnits(uint32 i)
2025 if(!unitTarget || unitTarget->isInFlight())
2026 return;
2028 switch (m_spellInfo->EffectImplicitTargetB[i])
2030 case TARGET_INNKEEPER_COORDINATES:
2032 // Only players can teleport to innkeeper
2033 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2034 return;
2036 ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0);
2037 return;
2039 case TARGET_TABLE_X_Y_Z_COORDINATES:
2041 // TODO: Only players can teleport?
2042 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2043 return;
2044 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2045 if(!st)
2047 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id );
2048 return;
2050 ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0);
2051 break;
2053 case TARGET_BEHIND_VICTIM:
2055 // Get selected target for player (or victim for units)
2056 Unit *pTarget = NULL;
2057 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2058 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2059 else
2060 pTarget = m_caster->getVictim();
2061 // No target present - return
2062 if (!pTarget)
2063 return;
2064 // Init dest coordinates
2065 uint32 mapid = m_caster->GetMapId();
2066 float x = m_targets.m_destX;
2067 float y = m_targets.m_destY;
2068 float z = m_targets.m_destZ;
2069 float orientation = pTarget->GetOrientation();
2070 // Teleport
2071 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2072 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2073 else
2075 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2076 WorldPacket data;
2077 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2078 unitTarget->SendMessageToSet(&data, false);
2080 return;
2082 default:
2084 // If not exist data for dest location - return
2085 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2087 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2088 return;
2090 // Init dest coordinates
2091 uint32 mapid = m_caster->GetMapId();
2092 float x = m_targets.m_destX;
2093 float y = m_targets.m_destY;
2094 float z = m_targets.m_destZ;
2095 float orientation = unitTarget->GetOrientation();
2096 // Teleport
2097 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2098 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2099 else
2101 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2102 WorldPacket data;
2103 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2104 unitTarget->SendMessageToSet(&data, false);
2106 return;
2110 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2111 switch ( m_spellInfo->Id )
2113 // Dimensional Ripper - Everlook
2114 case 23442:
2116 int32 r = irand(0, 119);
2117 if ( r >= 70 ) // 7/12 success
2119 if ( r < 100 ) // 4/12 evil twin
2120 m_caster->CastSpell(m_caster,23445,true);
2121 else // 1/12 fire
2122 m_caster->CastSpell(m_caster,23449,true);
2124 return;
2126 // Ultrasafe Transporter: Toshley's Station
2127 case 36941:
2129 if ( roll_chance_i(50) ) // 50% success
2131 int32 rand_eff = urand(1,7);
2132 switch ( rand_eff )
2134 case 1:
2135 // soul split - evil
2136 m_caster->CastSpell(m_caster,36900,true);
2137 break;
2138 case 2:
2139 // soul split - good
2140 m_caster->CastSpell(m_caster,36901,true);
2141 break;
2142 case 3:
2143 // Increase the size
2144 m_caster->CastSpell(m_caster,36895,true);
2145 break;
2146 case 4:
2147 // Decrease the size
2148 m_caster->CastSpell(m_caster,36893,true);
2149 break;
2150 case 5:
2151 // Transform
2153 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2154 m_caster->CastSpell(m_caster,36897,true);
2155 else
2156 m_caster->CastSpell(m_caster,36899,true);
2157 break;
2159 case 6:
2160 // chicken
2161 m_caster->CastSpell(m_caster,36940,true);
2162 break;
2163 case 7:
2164 // evil twin
2165 m_caster->CastSpell(m_caster,23445,true);
2166 break;
2169 return;
2171 // Dimensional Ripper - Area 52
2172 case 36890:
2174 if ( roll_chance_i(50) ) // 50% success
2176 int32 rand_eff = urand(1,4);
2177 switch ( rand_eff )
2179 case 1:
2180 // soul split - evil
2181 m_caster->CastSpell(m_caster,36900,true);
2182 break;
2183 case 2:
2184 // soul split - good
2185 m_caster->CastSpell(m_caster,36901,true);
2186 break;
2187 case 3:
2188 // Increase the size
2189 m_caster->CastSpell(m_caster,36895,true);
2190 break;
2191 case 4:
2192 // Transform
2194 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2195 m_caster->CastSpell(m_caster,36897,true);
2196 else
2197 m_caster->CastSpell(m_caster,36899,true);
2198 break;
2202 return;
2207 void Spell::EffectApplyAura(uint32 i)
2209 if(!unitTarget)
2210 return;
2212 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2213 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2214 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2215 return;
2217 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2218 if(!caster)
2219 return;
2221 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2223 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2225 // Now Reduce spell duration using data received at spell hit
2226 int32 duration = Aur->GetAuraMaxDuration();
2227 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2228 Aur->setDiminishGroup(m_diminishGroup);
2230 // if Aura removed and deleted, do not continue.
2231 if(duration== 0 && !(Aur->IsPermanent()))
2233 delete Aur;
2234 return;
2237 if(duration != Aur->GetAuraMaxDuration())
2239 Aur->SetAuraMaxDuration(duration);
2240 Aur->SetAuraDuration(duration);
2243 bool added = unitTarget->AddAura(Aur);
2245 // Aura not added and deleted in AddAura call;
2246 if (!added)
2247 return;
2249 // found crash at character loading, broken pointer to Aur...
2250 // Aur was deleted in AddAura()...
2251 if(!Aur)
2252 return;
2254 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2255 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2256 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2259 void Spell::EffectUnlearnSpecialization( uint32 i )
2261 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2262 return;
2264 Player *_player = (Player*)unitTarget;
2265 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2267 _player->removeSpell(spellToUnlearn);
2269 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2272 void Spell::EffectPowerDrain(uint32 i)
2274 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2275 return;
2277 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2279 if(!unitTarget)
2280 return;
2281 if(!unitTarget->isAlive())
2282 return;
2283 if(unitTarget->getPowerType() != drain_power)
2284 return;
2285 if(damage < 0)
2286 return;
2288 uint32 curPower = unitTarget->GetPower(drain_power);
2290 //add spell damage bonus
2291 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2293 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2294 uint32 power = damage;
2295 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2296 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2298 int32 new_damage;
2299 if(curPower < power)
2300 new_damage = curPower;
2301 else
2302 new_damage = power;
2304 unitTarget->ModifyPower(drain_power,-new_damage);
2306 // Don`t restore from self drain
2307 if(drain_power == POWER_MANA && m_caster != unitTarget)
2309 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2310 if(manaMultiplier==0)
2311 manaMultiplier = 1;
2313 if(Player *modOwner = m_caster->GetSpellModOwner())
2314 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2316 int32 gain = int32(new_damage*manaMultiplier);
2318 m_caster->ModifyPower(POWER_MANA,gain);
2319 //send log
2320 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2324 void Spell::EffectSendEvent(uint32 EffectIndex)
2326 if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround())
2328 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
2329 if(bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2331 switch(m_spellInfo->Id)
2333 case 23333: // Pickup Horde Flag
2334 /*do not uncomment .
2335 if(bg->GetTypeID()==BATTLEGROUND_WS)
2336 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2337 sLog.outDebug("Send Event Horde Flag Picked Up");
2338 break;
2339 /* not used :
2340 case 23334: // Drop Horde Flag
2341 if(bg->GetTypeID()==BATTLEGROUND_WS)
2342 bg->EventPlayerDroppedFlag((Player*)m_caster);
2343 sLog.outDebug("Drop Horde Flag");
2344 break;
2346 case 23335: // Pickup Alliance Flag
2347 /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2348 if(bg->GetTypeID()==BATTLEGROUND_WS)
2349 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2350 sLog.outDebug("Send Event Alliance Flag Picked Up");
2351 break;
2352 /* not used :
2353 case 23336: // Drop Alliance Flag
2354 if(bg->GetTypeID()==BATTLEGROUND_WS)
2355 bg->EventPlayerDroppedFlag((Player*)m_caster);
2356 sLog.outDebug("Drop Alliance Flag");
2357 break;
2358 case 23385: // Alliance Flag Returns
2359 if(bg->GetTypeID()==BATTLEGROUND_WS)
2360 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2361 sLog.outDebug("Alliance Flag Returned");
2362 break;
2363 case 23386: // Horde Flag Returns
2364 if(bg->GetTypeID()==BATTLEGROUND_WS)
2365 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2366 sLog.outDebug("Horde Flag Returned");
2367 break;*/
2368 case 34976:
2370 if(bg->GetTypeID()==BATTLEGROUND_EY)
2371 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2373 break;
2374 default:
2375 sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2376 break;
2380 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2381 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2384 void Spell::EffectPowerBurn(uint32 i)
2386 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2387 return;
2389 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2391 if(!unitTarget)
2392 return;
2393 if(!unitTarget->isAlive())
2394 return;
2395 if(unitTarget->getPowerType()!=powertype)
2396 return;
2397 if(damage < 0)
2398 return;
2400 int32 curPower = int32(unitTarget->GetPower(powertype));
2402 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2403 uint32 power = damage;
2404 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2405 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2407 int32 new_damage = (curPower < power) ? curPower : power;
2409 unitTarget->ModifyPower(powertype,-new_damage);
2410 float multiplier = m_spellInfo->EffectMultipleValue[i];
2412 if(Player *modOwner = m_caster->GetSpellModOwner())
2413 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2415 new_damage = int32(new_damage*multiplier);
2416 m_damage+=new_damage;
2419 void Spell::EffectHeal( uint32 /*i*/ )
2421 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2423 // Try to get original caster
2424 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2426 // Skip if m_originalCaster not available
2427 if (!caster)
2428 return;
2430 int32 addhealth = damage;
2432 // Vessel of the Naaru (Vial of the Sunwell trinket)
2433 if (m_spellInfo->Id == 45064)
2435 // Amount of heal - depends from stacked Holy Energy
2436 int damageAmount = 0;
2437 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2438 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2439 if((*i)->GetId() == 45062)
2440 damageAmount+=(*i)->GetModifier()->m_amount;
2441 if (damageAmount)
2442 m_caster->RemoveAurasDueToSpell(45062);
2444 addhealth += damageAmount;
2446 // Swiftmend - consumes Regrowth or Rejuvenation
2447 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2449 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2450 // find most short by duration
2451 Aura *targetAura = NULL;
2452 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2454 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2455 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2457 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2458 targetAura = *i;
2462 if(!targetAura)
2464 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2465 return;
2467 int idx = 0;
2468 while(idx < 3)
2470 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2471 break;
2472 idx++;
2475 int32 tickheal = caster->SpellHealingBonus(targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT, unitTarget);
2476 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2477 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2479 addhealth += tickheal * tickcount;
2481 else
2482 addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
2484 m_healing+=addhealth;
2488 void Spell::EffectHealPct( uint32 /*i*/ )
2490 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2492 // Try to get original caster
2493 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2495 // Skip if m_originalCaster not available
2496 if (!caster)
2497 return;
2499 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2500 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2502 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2503 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2505 if(caster->GetTypeId()==TYPEID_PLAYER)
2506 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2507 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2511 void Spell::EffectHealMechanical( uint32 /*i*/ )
2513 // Mechanic creature type should be correctly checked by targetCreatureType field
2514 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2516 // Try to get original caster
2517 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2519 // Skip if m_originalCaster not available
2520 if (!caster)
2521 return;
2523 uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget);
2524 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2525 unitTarget->ModifyHealth( int32(damage) );
2529 void Spell::EffectHealthLeech(uint32 i)
2531 if(!unitTarget)
2532 return;
2533 if(!unitTarget->isAlive())
2534 return;
2536 if(damage < 0)
2537 return;
2539 sLog.outDebug("HealthLeech :%i", damage);
2541 float multiplier = m_spellInfo->EffectMultipleValue[i];
2543 if(Player *modOwner = m_caster->GetSpellModOwner())
2544 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2546 int32 new_damage = int32(damage*multiplier);
2547 uint32 curHealth = unitTarget->GetHealth();
2548 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2549 if(curHealth < new_damage)
2550 new_damage = curHealth;
2552 if(m_caster->isAlive())
2554 new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster);
2556 m_caster->ModifyHealth(new_damage);
2558 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2559 m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2561 // m_healthLeech+=tmpvalue;
2562 // m_damage+=new_damage;
2565 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2567 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2568 return;
2570 Player* player = (Player*)unitTarget;
2572 uint32 newitemid = itemtype;
2573 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2574 if(!pProto)
2576 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2577 return;
2580 uint32 num_to_add;
2582 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2583 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2585 int32 basePoints = m_currentBasePoints[i];
2586 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2587 if (randomPoints)
2588 num_to_add = basePoints + irand(1, randomPoints);
2589 else
2590 num_to_add = basePoints + 1;
2592 else if (pProto->MaxCount == 1)
2593 num_to_add = 1;
2594 else if(player->getLevel() >= m_spellInfo->spellLevel)
2596 int32 basePoints = m_currentBasePoints[i];
2597 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2598 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2600 else
2601 num_to_add = 2;
2603 if (num_to_add < 1)
2604 num_to_add = 1;
2605 if (num_to_add > pProto->GetMaxStackSize())
2606 num_to_add = pProto->GetMaxStackSize();
2608 // init items_count to 1, since 1 item will be created regardless of specialization
2609 int items_count=1;
2610 // the chance to create additional items
2611 float additionalCreateChance=0.0f;
2612 // the maximum number of created additional items
2613 uint8 additionalMaxNum=0;
2614 // get the chance and maximum number for creating extra items
2615 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2617 // roll with this chance till we roll not to create or we create the max num
2618 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2619 ++items_count;
2622 // really will be created more items
2623 num_to_add *= items_count;
2625 // can the player store the new item?
2626 ItemPosCountVec dest;
2627 uint32 no_space = 0;
2628 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2629 if( msg != EQUIP_ERR_OK )
2631 // convert to possible store amount
2632 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2633 num_to_add -= no_space;
2634 else
2636 // if not created by another reason from full inventory or unique items amount limitation
2637 player->SendEquipError( msg, NULL, NULL );
2638 return;
2642 if(num_to_add)
2644 // create the new item and store it
2645 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2647 // was it successful? return error if not
2648 if(!pItem)
2650 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2651 return;
2654 // set the "Crafted by ..." property of the item
2655 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2656 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2658 // send info to the client
2659 if(pItem)
2660 player->SendNewItem(pItem, num_to_add, true, true);
2662 // we succeeded in creating at least one item, so a levelup is possible
2663 player->UpdateCraftSkill(m_spellInfo->Id);
2666 // for battleground marks send by mail if not add all expected
2667 if(no_space > 0 )
2669 BattleGroundTypeId bgType;
2670 switch(m_spellInfo->Id)
2672 case SPELL_AV_MARK_WINNER:
2673 case SPELL_AV_MARK_LOSER:
2674 bgType = BATTLEGROUND_AV;
2675 break;
2676 case SPELL_WS_MARK_WINNER:
2677 case SPELL_WS_MARK_LOSER:
2678 bgType = BATTLEGROUND_WS;
2679 break;
2680 case SPELL_AB_MARK_WINNER:
2681 case SPELL_AB_MARK_LOSER:
2682 bgType = BATTLEGROUND_AB;
2683 break;
2684 default:
2685 return;
2688 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2689 bg->SendRewardMarkByMail(player,newitemid,no_space);
2693 void Spell::EffectCreateItem(uint32 i)
2695 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2698 void Spell::EffectPersistentAA(uint32 i)
2700 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2702 if(Player* modOwner = m_caster->GetSpellModOwner())
2703 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2705 int32 duration = GetSpellDuration(m_spellInfo);
2706 DynamicObject* dynObj = new DynamicObject;
2707 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))
2709 delete dynObj;
2710 return;
2712 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2713 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2714 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2715 m_caster->AddDynObject(dynObj);
2716 dynObj->GetMap()->Add(dynObj);
2719 void Spell::EffectEnergize(uint32 i)
2721 if(!unitTarget)
2722 return;
2723 if(!unitTarget->isAlive())
2724 return;
2726 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2727 return;
2729 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2731 // Some level depends spells
2732 int multiplier = 0;
2733 int level_diff = 0;
2734 switch (m_spellInfo->Id)
2736 // Restore Energy
2737 case 9512:
2738 level_diff = m_caster->getLevel() - 40;
2739 multiplier = 2;
2740 break;
2741 // Blood Fury
2742 case 24571:
2743 level_diff = m_caster->getLevel() - 60;
2744 multiplier = 10;
2745 break;
2746 // Burst of Energy
2747 case 24532:
2748 level_diff = m_caster->getLevel() - 60;
2749 multiplier = 4;
2750 break;
2751 default:
2752 break;
2755 if (level_diff > 0)
2756 damage -= multiplier * level_diff;
2758 if(damage < 0)
2759 return;
2761 if(unitTarget->GetMaxPower(power) == 0)
2762 return;
2764 unitTarget->ModifyPower(power,damage);
2765 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2767 // Mad Alchemist's Potion
2768 if (m_spellInfo->Id == 45051)
2770 // find elixirs on target
2771 uint32 elixir_mask = 0;
2772 Unit::AuraMap& Auras = unitTarget->GetAuras();
2773 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2775 uint32 spell_id = itr->second->GetId();
2776 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2777 elixir_mask |= mask;
2780 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2781 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2783 // get all available elixirs by mask and spell level
2784 std::vector<uint32> elixirs;
2785 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2786 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2788 if (itr->second & elixir_mask)
2790 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2791 continue;
2793 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2794 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2795 continue;
2797 elixirs.push_back(itr->first);
2801 if (!elixirs.empty())
2803 // cast random elixir on target
2804 uint32 rand_spell = urand(0,elixirs.size()-1);
2805 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2810 void Spell::EffectEnergisePct(uint32 i)
2812 if(!unitTarget)
2813 return;
2814 if(!unitTarget->isAlive())
2815 return;
2817 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2818 return;
2820 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2822 uint32 maxPower = unitTarget->GetMaxPower(power);
2823 if(maxPower == 0)
2824 return;
2826 uint32 gain = damage * maxPower / 100;
2827 unitTarget->ModifyPower(power, gain);
2828 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
2831 void Spell::SendLoot(uint64 guid, LootType loottype)
2833 Player* player = (Player*)m_caster;
2834 if (!player)
2835 return;
2837 if (gameObjTarget)
2839 if (Script->GOHello(player, gameObjTarget))
2840 return;
2842 switch (gameObjTarget->GetGoType())
2844 case GAMEOBJECT_TYPE_DOOR:
2845 case GAMEOBJECT_TYPE_BUTTON:
2846 gameObjTarget->UseDoorOrButton();
2847 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2848 return;
2850 case GAMEOBJECT_TYPE_QUESTGIVER:
2851 // start or end quest
2852 player->PrepareQuestMenu(guid);
2853 player->SendPreparedQuest(guid);
2854 return;
2856 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2857 // triggering linked GO
2858 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2859 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2860 return;
2862 case GAMEOBJECT_TYPE_GOOBER:
2863 // goober_scripts can be triggered if the player don't have the quest
2864 if (gameObjTarget->GetGOInfo()->goober.eventId)
2866 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2867 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2870 // cast goober spell
2871 if (gameObjTarget->GetGOInfo()->goober.questId)
2872 ///Quest require to be active for GO using
2873 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2874 return;
2876 gameObjTarget->AddUniqueUse(player);
2877 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2879 //TODO? Objective counting called without spell check but with quest objective check
2880 // if send spell id then this line will duplicate to spell casting call (double counting)
2881 // So we or have this line and not required in quest_template have reqSpellIdN
2882 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2883 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2885 // triggering linked GO
2886 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2887 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2889 return;
2891 case GAMEOBJECT_TYPE_CHEST:
2892 // TODO: possible must be moved to loot release (in different from linked triggering)
2893 if (gameObjTarget->GetGOInfo()->chest.eventId)
2895 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2896 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2899 // triggering linked GO
2900 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2901 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2903 // Don't return, let loots been taken
2907 // Send loot
2908 player->SendLoot(guid, loottype);
2911 void Spell::EffectOpenLock(uint32 /*i*/)
2913 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2915 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2916 return;
2919 Player* player = (Player*)m_caster;
2921 LootType loottype = LOOT_CORPSE;
2922 uint32 lockId = 0;
2923 uint64 guid = 0;
2925 // Get lockId
2926 if(gameObjTarget)
2928 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2929 // Arathi Basin banner opening !
2930 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2931 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2933 //isAllowUseBattleGroundObject() already called in CanCast()
2934 // in battleground check
2935 if(BattleGround *bg = player->GetBattleGround())
2937 // check if it's correct bg
2938 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2939 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2940 return;
2943 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2945 //isAllowUseBattleGroundObject() already called in CanCast()
2946 // in battleground check
2947 if(BattleGround *bg = player->GetBattleGround())
2949 if(bg->GetTypeID() == BATTLEGROUND_EY)
2950 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2951 return;
2954 lockId = gameObjTarget->GetLockId();
2955 guid = gameObjTarget->GetGUID();
2957 else if(itemTarget)
2959 lockId = itemTarget->GetProto()->LockID;
2960 guid = itemTarget->GetGUID();
2962 else
2964 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2965 return;
2968 if(!lockId) // possible case for GO and maybe for items.
2970 SendLoot(guid, loottype);
2971 return;
2974 // Get LockInfo
2975 LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
2977 if (!lockInfo)
2979 sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2980 (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
2981 SendCastResult(SPELL_FAILED_BAD_TARGETS);
2982 return;
2985 // check key
2986 for(int i = 0; i < 8; ++i)
2988 // Type==1 This means lockInfo->Index[i] is an item
2989 if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
2991 SendLoot(guid, loottype);
2992 return;
2996 uint32 SkillId = 0;
2997 // Check and skill-up skill
2998 if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
2999 SkillId = m_spellInfo->EffectMiscValue[1];
3000 // pickpocketing spells
3001 else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
3002 SkillId = SKILL_LOCKPICKING;
3004 // skill bonus provided by casting spell (mostly item spells)
3005 uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
3007 uint32 reqSkillValue = lockInfo->Skill[0];
3009 if(lockInfo->Skill[1]) // required pick lock skill applying
3011 if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
3013 SendCastResult(SPELL_FAILED_FIZZLE);
3014 return;
3017 reqSkillValue = lockInfo->Skill[1];
3019 else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
3021 SendCastResult(SPELL_FAILED_BAD_TARGETS);
3022 return;
3025 if ( SkillId )
3027 loottype = LOOT_SKINNING;
3028 if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
3030 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
3031 return;
3034 // update skill if really known
3035 uint32 SkillValue = player->GetPureSkillValue(SkillId);
3036 if(SkillValue) // non only item base skill
3038 if(gameObjTarget)
3040 // Allow one skill-up until respawned
3041 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3042 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
3043 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3045 else if(itemTarget)
3047 // Do one skill-up
3048 uint32 SkillValue = player->GetPureSkillValue(SkillId);
3049 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
3054 SendLoot(guid, loottype);
3057 void Spell::EffectSummonChangeItem(uint32 i)
3059 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3060 return;
3062 Player *player = (Player*)m_caster;
3064 // applied only to using item
3065 if(!m_CastItem)
3066 return;
3068 // ... only to item in own inventory/bank/equip_slot
3069 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3070 return;
3072 uint32 newitemid = m_spellInfo->EffectItemType[i];
3073 if(!newitemid)
3074 return;
3076 uint16 pos = m_CastItem->GetPos();
3078 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3079 if( !pNewItem )
3080 return;
3082 for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3084 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3085 pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3088 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3090 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3091 player->DurabilityLoss(pNewItem, loosePercent);
3094 if( player->IsInventoryPos( pos ) )
3096 ItemPosCountVec dest;
3097 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3098 if( msg == EQUIP_ERR_OK )
3100 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3102 // prevent crash at access and unexpected charges counting with item update queue corrupt
3103 if(m_CastItem==m_targets.getItemTarget())
3104 m_targets.setItemTarget(NULL);
3106 m_CastItem = NULL;
3108 player->StoreItem( dest, pNewItem, true);
3109 return;
3112 else if( player->IsBankPos ( pos ) )
3114 ItemPosCountVec dest;
3115 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3116 if( msg == EQUIP_ERR_OK )
3118 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3120 // prevent crash at access and unexpected charges counting with item update queue corrupt
3121 if(m_CastItem==m_targets.getItemTarget())
3122 m_targets.setItemTarget(NULL);
3124 m_CastItem = NULL;
3126 player->BankItem( dest, pNewItem, true);
3127 return;
3130 else if( player->IsEquipmentPos ( pos ) )
3132 uint16 dest;
3133 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3134 if( msg == EQUIP_ERR_OK )
3136 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3138 // prevent crash at access and unexpected charges counting with item update queue corrupt
3139 if(m_CastItem==m_targets.getItemTarget())
3140 m_targets.setItemTarget(NULL);
3142 m_CastItem = NULL;
3144 player->EquipItem( dest, pNewItem, true);
3145 player->AutoUnequipOffhandIfNeed();
3146 return;
3150 // fail
3151 delete pNewItem;
3154 void Spell::EffectOpenSecretSafe(uint32 i)
3156 EffectOpenLock(i); //no difference for now
3159 void Spell::EffectProficiency(uint32 /*i*/)
3161 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3162 return;
3163 Player *p_target = (Player*)unitTarget;
3165 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3166 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3168 p_target->AddWeaponProficiency(subClassMask);
3169 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3171 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3173 p_target->AddArmorProficiency(subClassMask);
3174 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3178 void Spell::EffectApplyAreaAura(uint32 i)
3180 if(!unitTarget)
3181 return;
3182 if(!unitTarget->isAlive())
3183 return;
3185 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3186 unitTarget->AddAura(Aur);
3189 void Spell::EffectSummonType(uint32 i)
3191 switch(m_spellInfo->EffectMiscValueB[i])
3193 case SUMMON_TYPE_GUARDIAN:
3194 case SUMMON_TYPE_POSESSED:
3195 case SUMMON_TYPE_POSESSED2:
3196 case SUMMON_TYPE_FORCE_OF_NATURE:
3197 case SUMMON_TYPE_GUARDIAN2:
3198 EffectSummonGuardian(i);
3199 break;
3200 case SUMMON_TYPE_WILD:
3201 EffectSummonWild(i);
3202 break;
3203 case SUMMON_TYPE_DEMON:
3204 EffectSummonDemon(i);
3205 break;
3206 case SUMMON_TYPE_SUMMON:
3207 EffectSummon(i);
3208 break;
3209 case SUMMON_TYPE_CRITTER:
3210 case SUMMON_TYPE_CRITTER2:
3211 case SUMMON_TYPE_CRITTER3:
3212 EffectSummonCritter(i);
3213 break;
3214 case SUMMON_TYPE_TOTEM_SLOT1:
3215 case SUMMON_TYPE_TOTEM_SLOT2:
3216 case SUMMON_TYPE_TOTEM_SLOT3:
3217 case SUMMON_TYPE_TOTEM_SLOT4:
3218 case SUMMON_TYPE_TOTEM:
3219 EffectSummonTotem(i);
3220 break;
3221 case SUMMON_TYPE_UNKNOWN1:
3222 case SUMMON_TYPE_UNKNOWN2:
3223 case SUMMON_TYPE_UNKNOWN3:
3224 case SUMMON_TYPE_UNKNOWN4:
3225 case SUMMON_TYPE_UNKNOWN5:
3226 break;
3227 default:
3228 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3229 break;
3233 void Spell::EffectSummon(uint32 i)
3235 if(m_caster->GetPetGUID())
3236 return;
3238 if(!unitTarget)
3239 return;
3240 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3241 if(!pet_entry)
3242 return;
3243 uint32 level = m_caster->getLevel();
3244 Pet* spawnCreature = new Pet(SUMMON_PET);
3246 if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3248 // set timer for unsummon
3249 int32 duration = GetSpellDuration(m_spellInfo);
3250 if(duration > 0)
3251 spawnCreature->SetDuration(duration);
3253 return;
3256 Map *map = m_caster->GetMap();
3257 uint32 pet_number = objmgr.GeneratePetNumber();
3258 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number))
3260 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3261 delete spawnCreature;
3262 return;
3265 // Summon in dest location
3266 float x,y,z;
3267 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3269 x = m_targets.m_destX;
3270 y = m_targets.m_destY;
3271 z = m_targets.m_destZ;
3273 else
3274 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3276 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3278 if(!spawnCreature->IsPositionValid())
3280 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3281 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3282 delete spawnCreature;
3283 return;
3286 // set timer for unsummon
3287 int32 duration = GetSpellDuration(m_spellInfo);
3288 if(duration > 0)
3289 spawnCreature->SetDuration(duration);
3291 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3292 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3293 spawnCreature->setPowerType(POWER_MANA);
3294 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3295 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3296 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3297 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3298 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3299 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3300 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3301 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3302 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3304 spawnCreature->InitStatsForLevel(level);
3306 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3308 spawnCreature->AIM_Initialize();
3309 spawnCreature->InitPetCreateSpells();
3310 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3311 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3313 std::string name = m_caster->GetName();
3314 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3315 spawnCreature->SetName( name );
3317 map->Add((Creature*)spawnCreature);
3319 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3321 m_caster->SetPet(spawnCreature);
3322 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3323 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3324 ((Player*)m_caster)->PetSpellInitialize();
3328 void Spell::EffectLearnSpell(uint32 i)
3330 if(!unitTarget)
3331 return;
3333 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3335 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3336 EffectLearnPetSpell(i);
3338 return;
3341 Player *player = (Player*)unitTarget;
3343 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3344 player->learnSpell(spellToLearn,false);
3346 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3349 void Spell::EffectDispel(uint32 i)
3351 if(!unitTarget)
3352 return;
3354 // Fill possible dispell list
3355 std::vector <Aura *> dispel_list;
3357 // Create dispel mask by dispel type
3358 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3359 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3360 Unit::AuraMap const& auras = unitTarget->GetAuras();
3361 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3363 Aura *aur = (*itr).second;
3364 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3366 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3368 bool positive = true;
3369 if (!aur->IsPositive())
3370 positive = false;
3371 else
3372 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3374 // do not remove positive auras if friendly target
3375 // negative auras if non-friendly target
3376 if(positive == unitTarget->IsFriendlyTo(m_caster))
3377 continue;
3379 // Add aura to dispel list
3380 dispel_list.push_back(aur);
3383 // Ok if exist some buffs for dispel try dispel it
3384 if (!dispel_list.empty())
3386 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3387 std::list < uint32 > fail_list; // spell_id
3388 int32 list_size = dispel_list.size();
3389 // Dispell N = damage buffs (or while exist buffs for dispel)
3390 for (int32 count=0; count < damage && list_size > 0; ++count)
3392 // Random select buff for dispel
3393 Aura *aur = dispel_list[urand(0, list_size-1)];
3395 SpellEntry const* spellInfo = aur->GetSpellProto();
3396 // Base dispel chance
3397 // TODO: possible chance depend from spell level??
3398 int32 miss_chance = 0;
3399 // Apply dispel mod from aura caster
3400 if (Unit *caster = aur->GetCaster())
3402 if ( Player* modOwner = caster->GetSpellModOwner() )
3403 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3405 // Try dispel
3406 if (roll_chance_i(miss_chance))
3407 fail_list.push_back(aur->GetId());
3408 else
3409 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3410 // Remove buff from list for prevent doubles
3411 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3413 Aura *dispeled = *j;
3414 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3416 j = dispel_list.erase(j);
3417 --list_size;
3419 else
3420 ++j;
3423 // Send success log and really remove auras
3424 if (!success_list.empty())
3426 int32 count = success_list.size();
3427 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3428 data.append(unitTarget->GetPackGUID()); // Victim GUID
3429 data.append(m_caster->GetPackGUID()); // Caster GUID
3430 data << uint32(m_spellInfo->Id); // Dispell spell id
3431 data << uint8(0); // not used
3432 data << uint32(count); // count
3433 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3435 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3436 data << uint32(spellInfo->Id); // Spell Id
3437 data << uint8(0); // 0 - dispeled !=0 cleansed
3438 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3440 m_caster->SendMessageToSet(&data, true);
3442 // On succes dispel
3443 // Devour Magic
3444 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12)
3446 uint32 heal_spell = 0;
3447 switch (m_spellInfo->Id)
3449 case 19505: heal_spell = 19658; break;
3450 case 19731: heal_spell = 19732; break;
3451 case 19734: heal_spell = 19733; break;
3452 case 19736: heal_spell = 19735; break;
3453 case 27276: heal_spell = 27278; break;
3454 case 27277: heal_spell = 27279; break;
3455 default:
3456 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3457 break;
3459 if (heal_spell)
3460 m_caster->CastSpell(m_caster, heal_spell, true);
3463 // Send fail log to client
3464 if (!fail_list.empty())
3466 // Failed to dispell
3467 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3468 data << uint64(m_caster->GetGUID()); // Caster GUID
3469 data << uint64(unitTarget->GetGUID()); // Victim GUID
3470 data << uint32(m_spellInfo->Id); // Dispell spell id
3471 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3472 data << uint32(*j); // Spell Id
3473 m_caster->SendMessageToSet(&data, true);
3478 void Spell::EffectDualWield(uint32 /*i*/)
3480 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3481 ((Player*)unitTarget)->SetCanDualWield(true);
3484 void Spell::EffectPull(uint32 /*i*/)
3486 // TODO: create a proper pull towards distract spell center for distract
3487 sLog.outDebug("WORLD: Spell Effect DUMMY");
3490 void Spell::EffectDistract(uint32 /*i*/)
3492 // Check for possible target
3493 if (!unitTarget || unitTarget->isInCombat())
3494 return;
3496 // target must be OK to do this
3497 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3498 return;
3500 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3502 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3504 // For players just turn them
3505 WorldPacket data;
3506 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3507 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3508 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3510 else
3512 // Set creature Distracted, Stop it, And turn it
3513 unitTarget->SetOrientation(angle);
3514 unitTarget->StopMoving();
3515 unitTarget->GetMotionMaster()->MoveDistract(damage*1000);
3519 void Spell::EffectPickPocket(uint32 /*i*/)
3521 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3522 return;
3524 // victim must be creature and attackable
3525 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3526 return;
3528 // victim have to be alive and humanoid or undead
3529 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3531 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3533 if (chance > irand(0, 19))
3535 // Stealing successful
3536 //sLog.outDebug("Sending loot from pickpocket");
3537 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3539 else
3541 // Reveal action + get attack
3542 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3543 if (((Creature*)unitTarget)->AI())
3544 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3549 void Spell::EffectAddFarsight(uint32 i)
3551 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3552 int32 duration = GetSpellDuration(m_spellInfo);
3553 DynamicObject* dynObj = new DynamicObject;
3554 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))
3556 delete dynObj;
3557 return;
3559 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3560 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3561 m_caster->AddDynObject(dynObj);
3562 dynObj->GetMap()->Add(dynObj);
3563 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3564 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3567 void Spell::EffectSummonWild(uint32 i)
3569 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3570 if(!creature_entry)
3571 return;
3573 uint32 level = m_caster->getLevel();
3575 // level of creature summoned using engineering item based at engineering skill level
3576 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3578 ItemPrototype const *proto = m_CastItem->GetProto();
3579 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3581 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3582 if(skill202)
3584 level = skill202/5;
3589 // select center of summon position
3590 float center_x = m_targets.m_destX;
3591 float center_y = m_targets.m_destY;
3592 float center_z = m_targets.m_destZ;
3594 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3596 int32 amount = damage > 0 ? damage : 1;
3598 for(int32 count = 0; count < amount; ++count)
3600 float px, py, pz;
3601 // If dest location if present
3602 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3604 // Summon 1 unit in dest location
3605 if (count == 0)
3607 px = m_targets.m_destX;
3608 py = m_targets.m_destY;
3609 pz = m_targets.m_destZ;
3611 // Summon in random point all other units if location present
3612 else
3613 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3615 // Summon if dest location not present near caster
3616 else
3617 m_caster->GetClosePoint(px,py,pz,3.0f);
3619 int32 duration = GetSpellDuration(m_spellInfo);
3621 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3623 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3627 void Spell::EffectSummonGuardian(uint32 i)
3629 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3630 if(!pet_entry)
3631 return;
3633 // Jewelery statue case (totem like)
3634 if(m_spellInfo->SpellIconID==2056)
3636 EffectSummonTotem(i);
3637 return;
3640 // set timer for unsummon
3641 int32 duration = GetSpellDuration(m_spellInfo);
3643 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3644 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3645 // so this code hack in fact
3646 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3647 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3648 return; // find old guardian, ignore summon
3650 // in another case summon new
3651 uint32 level = m_caster->getLevel();
3653 // level of pet summoned using engineering item based at engineering skill level
3654 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3656 ItemPrototype const *proto = m_CastItem->GetProto();
3657 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3659 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3660 if(skill202)
3662 level = skill202/5;
3667 // select center of summon position
3668 float center_x = m_targets.m_destX;
3669 float center_y = m_targets.m_destY;
3670 float center_z = m_targets.m_destZ;
3672 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3674 int32 amount = damage > 0 ? damage : 1;
3676 for(int32 count = 0; count < amount; ++count)
3678 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3680 Map *map = m_caster->GetMap();
3681 uint32 pet_number = objmgr.GeneratePetNumber();
3682 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number))
3684 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3685 delete spawnCreature;
3686 return;
3689 float px, py, pz;
3690 // If dest location if present
3691 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3693 // Summon 1 unit in dest location
3694 if (count == 0)
3696 px = m_targets.m_destX;
3697 py = m_targets.m_destY;
3698 pz = m_targets.m_destZ;
3700 // Summon in random point all other units if location present
3701 else
3702 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3704 // Summon if dest location not present near caster
3705 else
3706 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3708 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3710 if(!spawnCreature->IsPositionValid())
3712 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3713 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3714 delete spawnCreature;
3715 return;
3718 if(duration > 0)
3719 spawnCreature->SetDuration(duration);
3721 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3722 spawnCreature->setPowerType(POWER_MANA);
3723 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3724 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3725 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3726 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3727 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3728 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3729 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3731 spawnCreature->InitStatsForLevel(level);
3732 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3734 spawnCreature->AIM_Initialize();
3736 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3737 ((Player*)m_caster)->AddGuardian(spawnCreature);
3739 map->Add((Creature*)spawnCreature);
3743 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3745 if(!unitTarget)
3746 return;
3748 if(unitTarget->isInFlight())
3749 return;
3751 uint32 mapid = m_caster->GetMapId();
3752 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3754 float fx,fy,fz;
3755 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3757 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3758 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
3759 else
3760 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3763 void Spell::EffectLearnSkill(uint32 i)
3765 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3766 return;
3768 if(damage < 0)
3769 return;
3771 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3772 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3773 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3776 void Spell::EffectAddHonor(uint32 /*i*/)
3778 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3779 return;
3781 sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3783 // TODO: find formula for honor reward based on player's level!
3785 // now fixed only for level 70 players:
3786 if (((Player*)unitTarget)->getLevel() == 70)
3787 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3790 void Spell::EffectTradeSkill(uint32 /*i*/)
3792 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3793 return;
3794 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3795 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3796 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3799 void Spell::EffectEnchantItemPerm(uint32 i)
3801 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3802 return;
3803 if (!itemTarget)
3804 return;
3806 Player* p_caster = (Player*)m_caster;
3808 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3810 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3811 if (!enchant_id)
3812 return;
3814 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3815 if(!pEnchant)
3816 return;
3818 // item can be in trade slot and have owner diff. from caster
3819 Player* item_owner = itemTarget->GetOwner();
3820 if(!item_owner)
3821 return;
3823 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3825 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3826 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3827 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3828 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3831 // remove old enchanting before applying new if equipped
3832 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3834 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3836 // add new enchanting if equipped
3837 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3840 void Spell::EffectEnchantItemTmp(uint32 i)
3842 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3843 return;
3845 Player* p_caster = (Player*)m_caster;
3847 if(!itemTarget)
3848 return;
3850 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3852 // Shaman Rockbiter Weapon
3853 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3855 int32 enchnting_damage = m_currentBasePoints[1]+1;
3857 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3858 // with already applied percent bonus from Elemental Weapons talent
3859 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3860 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3861 switch(enchnting_damage)
3863 // Rank 1
3864 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3865 // Rank 2
3866 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3867 case 5: enchant_id = 3025; break; // 20%
3868 // Rank 3
3869 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3870 case 7: enchant_id = 3027; break; // 20%
3871 // Rank 4
3872 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3873 case 10: enchant_id = 503; break; // 14%
3874 case 11: enchant_id = 3031; break; // 20%
3875 // Rank 5
3876 case 15: enchant_id = 3035; break; // 0%
3877 case 16: enchant_id = 1663; break; // 7%
3878 case 17: enchant_id = 3033; break; // 14%
3879 case 18: enchant_id = 3034; break; // 20%
3880 // Rank 6
3881 case 28: enchant_id = 3038; break; // 0%
3882 case 29: enchant_id = 683; break; // 7%
3883 case 31: enchant_id = 3036; break; // 14%
3884 case 33: enchant_id = 3037; break; // 20%
3885 // Rank 7
3886 case 40: enchant_id = 3041; break; // 0%
3887 case 42: enchant_id = 1664; break; // 7%
3888 case 45: enchant_id = 3039; break; // 14%
3889 case 48: enchant_id = 3040; break; // 20%
3890 // Rank 8
3891 case 49: enchant_id = 3044; break; // 0%
3892 case 52: enchant_id = 2632; break; // 7%
3893 case 55: enchant_id = 3042; break; // 14%
3894 case 58: enchant_id = 3043; break; // 20%
3895 // Rank 9
3896 case 62: enchant_id = 2633; break; // 0%
3897 case 66: enchant_id = 3018; break; // 7%
3898 case 70: enchant_id = 3019; break; // 14%
3899 case 74: enchant_id = 3020; break; // 20%
3900 default:
3901 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3902 return;
3906 if (!enchant_id)
3908 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3909 return;
3912 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3913 if(!pEnchant)
3915 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3916 return;
3919 // select enchantment duration
3920 uint32 duration;
3922 // rogue family enchantments exception by duration
3923 if(m_spellInfo->Id==38615)
3924 duration = 1800; // 30 mins
3925 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3926 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3927 duration = 3600; // 1 hour
3928 // shaman family enchantments
3929 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3930 duration = 1800; // 30 mins
3931 // other cases with this SpellVisual already selected
3932 else if(m_spellInfo->SpellVisual[0]==215)
3933 duration = 1800; // 30 mins
3934 // some fishing pole bonuses
3935 else if(m_spellInfo->SpellVisual[0]==563)
3936 duration = 600; // 10 mins
3937 // shaman rockbiter enchantments
3938 else if(m_spellInfo->SpellVisual[0]==0)
3939 duration = 1800; // 30 mins
3940 else if(m_spellInfo->Id==29702)
3941 duration = 300; // 5 mins
3942 else if(m_spellInfo->Id==37360)
3943 duration = 300; // 5 mins
3944 // default case
3945 else
3946 duration = 3600; // 1 hour
3948 // item can be in trade slot and have owner diff. from caster
3949 Player* item_owner = itemTarget->GetOwner();
3950 if(!item_owner)
3951 return;
3953 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3955 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3956 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3957 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3958 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3961 // remove old enchanting before applying new if equipped
3962 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3964 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3966 // add new enchanting if equipped
3967 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3970 void Spell::EffectTameCreature(uint32 /*i*/)
3972 if(m_caster->GetPetGUID())
3973 return;
3975 if(!unitTarget)
3976 return;
3978 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3979 return;
3981 Creature* creatureTarget = (Creature*)unitTarget;
3983 if(creatureTarget->isPet())
3984 return;
3986 if(m_caster->getClass() != CLASS_HUNTER)
3987 return;
3989 // cast finish successfully
3990 //SendChannelUpdate(0);
3991 finish();
3993 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
3995 // kill original creature
3996 creatureTarget->setDeathState(JUST_DIED);
3997 creatureTarget->RemoveCorpse();
3998 creatureTarget->SetHealth(0); // just for nice GM-mode view
4000 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4002 // prepare visual effect for levelup
4003 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4005 // add to world
4006 pet->GetMap()->Add((Creature*)pet);
4008 // visual effect for levelup
4009 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4011 // caster have pet now
4012 m_caster->SetPet(pet);
4014 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4016 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4017 ((Player*)m_caster)->PetSpellInitialize();
4021 void Spell::EffectSummonPet(uint32 i)
4023 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4025 Pet *OldSummon = m_caster->GetPet();
4027 // if pet requested type already exist
4028 if( OldSummon )
4030 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4032 // pet in corpse state can't be summoned
4033 if( OldSummon->isDead() )
4034 return;
4036 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4037 OldSummon->SetMapId(m_caster->GetMapId());
4039 float px, py, pz;
4040 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4042 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4043 m_caster->GetMap()->Add((Creature*)OldSummon);
4045 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4047 ((Player*)m_caster)->PetSpellInitialize();
4049 return;
4052 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4053 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4054 else
4055 return;
4058 Pet* NewSummon = new Pet;
4060 // petentry==0 for hunter "call pet" (current pet summoned if any)
4061 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4063 if(NewSummon->getPetType()==SUMMON_PET)
4065 // Remove Demonic Sacrifice auras (known pet)
4066 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4067 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4069 if((*itr)->GetModifier()->m_miscvalue==2228)
4071 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4072 itr = auraClassScripts.begin();
4074 else
4075 ++itr;
4079 return;
4082 // not error in case fail hunter call pet
4083 if(!petentry)
4085 delete NewSummon;
4086 return;
4089 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4091 if(!cInfo)
4093 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4094 delete NewSummon;
4095 return;
4098 Map *map = m_caster->GetMap();
4099 uint32 pet_number = objmgr.GeneratePetNumber();
4100 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
4102 delete NewSummon;
4103 return;
4106 float px, py, pz;
4107 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4109 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4111 if(!NewSummon->IsPositionValid())
4113 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4114 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4115 delete NewSummon;
4116 return;
4119 uint32 petlevel = m_caster->getLevel();
4120 NewSummon->setPetType(SUMMON_PET);
4122 uint32 faction = m_caster->getFaction();
4123 if(m_caster->GetTypeId() == TYPEID_UNIT)
4125 if ( ((Creature*)m_caster)->isTotem() )
4126 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4127 else
4128 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4131 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4132 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4133 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4134 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4135 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4136 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4137 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4138 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4139 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4140 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4142 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4143 // this enables pet details window (Shift+P)
4145 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4146 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4147 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4149 NewSummon->InitStatsForLevel(petlevel);
4150 NewSummon->InitPetCreateSpells();
4151 NewSummon->InitTalentForLevel();
4153 if(NewSummon->getPetType()==SUMMON_PET)
4155 // Remove Demonic Sacrifice auras (new pet)
4156 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4157 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4159 if((*itr)->GetModifier()->m_miscvalue==2228)
4161 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4162 itr = auraClassScripts.begin();
4164 else
4165 ++itr;
4168 // generate new name for summon pet
4169 std::string new_name=objmgr.GeneratePetName(petentry);
4170 if(!new_name.empty())
4171 NewSummon->SetName(new_name);
4173 else if(NewSummon->getPetType()==HUNTER_PET)
4174 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4176 NewSummon->AIM_Initialize();
4177 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4178 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4180 map->Add((Creature*)NewSummon);
4182 m_caster->SetPet(NewSummon);
4183 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4185 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4187 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4188 ((Player*)m_caster)->PetSpellInitialize();
4192 void Spell::EffectLearnPetSpell(uint32 i)
4194 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4195 return;
4197 Player *_player = (Player*)m_caster;
4199 Pet *pet = _player->GetPet();
4200 if(!pet)
4201 return;
4202 if(!pet->isAlive())
4203 return;
4205 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4206 if(!learn_spellproto)
4207 return;
4209 pet->learnSpell(learn_spellproto->Id);
4211 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4212 _player->PetSpellInitialize();
4215 void Spell::EffectTaunt(uint32 /*i*/)
4217 // this effect use before aura Taunt apply for prevent taunt already attacking target
4218 // for spell as marked "non effective at already attacking target"
4219 if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4221 if(unitTarget->getVictim()==m_caster)
4223 SendCastResult(SPELL_FAILED_DONT_REPORT);
4224 return;
4228 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4229 if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4230 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4233 void Spell::EffectWeaponDmg(uint32 i)
4235 if(!unitTarget)
4236 return;
4237 if(!unitTarget->isAlive())
4238 return;
4240 // multiple weapon dmg effect workaround
4241 // execute only the last weapon damage
4242 // and handle all effects at once
4243 for (int j = 0; j < 3; j++)
4245 switch(m_spellInfo->Effect[j])
4247 case SPELL_EFFECT_WEAPON_DAMAGE:
4248 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4249 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4250 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4251 if (j < i) // we must calculate only at last weapon effect
4252 return;
4253 break;
4257 // some spell specific modifiers
4258 bool customBonusDamagePercentMod = false;
4259 float bonusDamagePercentMod = 1.0f; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4260 float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4261 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4262 bool normalized = false;
4264 int32 spell_bonus = 0; // bonus specific for spell
4265 switch(m_spellInfo->SpellFamilyName)
4267 case SPELLFAMILY_WARRIOR:
4269 // Whirlwind, single only spell with 2 weapon white damage apply if have
4270 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4272 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4273 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4275 // Devastate bonus and sunder armor refresh
4276 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4278 uint32 stack = 0;
4279 // Need refresh all Sunder Armor auras from this caster
4280 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4281 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4283 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4284 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4285 spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
4286 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4288 (*itr).second->RefreshAura();
4289 stack = (*itr).second->GetStackAmount();
4292 if (stack)
4293 spell_bonus += stack * CalculateDamage(2, unitTarget);
4295 break;
4297 case SPELLFAMILY_ROGUE:
4299 // Ambush
4300 if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4302 customBonusDamagePercentMod = true;
4303 bonusDamagePercentMod = 2.5f; // 250%
4305 // Mutilate (for each hand)
4306 else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4308 bool found = false;
4309 // fast check
4310 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4311 found = true;
4312 // full aura scan
4313 else
4315 Unit::AuraMap const& auras = unitTarget->GetAuras();
4316 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4318 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4320 found = true;
4321 break;
4326 if(found)
4327 totalDamagePercentMod *= 1.5f; // 150% if poisoned
4329 break;
4331 case SPELLFAMILY_PALADIN:
4333 // Seal of Command - receive benefit from Spell Damage and Healing
4334 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4336 spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4337 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4339 break;
4341 case SPELLFAMILY_SHAMAN:
4343 // Skyshatter Harness item set bonus
4344 // Stormstrike
4345 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4347 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4348 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4350 // Stormstrike AP Buff
4351 if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4353 m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4354 break;
4361 int32 fixed_bonus = 0;
4362 for (int j = 0; j < 3; j++)
4364 switch(m_spellInfo->Effect[j])
4366 case SPELL_EFFECT_WEAPON_DAMAGE:
4367 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4368 fixed_bonus += CalculateDamage(j,unitTarget);
4369 break;
4370 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4371 fixed_bonus += CalculateDamage(j,unitTarget);
4372 normalized = true;
4373 break;
4374 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4375 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4377 // applied only to prev.effects fixed damage
4378 if(customBonusDamagePercentMod)
4379 fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4380 else
4381 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4382 break;
4383 default:
4384 break; // not weapon damage effect, just skip
4388 // non-weapon damage
4389 int32 bonus = spell_bonus + fixed_bonus;
4391 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4392 if(bonus)
4394 UnitMods unitMod;
4395 switch(m_attackType)
4397 default:
4398 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4399 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4400 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4403 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4404 bonus = int32(bonus*weapon_total_pct);
4407 // + weapon damage with applied weapon% dmg to base weapon damage in call
4408 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4410 // total damage
4411 bonus = int32(bonus*totalDamagePercentMod);
4413 // prevent negative damage
4414 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4416 // Add melee damage bonuses (also check for negative)
4417 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4418 m_damage+= eff_damage;
4420 // Hemorrhage
4421 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4423 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4424 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4427 // Mangle (Cat): CP
4428 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4430 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4431 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4434 // take ammo
4435 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4437 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4439 // wands don't have ammo
4440 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4441 return;
4443 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4445 if(pItem->GetMaxStackCount()==1)
4447 // decrease durability for non-stackable throw weapon
4448 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4450 else
4452 // decrease items amount for stackable throw weapon
4453 uint32 count = 1;
4454 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4457 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4458 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4462 void Spell::EffectThreat(uint32 /*i*/)
4464 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4465 return;
4467 if(!unitTarget->CanHaveThreatList())
4468 return;
4470 unitTarget->AddThreat(m_caster, float(damage));
4473 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4475 if(!unitTarget)
4476 return;
4477 if(!unitTarget->isAlive())
4478 return;
4480 uint32 heal = m_caster->GetMaxHealth();
4482 m_healing+=heal;
4485 void Spell::EffectInterruptCast(uint32 /*i*/)
4487 if(!unitTarget)
4488 return;
4489 if(!unitTarget->isAlive())
4490 return;
4492 // TODO: not all spells that used this effect apply cooldown at school spells
4493 // also exist case: apply cooldown to interrupted cast only and to all spells
4494 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4496 if (unitTarget->m_currentSpells[i])
4498 // check if we can interrupt spell
4499 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4501 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4502 unitTarget->InterruptSpell(i,false);
4508 void Spell::EffectSummonObjectWild(uint32 i)
4510 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4512 GameObject* pGameObj = new GameObject;
4514 WorldObject* target = focusObject;
4515 if( !target )
4516 target = m_caster;
4518 float x,y,z;
4519 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4521 x = m_targets.m_destX;
4522 y = m_targets.m_destY;
4523 z = m_targets.m_destZ;
4525 else
4526 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4528 Map *map = target->GetMap();
4530 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4531 x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4533 delete pGameObj;
4534 return;
4537 int32 duration = GetSpellDuration(m_spellInfo);
4538 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4539 pGameObj->SetSpellId(m_spellInfo->Id);
4541 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4542 m_caster->AddGameObject(pGameObj);
4543 map->Add(pGameObj);
4545 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4547 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4549 Player *pl = (Player*)m_caster;
4550 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4551 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4553 uint32 team = ALLIANCE;
4555 if(pl->GetTeam() == team)
4556 team = HORDE;
4558 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4563 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4565 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4567 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4568 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4570 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4575 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4577 GameObject* linkedGO = new GameObject;
4578 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4579 x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4581 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4582 linkedGO->SetSpellId(m_spellInfo->Id);
4584 m_caster->AddGameObject(linkedGO);
4585 map->Add(linkedGO);
4587 else
4589 delete linkedGO;
4590 linkedGO = NULL;
4591 return;
4596 void Spell::EffectScriptEffect(uint32 effIndex)
4598 // TODO: we must implement hunter pet summon at login there (spell 6962)
4600 switch(m_spellInfo->SpellFamilyName)
4602 case SPELLFAMILY_GENERIC:
4604 switch(m_spellInfo->Id)
4606 // PX-238 Winter Wondervolt TRAP
4607 case 26275:
4609 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4611 // check presence
4612 for(int j = 0; j < 4; ++j)
4613 if(unitTarget->HasAura(spells[j],0))
4614 return;
4616 // select spell
4617 uint32 iTmpSpellId = spells[urand(0,3)];
4619 // cast
4620 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4621 return;
4623 // Bending Shinbone
4624 case 8856:
4626 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4627 return;
4629 uint32 spell_id = 0;
4630 switch(urand(1,5))
4632 case 1: spell_id = 8854; break;
4633 default: spell_id = 8855; break;
4636 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4637 return;
4639 // Brittle Armor - need remove one 24575 Brittle Armor aura
4640 case 24590:
4641 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4642 return;
4643 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4644 case 26465:
4645 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4646 return;
4647 // Orb teleport spells
4648 case 25140:
4649 case 25143:
4650 case 25650:
4651 case 25652:
4652 case 29128:
4653 case 29129:
4654 case 35376:
4655 case 35727:
4657 if(!unitTarget)
4658 return;
4660 uint32 spellid;
4661 switch(m_spellInfo->Id)
4663 case 25140: spellid = 32571; break;
4664 case 25143: spellid = 32572; break;
4665 case 25650: spellid = 30140; break;
4666 case 25652: spellid = 30141; break;
4667 case 29128: spellid = 32568; break;
4668 case 29129: spellid = 32569; break;
4669 case 35376: spellid = 25649; break;
4670 case 35727: spellid = 35730; break;
4671 default:
4672 return;
4675 unitTarget->CastSpell(unitTarget,spellid,false);
4676 return;
4678 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4679 case 22539:
4680 case 22972:
4681 case 22975:
4682 case 22976:
4683 case 22977:
4684 case 22978:
4685 case 22979:
4686 case 22980:
4687 case 22981:
4688 case 22982:
4689 case 22983:
4690 case 22984:
4691 case 22985:
4693 if(!unitTarget || !unitTarget->isAlive())
4694 return;
4696 // Onyxia Scale Cloak
4697 if(unitTarget->GetDummyAura(22683))
4698 return;
4700 // Shadow Flame
4701 m_caster->CastSpell(unitTarget, 22682, true);
4702 return;
4704 // Summon Black Qiraji Battle Tank
4705 case 26656:
4707 if(!unitTarget)
4708 return;
4710 // Prevent stacking of mounts
4711 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4713 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4714 if (unitTarget->GetAreaId() == 3428)
4715 unitTarget->CastSpell(unitTarget, 25863, false);
4716 else
4717 unitTarget->CastSpell(unitTarget, 26655, false);
4718 break;
4720 // Piccolo of the Flaming Fire
4721 case 17512:
4723 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4724 return;
4725 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4726 break;
4728 // Mirren's Drinking Hat
4729 case 29830:
4731 uint32 item = 0;
4732 switch ( urand(1,6) )
4734 case 1:case 2:case 3:
4735 item = 23584;break; // Loch Modan Lager
4736 case 4:case 5:
4737 item = 23585;break; // Stouthammer Lite
4738 case 6:
4739 item = 23586;break; // Aerie Peak Pale Ale
4741 if (item)
4742 DoCreateItem(effIndex,item);
4743 break;
4745 // Improved Sprint
4746 case 30918:
4748 // Removes snares and roots.
4749 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4750 Unit::AuraMap& Auras = unitTarget->GetAuras();
4751 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4753 next = iter;
4754 ++next;
4755 Aura *aur = iter->second;
4756 if (!aur->IsPositive()) //only remove negative spells
4758 // check for mechanic mask
4759 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4761 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4762 if(Auras.empty())
4763 break;
4764 else
4765 next = Auras.begin();
4769 break;
4771 // Flame Crash
4772 case 41126:
4774 if(!unitTarget)
4775 return;
4777 unitTarget->CastSpell(unitTarget, 41131, true);
4778 break;
4780 // Force Cast - Portal Effect: Sunwell Isle
4781 case 44876:
4783 if(!unitTarget)
4784 return;
4786 unitTarget->CastSpell(unitTarget, 44870, true);
4787 break;
4789 // Goblin Weather Machine
4790 case 46203:
4792 if(!unitTarget)
4793 return;
4795 uint32 spellId;
4796 switch(rand()%4)
4798 case 0: spellId = 46740; break;
4799 case 1: spellId = 46739; break;
4800 case 2: spellId = 46738; break;
4801 case 3: spellId = 46736; break;
4803 unitTarget->CastSpell(unitTarget, spellId, true);
4804 break;
4806 //5,000 Gold
4807 case 46642:
4809 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4810 return;
4812 ((Player*)unitTarget)->ModifyMoney(50000000);
4814 break;
4816 // Emblazon Runeblade
4817 case 51770:
4819 if(!unitTarget)
4820 return;
4822 unitTarget->CastSpell(unitTarget,51771,false);
4823 break;
4825 // Death Gate
4826 case 52751:
4828 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
4829 return;
4830 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4831 unitTarget->CastSpell(unitTarget, damage, false);
4832 break;
4834 // random spell learn instead placeholder
4835 case 60893: // Northrend Alchemy Research
4836 case 61177: // Northrend Inscription Research
4837 case 61288: // Minor Inscription Research
4838 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4840 if(!IsExplicitDiscoverySpell(m_spellInfo))
4842 sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id);
4843 return;
4846 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
4847 return;
4848 Player* player = (Player*)m_caster;
4850 // need replace effect 0 item by loot
4851 uint32 reagent_id = m_spellInfo->EffectItemType[0];
4853 if(!player->HasItemCount(reagent_id,1))
4854 return;
4856 // remove reagent
4857 uint32 count = 1;
4858 player->DestroyItemCount (reagent_id,count,true);
4860 // create some random items
4861 player->AutoStoreLootItem(m_spellInfo->Id,LootTemplates_Spell);
4863 // learn random explicit discovery recipe (if any)
4864 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
4865 player->learnSpell(discoveredSpell,false);
4866 return;
4869 break;
4871 case SPELLFAMILY_WARLOCK:
4873 switch(m_spellInfo->Id)
4875 // Healthstone creating spells
4876 case 6201:
4877 case 6202:
4878 case 5699:
4879 case 11729:
4880 case 11730:
4881 case 27230:
4882 case 47871:
4883 case 47878:
4885 uint32 itemtype;
4886 uint32 rank = 0;
4887 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4888 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4890 if((*i)->GetId() == 18692)
4892 rank = 1;
4893 break;
4895 else if((*i)->GetId() == 18693)
4897 rank = 2;
4898 break;
4902 static uint32 const itypes[8][3] = {
4903 { 5512,19004,19005}, // Minor Healthstone
4904 { 5511,19006,19007}, // Lesser Healthstone
4905 { 5509,19008,19009}, // Healthstone
4906 { 5510,19010,19011}, // Greater Healthstone
4907 { 9421,19012,19013}, // Major Healthstone
4908 {22103,22104,22105}, // Master Healthstone
4909 {36889,36890,36891}, // Demonic Healthstone
4910 {36892,36893,36894} // Fel Healthstone
4913 switch(m_spellInfo->Id)
4915 case 6201:
4916 itemtype=itypes[0][rank];break; // Minor Healthstone
4917 case 6202:
4918 itemtype=itypes[1][rank];break; // Lesser Healthstone
4919 case 5699:
4920 itemtype=itypes[2][rank];break; // Healthstone
4921 case 11729:
4922 itemtype=itypes[3][rank];break; // Greater Healthstone
4923 case 11730:
4924 itemtype=itypes[4][rank];break; // Major Healthstone
4925 case 27230:
4926 itemtype=itypes[5][rank];break; // Master Healthstone
4927 case 47871:
4928 itemtype=itypes[6][rank];break; // Demonic Healthstone
4929 case 47878:
4930 itemtype=itypes[7][rank];break; // Fel Healthstone
4931 default:
4932 return;
4934 DoCreateItem( effIndex, itemtype );
4935 return;
4938 break;
4940 case SPELLFAMILY_HUNTER:
4942 switch(m_spellInfo->Id)
4944 // Chimera Shot
4945 case 53209:
4947 uint32 spellId = 0;
4948 int32 basePoint = 0;
4949 Unit::AuraMap& Auras = unitTarget->GetAuras();
4950 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
4952 Aura *aura = (*i).second;
4953 if (aura->GetCasterGUID() != m_caster->GetGUID())
4954 continue;
4955 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
4956 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
4957 if (!(familyFlag & 0x000000800000C000LL))
4958 continue;
4959 // Refresh aura duration
4960 aura->RefreshAura();
4962 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
4963 if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
4965 spellId = 53353; // 53353 Chimera Shot - Serpent
4966 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
4968 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
4969 if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
4971 spellId = 53358; // 53358 Chimera Shot - Viper
4972 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
4974 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
4975 if (familyFlag & 0x0000000000008000LL)
4976 spellId = 53359; // 53359 Chimera Shot - Scorpid
4977 // ?? nothing say in spell desc (possibly need addition check)
4978 //if (familyFlag & 0x0000010000000000LL || // dot
4979 // familyFlag & 0x0000100000000000LL) // stun
4981 // spellId = 53366; // 53366 Chimera Shot - Wyvern
4984 if (spellId)
4985 m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
4986 return;
4988 default:
4989 break;
4991 break;
4993 case SPELLFAMILY_PALADIN:
4995 // Judgement
4996 if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
4998 if(!unitTarget || !unitTarget->isAlive())
4999 return;
5000 uint32 spellId1 = 0;
5001 uint32 spellId2 = 0;
5003 // Judgement self add switch
5004 switch (m_spellInfo->Id)
5006 case 41467: break; // Judgement
5007 case 53407: spellId1 = 20184; break; // Judgement of Justice
5008 case 20271: // Judgement of Light
5009 case 57774: spellId1 = 20185; break; // Judgement of Light
5010 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5011 default:
5012 return;
5014 // all seals have aura dummy in 2 effect
5015 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5016 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5018 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5019 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5020 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5021 continue;
5022 spellId2 = (*itr)->GetModifier()->m_amount;
5023 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5024 if (!judge)
5025 continue;
5026 break;
5028 if (spellId1)
5029 m_caster->CastSpell(unitTarget, spellId1, true);
5030 if (spellId2)
5031 m_caster->CastSpell(unitTarget, spellId2, true);
5032 return;
5035 case SPELLFAMILY_POTION:
5037 switch(m_spellInfo->Id)
5039 // Dreaming Glory
5040 case 28698:
5042 if(!unitTarget)
5043 return;
5044 unitTarget->CastSpell(unitTarget, 28694, true);
5045 break;
5047 // Netherbloom
5048 case 28702:
5050 if(!unitTarget)
5051 return;
5052 // 25% chance of casting a random buff
5053 if(roll_chance_i(75))
5054 return;
5056 // triggered spells are 28703 to 28707
5057 // Note: some sources say, that there was the possibility of
5058 // receiving a debuff. However, this seems to be removed by a patch.
5059 const uint32 spellid = 28703;
5061 // don't overwrite an existing aura
5062 for(uint8 i=0; i<5; i++)
5063 if(unitTarget->HasAura(spellid+i, 0))
5064 return;
5065 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5066 break;
5069 // Nightmare Vine
5070 case 28720:
5072 if(!unitTarget)
5073 return;
5074 // 25% chance of casting Nightmare Pollen
5075 if(roll_chance_i(75))
5076 return;
5077 unitTarget->CastSpell(unitTarget, 28721, true);
5078 break;
5081 break;
5085 // normal DB scripted effect
5086 if(!unitTarget)
5087 return;
5089 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5090 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5093 void Spell::EffectSanctuary(uint32 /*i*/)
5095 if(!unitTarget)
5096 return;
5097 //unitTarget->CombatStop();
5099 unitTarget->CombatStop();
5100 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5101 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5102 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5104 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5108 void Spell::EffectAddComboPoints(uint32 /*i*/)
5110 if(!unitTarget)
5111 return;
5113 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5114 return;
5116 if(damage <= 0)
5117 return;
5119 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5122 void Spell::EffectDuel(uint32 i)
5124 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5125 return;
5127 Player *caster = (Player*)m_caster;
5128 Player *target = (Player*)unitTarget;
5130 // caster or target already have requested duel
5131 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5132 return;
5134 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5135 // Don't have to check the target's map since you cannot challenge someone across maps
5136 uint32 mapid = caster->GetMapId();
5137 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5139 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5140 return;
5143 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5144 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5146 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5147 return;
5150 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5151 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5153 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5154 return;
5157 //CREATE DUEL FLAG OBJECT
5158 GameObject* pGameObj = new GameObject;
5160 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5162 Map *map = m_caster->GetMap();
5163 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5164 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5165 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5166 m_caster->GetPositionZ(),
5167 m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5169 delete pGameObj;
5170 return;
5173 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5174 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5175 int32 duration = GetSpellDuration(m_spellInfo);
5176 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5177 pGameObj->SetSpellId(m_spellInfo->Id);
5179 m_caster->AddGameObject(pGameObj);
5180 map->Add(pGameObj);
5181 //END
5183 // Send request
5184 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5185 data << pGameObj->GetGUID();
5186 data << caster->GetGUID();
5187 caster->GetSession()->SendPacket(&data);
5188 target->GetSession()->SendPacket(&data);
5190 // create duel-info
5191 DuelInfo *duel = new DuelInfo;
5192 duel->initiator = caster;
5193 duel->opponent = target;
5194 duel->startTime = 0;
5195 duel->startTimer = 0;
5196 caster->duel = duel;
5198 DuelInfo *duel2 = new DuelInfo;
5199 duel2->initiator = caster;
5200 duel2->opponent = caster;
5201 duel2->startTime = 0;
5202 duel2->startTimer = 0;
5203 target->duel = duel2;
5205 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5206 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5209 void Spell::EffectStuck(uint32 /*i*/)
5211 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5212 return;
5214 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5215 return;
5217 Player* pTarget = (Player*)unitTarget;
5219 sLog.outDebug("Spell Effect: Stuck");
5220 sLog.outDetail("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", pTarget->GetName(), pTarget->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ());
5222 if(pTarget->isInFlight())
5223 return;
5225 // homebind location is loaded always
5226 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5228 // Stuck spell trigger Hearthstone cooldown
5229 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5230 if(!spellInfo)
5231 return;
5232 Spell spell(pTarget,spellInfo,true,0);
5233 spell.SendSpellCooldown();
5236 void Spell::EffectSummonPlayer(uint32 /*i*/)
5238 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5239 return;
5241 // Evil Twin (ignore player summon, but hide this for summoner)
5242 if(unitTarget->GetDummyAura(23445))
5243 return;
5245 float x,y,z;
5246 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5248 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5250 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5251 data << uint64(m_caster->GetGUID()); // summoner guid
5252 data << uint32(m_caster->GetZoneId()); // summoner zone
5253 data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs
5254 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5257 static ScriptInfo generateActivateCommand()
5259 ScriptInfo si;
5260 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5261 return si;
5264 void Spell::EffectActivateObject(uint32 effect_idx)
5266 if(!gameObjTarget)
5267 return;
5269 static ScriptInfo activateCommand = generateActivateCommand();
5271 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5273 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5276 void Spell::EffectApplyGlyph(uint32 i)
5278 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5279 return;
5281 Player *player = (Player*)m_caster;
5283 // remove old glyph
5284 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5286 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5288 player->RemoveAurasDueToSpell(old_gp->SpellId);
5289 player->SetGlyph(m_glyphIndex, 0);
5293 // apply new one
5294 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5296 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5298 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5300 if(gp->TypeFlags != gs->TypeFlags)
5302 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5303 return; // glyph slot missmatch
5307 player->CastSpell(m_caster, gp->SpellId, true);
5308 player->SetGlyph(m_glyphIndex, glyph);
5313 void Spell::EffectSummonTotem(uint32 i)
5315 uint8 slot = 0;
5316 switch(m_spellInfo->EffectMiscValueB[i])
5318 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5319 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5320 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5321 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5322 // Battle standard case
5323 case SUMMON_TYPE_TOTEM: slot = 254; break;
5324 // jewelery statue case, like totem without slot
5325 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5326 default: return;
5329 if(slot < MAX_TOTEM)
5331 uint64 guid = m_caster->m_TotemSlot[slot];
5332 if(guid != 0)
5334 Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5335 if(OldTotem && OldTotem->isTotem())
5336 ((Totem*)OldTotem)->UnSummon();
5340 uint32 team = 0;
5341 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5342 team = ((Player*)m_caster)->GetTeam();
5344 Totem* pTotem = new Totem;
5346 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
5348 delete pTotem;
5349 return;
5352 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5354 float x,y,z;
5355 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5357 // totem must be at same Z in case swimming caster and etc.
5358 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5359 z = m_caster->GetPositionZ();
5361 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5363 if(slot < MAX_TOTEM)
5364 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5366 pTotem->SetOwner(m_caster->GetGUID());
5367 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5369 int32 duration=GetSpellDuration(m_spellInfo);
5370 if(Player* modOwner = m_caster->GetSpellModOwner())
5371 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5372 pTotem->SetDuration(duration);
5374 if (damage) // if not spell info, DB values used
5376 pTotem->SetMaxHealth(damage);
5377 pTotem->SetHealth(damage);
5380 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5382 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5383 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5385 pTotem->Summon(m_caster);
5387 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5389 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5390 data << uint8(slot);
5391 data << uint64(pTotem->GetGUID());
5392 data << uint32(duration);
5393 data << uint32(m_spellInfo->Id);
5394 ((Player*)m_caster)->SendDirectMessage(&data);
5398 void Spell::EffectEnchantHeldItem(uint32 i)
5400 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5401 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5402 return;
5404 Player* item_owner = (Player*)unitTarget;
5405 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5407 if(!item )
5408 return;
5410 // must be equipped
5411 if(!item ->IsEquipped())
5412 return;
5414 if (m_spellInfo->EffectMiscValue[i])
5416 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5417 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5418 if(!duration)
5419 duration = m_currentBasePoints[i]+1; //Base points after ..
5420 if(!duration)
5421 duration = 10; //10 seconds for enchants which don't have listed duration
5423 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5424 if(!pEnchant)
5425 return;
5427 // Always go to temp enchantment slot
5428 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5430 // Enchantment will not be applied if a different one already exists
5431 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5432 return;
5434 // Apply the temporary enchantment
5435 item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5436 item_owner->ApplyEnchantment(item,slot,true);
5440 void Spell::EffectDisEnchant(uint32 /*i*/)
5442 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5443 return;
5445 Player* p_caster = (Player*)m_caster;
5446 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5447 return;
5449 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5451 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5453 // item will be removed at disenchanting end
5456 void Spell::EffectInebriate(uint32 /*i*/)
5458 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5459 return;
5461 Player *player = (Player*)unitTarget;
5462 uint16 currentDrunk = player->GetDrunkValue();
5463 uint16 drunkMod = damage * 256;
5464 if (currentDrunk + drunkMod > 0xFFFF)
5465 currentDrunk = 0xFFFF;
5466 else
5467 currentDrunk += drunkMod;
5468 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5471 void Spell::EffectFeedPet(uint32 i)
5473 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5474 return;
5476 Player *_player = (Player*)m_caster;
5478 Item* foodItem = m_targets.getItemTarget();
5479 if(!foodItem)
5480 return;
5482 Pet *pet = _player->GetPet();
5483 if(!pet)
5484 return;
5486 if(!pet->isAlive())
5487 return;
5489 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5490 if(benefit <= 0)
5491 return;
5493 uint32 count = 1;
5494 _player->DestroyItemCount(foodItem,count,true);
5495 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5497 m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5500 void Spell::EffectDismissPet(uint32 /*i*/)
5502 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5503 return;
5505 Pet* pet = m_caster->GetPet();
5507 // not let dismiss dead pet
5508 if(!pet||!pet->isAlive())
5509 return;
5511 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5514 void Spell::EffectSummonObject(uint32 i)
5516 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5518 uint8 slot = 0;
5519 switch(m_spellInfo->Effect[i])
5521 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5522 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5523 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5524 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5525 default: return;
5528 uint64 guid = m_caster->m_ObjectSlot[slot];
5529 if(guid != 0)
5531 GameObject* obj = NULL;
5532 if( m_caster )
5533 obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5535 if(obj) obj->Delete();
5536 m_caster->m_ObjectSlot[slot] = 0;
5539 GameObject* pGameObj = new GameObject;
5541 float rot2 = sin(m_caster->GetOrientation()/2);
5542 float rot3 = cos(m_caster->GetOrientation()/2);
5544 float x,y,z;
5545 // If dest location if present
5546 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5548 x = m_targets.m_destX;
5549 y = m_targets.m_destY;
5550 z = m_targets.m_destZ;
5552 // Summon in random point all other units if location present
5553 else
5554 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5556 Map *map = m_caster->GetMap();
5557 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5559 delete pGameObj;
5560 return;
5563 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5564 int32 duration = GetSpellDuration(m_spellInfo);
5565 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5566 pGameObj->SetSpellId(m_spellInfo->Id);
5567 m_caster->AddGameObject(pGameObj);
5569 map->Add(pGameObj);
5570 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5571 data << pGameObj->GetGUID();
5572 m_caster->SendMessageToSet(&data,true);
5574 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5577 void Spell::EffectResurrect(uint32 /*effIndex*/)
5579 if(!unitTarget)
5580 return;
5581 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5582 return;
5584 if(unitTarget->isAlive())
5585 return;
5586 if(!unitTarget->IsInWorld())
5587 return;
5589 switch (m_spellInfo->Id)
5591 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5592 case 8342:
5593 if (roll_chance_i(67))
5595 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5596 return;
5598 break;
5599 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5600 case 22999:
5601 if (roll_chance_i(50))
5603 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5604 return;
5606 break;
5607 default:
5608 break;
5611 Player* pTarget = ((Player*)unitTarget);
5613 if(pTarget->isRessurectRequested()) // already have one active request
5614 return;
5616 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5617 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5619 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5620 SendResurrectRequest(pTarget);
5623 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5625 if(!unitTarget || !unitTarget->isAlive())
5626 return;
5628 if( unitTarget->m_extraAttacks )
5629 return;
5631 unitTarget->m_extraAttacks = damage;
5634 void Spell::EffectParry(uint32 /*i*/)
5636 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5637 ((Player*)unitTarget)->SetCanParry(true);
5640 void Spell::EffectBlock(uint32 /*i*/)
5642 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5643 ((Player*)unitTarget)->SetCanBlock(true);
5646 void Spell::EffectMomentMove(uint32 i)
5648 if(unitTarget->isInFlight())
5649 return;
5651 if( m_spellInfo->rangeIndex== 1) //self range
5653 uint32 mapid = m_caster->GetMapId();
5654 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5656 // before caster
5657 float fx,fy,fz;
5658 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5659 float ox,oy,oz;
5660 unitTarget->GetPosition(ox,oy,oz);
5662 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5663 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5665 fx = fx2;
5666 fy = fy2;
5667 fz = fz2;
5668 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5671 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5672 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5673 else
5674 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5678 void Spell::EffectReputation(uint32 i)
5680 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5681 return;
5683 Player *_player = (Player*)unitTarget;
5685 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5687 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5689 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5691 if(!factionEntry)
5692 return;
5694 _player->ModifyFactionReputation(factionEntry,rep_change);
5697 void Spell::EffectQuestComplete(uint32 i)
5699 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5700 return;
5702 Player *_player = (Player*)m_caster;
5704 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5705 _player->AreaExploredOrEventHappens(quest_id);
5708 void Spell::EffectSelfResurrect(uint32 i)
5710 if(!unitTarget || unitTarget->isAlive())
5711 return;
5712 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5713 return;
5714 if(!unitTarget->IsInWorld())
5715 return;
5717 uint32 health = 0;
5718 uint32 mana = 0;
5720 // flat case
5721 if(damage < 0)
5723 health = uint32(-damage);
5724 mana = m_spellInfo->EffectMiscValue[i];
5726 // percent case
5727 else
5729 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5730 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5731 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5734 Player *plr = ((Player*)unitTarget);
5735 plr->ResurrectPlayer(0.0f);
5737 plr->SetHealth( health );
5738 plr->SetPower(POWER_MANA, mana );
5739 plr->SetPower(POWER_RAGE, 0 );
5740 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5742 plr->SpawnCorpseBones();
5744 plr->SaveToDB();
5747 void Spell::EffectSkinning(uint32 /*i*/)
5749 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5750 return;
5751 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5752 return;
5754 Creature* creature = (Creature*) unitTarget;
5755 int32 targetLevel = creature->getLevel();
5757 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5759 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5760 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5762 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5764 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5766 // Double chances for elites
5767 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5770 void Spell::EffectCharge(uint32 /*i*/)
5772 if(!unitTarget || !m_caster)
5773 return;
5775 float x, y, z;
5776 unitTarget->GetContactPoint(m_caster, x, y, z);
5777 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5778 ((Creature *)unitTarget)->StopMoving();
5780 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5781 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5783 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5784 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5786 // not all charge effects used in negative spells
5787 if ( !IsPositiveSpell(m_spellInfo->Id))
5788 m_caster->Attack(unitTarget,true);
5791 void Spell::EffectSummonCritter(uint32 i)
5793 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5794 return;
5795 Player* player = (Player*)m_caster;
5797 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5798 if(!pet_entry)
5799 return;
5801 Pet* old_critter = player->GetMiniPet();
5803 // for same pet just despawn
5804 if(old_critter && old_critter->GetEntry() == pet_entry)
5806 player->RemoveMiniPet();
5807 return;
5810 // despawn old pet before summon new
5811 if(old_critter)
5812 player->RemoveMiniPet();
5814 // summon new pet
5815 Pet* critter = new Pet(MINI_PET);
5817 Map *map = m_caster->GetMap();
5818 uint32 pet_number = objmgr.GeneratePetNumber();
5819 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
5820 map, pet_entry, pet_number))
5822 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5823 delete critter;
5824 return;
5827 float x,y,z;
5828 // If dest location if present
5829 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5831 x = m_targets.m_destX;
5832 y = m_targets.m_destY;
5833 z = m_targets.m_destZ;
5835 // Summon if dest location not present near caster
5836 else
5837 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5839 critter->Relocate(x,y,z,m_caster->GetOrientation());
5841 if(!critter->IsPositionValid())
5843 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5844 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5845 delete critter;
5846 return;
5849 critter->SetOwnerGUID(m_caster->GetGUID());
5850 critter->SetCreatorGUID(m_caster->GetGUID());
5851 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5852 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5854 critter->AIM_Initialize();
5855 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5856 critter->SetMaxHealth(1);
5857 critter->SetHealth(1);
5858 critter->SetLevel(1);
5860 // set timer for unsummon
5861 int32 duration = GetSpellDuration(m_spellInfo);
5862 if(duration > 0)
5863 critter->SetDuration(duration);
5865 std::string name = player->GetName();
5866 name.append(petTypeSuffix[critter->getPetType()]);
5867 critter->SetName( name );
5868 player->SetMiniPet(critter);
5870 map->Add((Creature*)critter);
5873 void Spell::EffectKnockBack(uint32 i)
5875 if(!unitTarget || !m_caster)
5876 return;
5878 // Effect only works on players
5879 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5880 return;
5882 float vsin = sin(m_caster->GetAngle(unitTarget));
5883 float vcos = cos(m_caster->GetAngle(unitTarget));
5885 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5886 data.append(unitTarget->GetPackGUID());
5887 data << uint32(0); // Sequence
5888 data << float(vcos); // x direction
5889 data << float(vsin); // y direction
5890 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
5891 data << float(damage/-10); // Z Movement speed (vertical)
5893 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5896 void Spell::EffectSendTaxi(uint32 i)
5898 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5899 return;
5901 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5902 if(!entry)
5903 return;
5905 std::vector<uint32> nodes;
5907 nodes.resize(2);
5908 nodes[0] = entry->from;
5909 nodes[1] = entry->to;
5911 uint32 mountid = 0;
5912 switch(m_spellInfo->Id)
5914 case 31606: //Stormcrow Amulet
5915 mountid = 17447;
5916 break;
5917 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5918 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5919 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5920 mountid = 22840;
5921 break;
5922 case 34905: //Stealth Flight
5923 mountid = 6851;
5924 break;
5925 case 45883: //Amber Ledge to Beryl Point
5926 mountid = 23524;
5927 break;
5928 case 46064: //Amber Ledge to Coldarra
5929 mountid = 6371;
5930 break;
5931 case 53335: //Stormwind Harbor Flight - Peaceful
5932 mountid = 6852;
5933 break;
5936 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
5940 void Spell::EffectPlayerPull(uint32 i)
5942 if(!unitTarget || !m_caster)
5943 return;
5945 // Effect only works on players
5946 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5947 return;
5949 float vsin = sin(unitTarget->GetAngle(m_caster));
5950 float vcos = cos(unitTarget->GetAngle(m_caster));
5952 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5953 data.append(unitTarget->GetPackGUID());
5954 data << uint32(0); // Sequence
5955 data << float(vcos); // x direction
5956 data << float(vsin); // y direction
5957 // Horizontal speed
5958 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
5959 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
5961 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5964 void Spell::EffectDispelMechanic(uint32 i)
5966 if(!unitTarget)
5967 return;
5969 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
5971 Unit::AuraMap& Auras = unitTarget->GetAuras();
5972 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5974 next = iter;
5975 ++next;
5976 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
5977 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
5979 unitTarget->RemoveAurasDueToSpell(spell->Id);
5980 if(Auras.empty())
5981 break;
5982 else
5983 next = Auras.begin();
5986 return;
5989 void Spell::EffectSummonDeadPet(uint32 /*i*/)
5991 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5992 return;
5993 Player *_player = (Player*)m_caster;
5994 Pet *pet = _player->GetPet();
5995 if(!pet)
5996 return;
5997 if(pet->isAlive())
5998 return;
5999 if(damage < 0)
6000 return;
6001 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6002 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6003 pet->setDeathState( ALIVE );
6004 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6005 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6007 pet->AIM_Initialize();
6009 _player->PetSpellInitialize();
6010 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6013 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6015 float mana = 0;
6016 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6018 if(!m_caster->m_TotemSlot[slot])
6019 continue;
6021 Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
6022 if(totem && totem->isTotem())
6024 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6025 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6026 if(spellInfo)
6027 mana += spellInfo->manaCost * damage / 100;
6028 ((Totem*)totem)->UnSummon();
6032 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
6033 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
6036 void Spell::EffectDurabilityDamage(uint32 i)
6038 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6039 return;
6041 int32 slot = m_spellInfo->EffectMiscValue[i];
6043 // FIXME: some spells effects have value -1/-2
6044 // Possibly its mean -1 all player equipped items and -2 all items
6045 if(slot < 0)
6047 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
6048 return;
6051 // invalid slot value
6052 if(slot >= INVENTORY_SLOT_BAG_END)
6053 return;
6055 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6056 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
6059 void Spell::EffectDurabilityDamagePCT(uint32 i)
6061 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6062 return;
6064 int32 slot = m_spellInfo->EffectMiscValue[i];
6066 // FIXME: some spells effects have value -1/-2
6067 // Possibly its mean -1 all player equipped items and -2 all items
6068 if(slot < 0)
6070 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
6071 return;
6074 // invalid slot value
6075 if(slot >= INVENTORY_SLOT_BAG_END)
6076 return;
6078 if(damage <= 0)
6079 return;
6081 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6082 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
6085 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6087 if(!unitTarget)
6088 return;
6090 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6093 void Spell::EffectTransmitted(uint32 effIndex)
6095 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6097 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6099 if (!goinfo)
6101 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6102 return;
6105 float fx,fy,fz;
6107 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6109 fx = m_targets.m_destX;
6110 fy = m_targets.m_destY;
6111 fz = m_targets.m_destZ;
6113 //FIXME: this can be better check for most objects but still hack
6114 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6116 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6117 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6119 else
6121 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6122 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6123 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6125 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6128 Map *cMap = m_caster->GetMap();
6130 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6132 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6133 { // but this is not proper, we really need to ignore not materialized objects
6134 SendCastResult(SPELL_FAILED_NOT_HERE);
6135 SendChannelUpdate(0);
6136 return;
6139 // replace by water level in this case
6140 fz = cMap->GetWaterLevel(fx,fy);
6142 // if gameobject is summoning object, it should be spawned right on caster's position
6143 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6145 m_caster->GetPosition(fx,fy,fz);
6148 GameObject* pGameObj = new GameObject;
6150 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6151 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6153 delete pGameObj;
6154 return;
6157 int32 duration = GetSpellDuration(m_spellInfo);
6159 switch(goinfo->type)
6161 case GAMEOBJECT_TYPE_FISHINGNODE:
6163 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6164 // Orientation3
6165 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 );
6166 // Orientation4
6167 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 );
6168 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6170 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6171 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6172 int32 lastSec;
6173 switch(urand(0, 3))
6175 case 0: lastSec = 3; break;
6176 case 1: lastSec = 7; break;
6177 case 2: lastSec = 13; break;
6178 case 3: lastSec = 17; break;
6181 duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
6182 break;
6184 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6186 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6188 pGameObj->AddUniqueUse((Player*)m_caster);
6189 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6191 break;
6193 case GAMEOBJECT_TYPE_FISHINGHOLE:
6194 case GAMEOBJECT_TYPE_CHEST:
6195 default:
6197 break;
6201 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6203 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6205 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6206 pGameObj->SetSpellId(m_spellInfo->Id);
6208 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6209 //m_caster->AddGameObject(pGameObj);
6210 //m_ObjToDel.push_back(pGameObj);
6212 cMap->Add(pGameObj);
6214 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6215 data << uint64(pGameObj->GetGUID());
6216 m_caster->SendMessageToSet(&data,true);
6218 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6220 GameObject* linkedGO = new GameObject;
6221 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6222 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6224 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6225 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6226 linkedGO->SetSpellId(m_spellInfo->Id);
6227 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6229 linkedGO->GetMap()->Add(linkedGO);
6231 else
6233 delete linkedGO;
6234 linkedGO = NULL;
6235 return;
6240 void Spell::EffectProspecting(uint32 /*i*/)
6242 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6243 return;
6245 Player* p_caster = (Player*)m_caster;
6246 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6247 return;
6249 if(itemTarget->GetCount() < 5)
6250 return;
6252 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6254 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6255 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6256 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6259 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6262 void Spell::EffectMilling(uint32 /*i*/)
6264 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6265 return;
6267 Player* p_caster = (Player*)m_caster;
6268 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6269 return;
6271 if(itemTarget->GetCount() < 5)
6272 return;
6274 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6276 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6277 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6278 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6281 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6284 void Spell::EffectSkill(uint32 /*i*/)
6286 sLog.outDebug("WORLD: SkillEFFECT");
6289 void Spell::EffectSummonDemon(uint32 i)
6291 float px = m_targets.m_destX;
6292 float py = m_targets.m_destY;
6293 float pz = m_targets.m_destZ;
6295 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6296 if (!Charmed)
6297 return;
6299 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6300 Charmed->SetLevel(m_caster->getLevel());
6302 // TODO: Add damage/mana/hp according to level
6304 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6306 // Enslave demon effect, without mana cost and cooldown
6307 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6309 // Inferno effect
6310 Charmed->CastSpell(Charmed, 22703, true, 0);
6314 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6315 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6316 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6317 This is why we use a half sec delay between the visual effect and the resurrection itself */
6318 void Spell::EffectSpiritHeal(uint32 /*i*/)
6321 if(!unitTarget || unitTarget->isAlive())
6322 return;
6323 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6324 return;
6325 if(!unitTarget->IsInWorld())
6326 return;
6328 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6329 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6330 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6331 ((Player*)unitTarget)->SpawnCorpseBones();
6335 // remove insignia spell effect
6336 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6338 sLog.outDebug("Effect: SkinPlayerCorpse");
6339 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6340 return;
6342 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6345 void Spell::EffectStealBeneficialBuff(uint32 i)
6347 sLog.outDebug("Effect: StealBeneficialBuff");
6349 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6350 return;
6352 std::vector <Aura *> steal_list;
6353 // Create dispel mask by dispel type
6354 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6355 Unit::AuraMap const& auras = unitTarget->GetAuras();
6356 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6358 Aura *aur = (*itr).second;
6359 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6361 // Need check for passive? this
6362 if (aur->IsPositive() && !aur->IsPassive())
6363 steal_list.push_back(aur);
6366 // Ok if exist some buffs for dispel try dispel it
6367 if (!steal_list.empty())
6369 std::list < std::pair<uint32,uint64> > success_list;
6370 int32 list_size = steal_list.size();
6371 // Dispell N = damage buffs (or while exist buffs for dispel)
6372 for (int32 count=0; count < damage && list_size > 0; ++count)
6374 // Random select buff for dispel
6375 Aura *aur = steal_list[urand(0, list_size-1)];
6376 // Not use chance for steal
6377 // TODO possible need do it
6378 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6380 // Remove buff from list for prevent doubles
6381 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6383 Aura *stealed = *j;
6384 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6386 j = steal_list.erase(j);
6387 --list_size;
6389 else
6390 ++j;
6393 // Really try steal and send log
6394 if (!success_list.empty())
6396 int32 count = success_list.size();
6397 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6398 data.append(unitTarget->GetPackGUID()); // Victim GUID
6399 data.append(m_caster->GetPackGUID()); // Caster GUID
6400 data << uint32(m_spellInfo->Id); // Dispell spell id
6401 data << uint8(0); // not used
6402 data << uint32(count); // count
6403 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6405 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6406 data << uint32(spellInfo->Id); // Spell Id
6407 data << uint8(0); // 0 - steals !=0 transfers
6408 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6410 m_caster->SendMessageToSet(&data, true);
6415 void Spell::EffectKillCredit(uint32 i)
6417 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6418 return;
6420 ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6423 void Spell::EffectQuestFail(uint32 i)
6425 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6426 return;
6428 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6431 void Spell::EffectActivateRune(uint32 eff_idx)
6433 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6434 return;
6436 Player *plr = (Player*)m_caster;
6438 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6439 return;
6441 for(uint32 j = 0; j < MAX_RUNES; ++j)
6443 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6445 plr->SetRuneCooldown(j, 0);
6450 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6452 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6453 ((Player*)unitTarget)->SetCanTitanGrip(true);
6456 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6458 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6459 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6460 return;
6462 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);