[7602] Fixed possible crash at instant stealth aura apply interrupt at internal visib...
[AHbot.git] / src / game / SpellEffects.cpp
blob168cf442dcaf3b370dcfcde767cb211b030ceba5
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 "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL, //154 unused
215 &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.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
222 void Spell::EffectNULL(uint32 /*i*/)
224 sLog.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32 /*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i)
234 if(!unitTarget || unitTarget->isAlive())
235 return;
237 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
238 return;
240 if(!unitTarget->IsInWorld())
241 return;
243 Player* pTarget = ((Player*)unitTarget);
245 if(pTarget->isRessurectRequested()) // already have one active request
246 return;
248 uint32 health = damage;
249 uint32 mana = m_spellInfo->EffectMiscValue[i];
250 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
251 SendResurrectRequest(pTarget);
254 void Spell::EffectInstaKill(uint32 /*i*/)
256 if( !unitTarget || !unitTarget->isAlive() )
257 return;
259 // Demonic Sacrifice
260 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
262 uint32 entry = unitTarget->GetEntry();
263 uint32 spellID;
264 switch(entry)
266 case 416: spellID=18789; break; //imp
267 case 417: spellID=18792; break; //fellhunter
268 case 1860: spellID=18790; break; //void
269 case 1863: spellID=18791; break; //succubus
270 case 17252: spellID=35701; break; //fellguard
271 default:
272 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
273 return;
276 m_caster->CastSpell(m_caster,spellID,true);
279 if(m_caster==unitTarget) // prevent interrupt message
280 finish();
282 uint32 health = unitTarget->GetHealth();
283 m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i)
288 uint32 absorb = 0;
289 uint32 resist = 0;
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage = m_spellInfo->CalculateSimpleValue(i);
296 m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
298 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
299 if(m_caster->GetTypeId() == TYPEID_PLAYER)
300 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE,damage);
303 void Spell::EffectSchoolDMG(uint32 effect_idx)
305 if( unitTarget && unitTarget->isAlive())
307 switch(m_spellInfo->SpellFamilyName)
309 case SPELLFAMILY_GENERIC:
311 //Gore
312 if(m_spellInfo->SpellIconID == 2269 )
314 damage+= rand()%2 ? damage : 0;
317 switch(m_spellInfo->Id) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
329 uint32 count = 0;
330 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
331 if(ihit->effectMask & (1<<effect_idx))
332 ++count;
334 damage /= count; // divide to all targets
335 break;
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage = unitTarget->GetHealth() / 2;
341 if(damage < 200)
342 damage = 200;
343 break;
345 // Intercept (warrior spell trigger)
346 case 20253:
347 case 61491:
349 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
350 break;
353 break;
356 case SPELLFAMILY_MAGE:
358 // Arcane Blast
359 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
361 m_caster->CastSpell(m_caster,36032,true);
363 break;
365 case SPELLFAMILY_WARRIOR:
367 // Bloodthirst
368 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
370 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
372 // Shield Slam
373 else if(m_spellInfo->SpellFamilyFlags & 0x0000020000000000LL)
374 damage += int32(m_caster->GetShieldBlockValue());
375 // Victory Rush
376 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
378 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
379 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
381 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
382 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL)
383 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
384 // Heroic Throw ${$m1+$AP*.50}
385 else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL)
386 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
387 // Shockwave ${$m3/100*$AP}
388 else if(m_spellInfo->SpellFamilyFlags & 0x0000800000000000LL)
390 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
391 if (pct > 0)
392 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
393 break;
395 break;
397 case SPELLFAMILY_WARLOCK:
399 // Incinerate Rank 1 & 2
400 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
402 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
403 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
404 damage += int32(damage*0.25f);
406 break;
408 case SPELLFAMILY_PRIEST:
410 // Shadow Word: Death - deals damage equal to damage done to caster
411 if (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
412 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
413 break;
415 case SPELLFAMILY_DRUID:
417 // Ferocious Bite
418 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
420 // converts each extra point of energy into ($f1+$AP/410) additional damage
421 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
422 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
423 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
424 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
425 m_caster->SetPower(POWER_ENERGY,0);
427 // Rake
428 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
430 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
432 // Swipe
433 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
435 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
437 //Mangle Bonus for the initial damage of Lacerate and Rake
438 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
439 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
441 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
442 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
443 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
445 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
446 break;
449 break;
451 case SPELLFAMILY_ROGUE:
453 // Envenom
454 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
456 // consume from stack dozes not more that have combo-points
457 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
459 Aura *poison = 0;
460 // Lookup for Deadly poison (only attacker applied)
461 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
462 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
463 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
464 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
465 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
467 poison = *itr;
468 break;
470 // count consumed deadly poison doses at target
471 if (poison)
473 uint32 spellId = poison->GetId();
474 uint32 doses = poison->GetStackAmount();
475 if (doses > combo)
476 doses = combo;
477 for (int i=0; i< doses; i++)
478 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
479 damage *= doses;
480 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
482 // Eviscerate and Envenom Bonus Damage (item set effect)
483 if(m_caster->GetDummyAura(37169))
484 damage += ((Player*)m_caster)->GetComboPoints()*40;
487 // Eviscerate
488 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
490 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
492 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
493 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
495 // Eviscerate and Envenom Bonus Damage (item set effect)
496 if(m_caster->GetDummyAura(37169))
497 damage += combo*40;
500 // Gouge
501 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL)
503 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
505 // Instant Poison
506 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
508 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
510 // Wound Poison
511 else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL)
513 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
515 break;
517 case SPELLFAMILY_HUNTER:
519 // Mongoose Bite
520 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
522 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
524 // Counterattack
525 else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL)
527 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
529 // Arcane Shot
530 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
532 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
534 // Steady Shot
535 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
537 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
538 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
540 // Explosive Trap Effect
541 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
543 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
545 break;
547 case SPELLFAMILY_PALADIN:
549 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
550 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
552 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
553 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
554 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
555 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
556 // Get stack of Holy Vengeance on the target added by caster
557 uint32 stacks = 0;
558 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
559 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
560 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
562 stacks = (*itr)->GetStackAmount();
563 break;
565 // + 10% for each application of Holy Vengeance on the target
566 if(stacks)
567 damage += damage * stacks * 10 /100;
569 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
570 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
572 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
573 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
574 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
575 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
577 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
578 else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL)
580 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
581 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
582 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
583 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
585 // Hammer of the Righteous
586 else if(m_spellInfo->SpellFamilyFlags&0x0004000000000000LL)
588 // Add main hand dps * effect[2] amount
589 float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
590 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
591 damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
593 // Shield of Righteousness
594 else if(m_spellInfo->SpellFamilyFlags&0x0010000000000000LL)
596 damage+=int32(m_caster->GetShieldBlockValue());
598 break;
602 if(damage >= 0)
603 m_damage+= damage;
607 void Spell::EffectDummy(uint32 i)
609 if(!unitTarget && !gameObjTarget && !itemTarget)
610 return;
612 // selection by spell family
613 switch(m_spellInfo->SpellFamilyName)
615 case SPELLFAMILY_GENERIC:
617 switch(m_spellInfo->Id )
619 case 8063: // Deviate Fish
621 if(m_caster->GetTypeId() != TYPEID_PLAYER)
622 return;
624 uint32 spell_id = 0;
625 switch(urand(1,5))
627 case 1: spell_id = 8064; break; // Sleepy
628 case 2: spell_id = 8065; break; // Invigorate
629 case 3: spell_id = 8066; break; // Shrink
630 case 4: spell_id = 8067; break; // Party Time!
631 case 5: spell_id = 8068; break; // Healthy Spirit
633 m_caster->CastSpell(m_caster,spell_id,true,NULL);
634 return;
636 case 8213: // Savory Deviate Delight
638 if(m_caster->GetTypeId() != TYPEID_PLAYER)
639 return;
641 uint32 spell_id = 0;
642 switch(urand(1,2))
644 // Flip Out - ninja
645 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
646 // Yaaarrrr - pirate
647 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
649 m_caster->CastSpell(m_caster,spell_id,true,NULL);
650 return;
652 case 8593: // Symbol of life (restore creature to life)
653 case 31225: // Shimmering Vessel (restore creature to life)
655 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
656 return;
657 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
658 return;
660 case 12162: // Deep wounds
661 case 12850: // (now good common check for this spells)
662 case 12868:
664 if(!unitTarget)
665 return;
667 float damage;
668 // DW should benefit of attack power, damage percent mods etc.
669 // TODO: check if using offhand damage is correct and if it should be divided by 2
670 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
671 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
672 else
673 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
675 switch (m_spellInfo->Id)
677 case 12850: damage *= 0.2f; break;
678 case 12162: damage *= 0.4f; break;
679 case 12868: damage *= 0.6f; break;
680 default:
681 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
682 return;
685 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
686 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
687 return;
689 case 13120: // net-o-matic
691 if(!unitTarget)
692 return;
694 uint32 spell_id = 0;
696 uint32 roll = urand(0, 99);
698 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
699 spell_id = 16566;
700 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
701 spell_id = 13119;
702 else // normal root
703 spell_id = 13099;
705 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
706 return;
708 case 13567: // Dummy Trigger
710 // can be used for different aura triggering, so select by aura
711 if(!m_triggeredByAuraSpell || !unitTarget)
712 return;
714 switch(m_triggeredByAuraSpell->Id)
716 case 26467: // Persistent Shield
717 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
718 break;
719 default:
720 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
721 break;
723 return;
725 case 15998: // Capture Worg Pup
726 case 29435: // Capture Female Kaliri Hatchling
728 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
729 return;
731 Creature* creatureTarget = (Creature*)unitTarget;
732 creatureTarget->setDeathState(JUST_DIED);
733 creatureTarget->RemoveCorpse();
734 creatureTarget->SetHealth(0); // just for nice GM-mode view
735 return;
737 case 16589: // Noggenfogger Elixir
739 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
740 return;
742 uint32 spell_id = 0;
743 switch(urand(1,3))
745 case 1: spell_id = 16595; break;
746 case 2: spell_id = 16593; break;
747 default:spell_id = 16591; break;
750 m_caster->CastSpell(m_caster,spell_id,true,NULL);
751 return;
753 case 17251: // Spirit Healer Res
755 if(!unitTarget || !m_originalCaster)
756 return;
758 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
760 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
761 data << unitTarget->GetGUID();
762 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
764 return;
766 case 17271: // Test Fetid Skull
768 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
769 return;
771 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
773 m_caster->CastSpell(m_caster,spell_id,true,NULL);
774 return;
776 case 20577: // Cannibalize
777 if (unitTarget)
778 m_caster->CastSpell(m_caster,20578,false,NULL);
779 return;
780 case 23019: // Crystal Prison Dummy DND
782 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
783 return;
785 Creature* creatureTarget = (Creature*)unitTarget;
786 if(creatureTarget->isPet())
787 return;
789 GameObject* pGameObj = new GameObject;
791 Map *map = creatureTarget->GetMap();
793 // create before death for get proper coordinates
794 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
795 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
796 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1) )
798 delete pGameObj;
799 return;
802 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
803 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
804 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
805 pGameObj->SetSpellId(m_spellInfo->Id);
807 creatureTarget->setDeathState(JUST_DIED);
808 creatureTarget->RemoveCorpse();
809 creatureTarget->SetHealth(0); // just for nice GM-mode view
811 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
812 map->Add(pGameObj);
814 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
815 data << uint64(pGameObj->GetGUID());
816 m_caster->SendMessageToSet(&data,true);
818 return;
820 case 23074: // Arcanite Dragonling
821 if (!m_CastItem) return;
822 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
823 return;
824 case 23075: // Mithril Mechanical Dragonling
825 if (!m_CastItem) return;
826 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
827 return;
828 case 23076: // Mechanical Dragonling
829 if (!m_CastItem) return;
830 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
831 return;
832 case 23133: // Gnomish Battle Chicken
833 if (!m_CastItem) return;
834 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
835 return;
836 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
838 int32 r = irand(0, 119);
839 if ( r < 20 ) // 1/6 polymorph
840 m_caster->CastSpell(m_caster,23444,true);
841 else if ( r < 100 ) // 4/6 evil twin
842 m_caster->CastSpell(m_caster,23445,true);
843 else // 1/6 miss the target
844 m_caster->CastSpell(m_caster,36902,true);
845 return;
847 case 23453: // Ultrasafe Transporter: Gadgetzan
848 if ( roll_chance_i(50) ) // success
849 m_caster->CastSpell(m_caster,23441,true);
850 else // failure
851 m_caster->CastSpell(m_caster,23446,true);
852 return;
853 case 23645: // Hourglass Sand
854 m_caster->RemoveAurasDueToSpell(23170);
855 return;
856 case 23725: // Gift of Life (warrior bwl trinket)
857 m_caster->CastSpell(m_caster,23782,true);
858 m_caster->CastSpell(m_caster,23783,true);
859 return;
860 case 25860: // Reindeer Transformation
862 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
863 return;
865 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
866 float speed = m_caster->GetSpeedRate(MOVE_RUN);
868 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
870 //5 different spells used depending on mounted speed and if mount can fly or not
871 if (flyspeed >= 4.1f)
872 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
873 else if (flyspeed >= 3.8f)
874 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
875 else if (flyspeed >= 1.6f)
876 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
877 else if (speed >= 2.0f)
878 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
879 else
880 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
882 return;
884 //case 26074: // Holiday Cheer
885 // return; -- implemented at client side
886 case 28006: // Arcane Cloaking
888 if( unitTarget->GetTypeId() == TYPEID_PLAYER )
889 m_caster->CastSpell(unitTarget,29294,true);
890 return;
892 case 28730: // Arcane Torrent (Mana)
894 Aura * dummy = m_caster->GetDummyAura(28734);
895 if (dummy)
897 int32 bp = damage * dummy->GetStackAmount();
898 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
899 m_caster->RemoveAurasDueToSpell(28734);
901 return;
903 case 29200: // Purify Helboar Meat
905 if( m_caster->GetTypeId() != TYPEID_PLAYER )
906 return;
908 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
910 m_caster->CastSpell(m_caster,spell_id,true,NULL);
911 return;
913 case 29858: // Soulshatter
914 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
915 m_caster->CastSpell(unitTarget,32835,true);
916 return;
917 case 30458: // Nigh Invulnerability
918 if (!m_CastItem) return;
919 if(roll_chance_i(86)) // success
920 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
921 else // backfire in 14% casts
922 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
923 return;
924 case 30507: // Poultryizer
925 if (!m_CastItem) return;
926 if(roll_chance_i(80)) // success
927 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
928 else // backfire 20%
929 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
930 return;
931 case 33060: // Make a Wish
933 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
934 return;
936 uint32 spell_id = 0;
938 switch(urand(1,5))
940 case 1: spell_id = 33053; break;
941 case 2: spell_id = 33057; break;
942 case 3: spell_id = 33059; break;
943 case 4: spell_id = 33062; break;
944 case 5: spell_id = 33064; break;
947 m_caster->CastSpell(m_caster,spell_id,true,NULL);
948 return;
950 case 35745:
952 uint32 spell_id;
953 switch(m_caster->GetAreaId())
955 case 3900: spell_id = 35743; break;
956 case 3742: spell_id = 35744; break;
957 default: return;
960 m_caster->CastSpell(m_caster,spell_id,true);
961 return;
963 case 37674: // Chaos Blast
965 if(!unitTarget)
966 return;
968 int32 basepoints0 = 100;
969 m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true);
970 return;
972 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
974 // selecting one from Bloodstained Fortune item
975 uint32 newitemid;
976 switch(urand(1,20))
978 case 1: newitemid = 32688; break;
979 case 2: newitemid = 32689; break;
980 case 3: newitemid = 32690; break;
981 case 4: newitemid = 32691; break;
982 case 5: newitemid = 32692; break;
983 case 6: newitemid = 32693; break;
984 case 7: newitemid = 32700; break;
985 case 8: newitemid = 32701; break;
986 case 9: newitemid = 32702; break;
987 case 10: newitemid = 32703; break;
988 case 11: newitemid = 32704; break;
989 case 12: newitemid = 32705; break;
990 case 13: newitemid = 32706; break;
991 case 14: newitemid = 32707; break;
992 case 15: newitemid = 32708; break;
993 case 16: newitemid = 32709; break;
994 case 17: newitemid = 32710; break;
995 case 18: newitemid = 32711; break;
996 case 19: newitemid = 32712; break;
997 case 20: newitemid = 32713; break;
998 default:
999 return;
1002 DoCreateItem(i,newitemid);
1003 return;
1005 // Demon Broiled Surprise
1006 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1007 case 43723:
1009 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1010 return;
1012 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1013 return;
1016 case 44875: // Complete Raptor Capture
1018 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1019 return;
1021 Creature* creatureTarget = (Creature*)unitTarget;
1023 creatureTarget->setDeathState(JUST_DIED);
1024 creatureTarget->RemoveCorpse();
1025 creatureTarget->SetHealth(0); // just for nice GM-mode view
1027 //cast spell Raptor Capture Credit
1028 m_caster->CastSpell(m_caster,42337,true,NULL);
1029 return;
1031 case 34665: //Administer Antidote
1033 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1034 return;
1036 if(!unitTarget)
1037 return;
1039 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1040 if(!tempSummon)
1041 return;
1043 uint32 health = tempSummon->GetHealth();
1045 float x = tempSummon->GetPositionX();
1046 float y = tempSummon->GetPositionY();
1047 float z = tempSummon->GetPositionZ();
1048 float o = tempSummon->GetOrientation();
1049 tempSummon->UnSummon();
1051 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1052 if (!pCreature)
1053 return;
1055 pCreature->SetHealth(health);
1056 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992,pCreature);
1058 if (pCreature->AI())
1059 pCreature->AI()->AttackStart(m_caster);
1061 return;
1063 case 44997: // Converting Sentry
1065 //Converted Sentry Credit
1066 m_caster->CastSpell(m_caster, 45009, true);
1067 return;
1069 case 45030: // Impale Emissary
1071 // Emissary of Hate Credit
1072 m_caster->CastSpell(m_caster, 45088, true);
1073 return;
1075 case 50243: // Teach Language
1077 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1078 return;
1080 // spell has a 1/3 chance to trigger one of the below
1081 if(roll_chance_i(66))
1082 return;
1083 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1085 // 1000001 - gnomish binary
1086 m_caster->CastSpell(m_caster, 50242, true);
1088 else
1090 // 01001000 - goblin binary
1091 m_caster->CastSpell(m_caster, 50246, true);
1094 return;
1096 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1098 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1099 return;
1101 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1102 bg->EventPlayerDroppedFlag((Player*)m_caster);
1104 m_caster->CastSpell(m_caster, 30452, true, NULL);
1105 return;
1107 case 52308:
1109 switch(i)
1111 case 0:
1113 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
1114 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1);
1116 if (m_caster->HasAura(reqAuraID,0))
1117 m_caster->CastSpell(m_caster,spellID,true,NULL);
1118 return;
1120 case 1:
1121 return; // additional data for dummy[0]
1123 return;
1125 case 53341:
1126 case 53343:
1128 m_caster->CastSpell(m_caster,54586,true);
1129 return;
1131 case 58418: // Portal to Orgrimmar
1132 case 58420: // Portal to Stormwind
1133 return; // implemented in EffectScript[0]
1136 //All IconID Check in there
1137 switch(m_spellInfo->SpellIconID)
1139 // Berserking (troll racial traits)
1140 case 1661:
1142 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1143 int32 melee_mod = 10;
1144 if (healthPerc <= 40)
1145 melee_mod = 30;
1146 if (healthPerc < 100 && healthPerc > 40)
1147 melee_mod = 10+(100-healthPerc)/3;
1149 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1150 int32 hasteModBasePoints1 = (5-melee_mod);
1151 int32 hasteModBasePoints2 = 5;
1153 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1154 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1155 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1156 return;
1159 break;
1161 case SPELLFAMILY_MAGE:
1162 switch(m_spellInfo->Id )
1164 case 11958: // Cold Snap
1166 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1167 return;
1169 // immediately finishes the cooldown on Frost spells
1170 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1171 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1173 if (itr->second->state == PLAYERSPELL_REMOVED)
1174 continue;
1176 uint32 classspell = itr->first;
1177 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1179 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1180 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1181 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1183 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1185 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1186 data << uint32(classspell);
1187 data << uint64(m_caster->GetGUID());
1188 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1191 return;
1193 case 32826:
1195 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1197 //Polymorph Cast Visual Rank 1
1198 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1199 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1201 return;
1204 break;
1205 case SPELLFAMILY_WARRIOR:
1206 // Charge
1207 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1209 int32 chargeBasePoints0 = damage;
1210 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1211 return;
1213 // Execute
1214 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1216 if(!unitTarget)
1217 return;
1219 uint32 rage = m_caster->GetPower(POWER_RAGE);
1220 // Glyph of Execution bonus
1221 if (Aura *aura = m_caster->GetDummyAura(58367))
1222 rage+=aura->GetModifier()->m_amount;
1224 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1225 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1226 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1227 m_caster->SetPower(POWER_RAGE,0);
1228 return;
1230 // Slam
1231 if(m_spellInfo->SpellFamilyFlags & 0x0000000000200000LL)
1233 if(!unitTarget)
1234 return;
1235 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1236 m_damage+=damage;
1237 return;
1239 switch(m_spellInfo->Id)
1241 // Warrior's Wrath
1242 case 21977:
1244 if(!unitTarget)
1245 return;
1246 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1247 return;
1249 // Last Stand
1250 case 12975:
1252 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1253 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1254 return;
1256 // Bloodthirst
1257 case 23881:
1259 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1260 return;
1263 break;
1264 case SPELLFAMILY_WARLOCK:
1265 // Life Tap
1266 if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL)
1268 // In 303 exist spirit depend
1269 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1270 switch (m_spellInfo->Id)
1272 case 1454: damage+=spirit; break;
1273 case 1455: damage+=spirit*15/10; break;
1274 case 1456: damage+=spirit*2; break;
1275 case 11687: damage+=spirit*25/10; break;
1276 case 11688:
1277 case 11689:
1278 case 27222:
1279 case 57946: damage+=spirit*3; break;
1280 default:
1281 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1282 return;
1284 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1285 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1286 if(int32(unitTarget->GetHealth()) > damage)
1288 // Shouldn't Appear in Combat Log
1289 unitTarget->ModifyHealth(-damage);
1291 int32 mana = damage;
1292 // Improved Life Tap mod
1293 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1294 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1296 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1297 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1299 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1301 // Mana Feed
1302 int32 manaFeedVal = 0;
1303 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1304 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1306 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1307 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1309 if(manaFeedVal > 0)
1311 manaFeedVal = manaFeedVal * mana / 100;
1312 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1315 else
1316 SendCastResult(SPELL_FAILED_FIZZLE);
1317 return;
1319 break;
1320 case SPELLFAMILY_PRIEST:
1321 // Penance
1322 if (m_spellInfo->SpellFamilyFlags & 0x0080000000000000LL)
1324 if (!unitTarget)
1325 return;
1327 int hurt = 0;
1328 int heal = 0;
1329 switch(m_spellInfo->Id)
1331 case 47540: hurt = 47758; heal = 47757; break;
1332 case 53005: hurt = 53001; heal = 52986; break;
1333 case 53006: hurt = 53002; heal = 52987; break;
1334 case 53007: hurt = 53003; heal = 52988; break;
1335 default:
1336 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1337 return;
1339 if (m_caster->IsFriendlyTo(unitTarget))
1340 m_caster->CastSpell(unitTarget, heal, true, 0);
1341 else
1342 m_caster->CastSpell(unitTarget, hurt, true, 0);
1343 return;
1345 break;
1346 case SPELLFAMILY_DRUID:
1347 // Starfall
1348 if (m_spellInfo->SpellFamilyFlags2 & 0x00000100LL)
1350 //Shapeshifting into an animal form or mounting cancels the effect.
1351 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1353 if(m_triggeredByAuraSpell)
1354 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1355 return;
1358 //Any effect which causes you to lose control of your character will supress the starfall effect.
1359 if(m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
1360 return;
1362 switch(m_spellInfo->Id)
1364 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1365 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1366 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1367 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1368 default:
1369 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1370 return;
1373 break;
1374 case SPELLFAMILY_ROGUE:
1375 switch(m_spellInfo->Id )
1377 case 5938: // Shiv
1379 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1380 return;
1382 Player *pCaster = ((Player*)m_caster);
1384 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1385 if(!item)
1386 return;
1388 // all poison enchantments is temporary
1389 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1390 if(!enchant_id)
1391 return;
1393 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1394 if(!pEnchant)
1395 return;
1397 for (int s=0;s<3;s++)
1399 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1400 continue;
1402 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1403 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1404 continue;
1406 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1409 m_caster->CastSpell(unitTarget, 5940, true);
1410 return;
1412 case 14185: // Preparation Rogue
1414 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1415 return;
1417 //immediately finishes the cooldown on certain Rogue abilities
1418 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1419 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1421 uint32 classspell = itr->first;
1422 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1424 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL))
1426 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1428 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1429 data << uint32(classspell);
1430 data << uint64(m_caster->GetGUID());
1431 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1434 return;
1436 case 31231: // Cheat Death
1438 m_caster->CastSpell(m_caster,45182,true);
1439 return;
1442 break;
1443 case SPELLFAMILY_HUNTER:
1444 // Steady Shot
1445 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1447 if( !unitTarget || !unitTarget->isAlive())
1448 return;
1450 bool found = false;
1452 // check dazed affect
1453 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1454 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1456 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1458 found = true;
1459 break;
1463 if(found)
1464 m_damage+= damage;
1465 return;
1468 switch(m_spellInfo->Id)
1470 case 23989: //Readiness talent
1472 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1473 return;
1475 //immediately finishes the cooldown for hunter abilities
1476 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1477 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1479 uint32 classspell = itr->first;
1480 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1482 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1484 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1486 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1487 data << uint32(classspell);
1488 data << uint64(m_caster->GetGUID());
1489 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1492 return;
1494 case 37506: // Scatter Shot
1496 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1497 return;
1499 // break Auto Shot and autohit
1500 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1501 m_caster->AttackStop();
1502 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1503 return;
1506 break;
1507 case SPELLFAMILY_PALADIN:
1508 switch(m_spellInfo->SpellIconID)
1510 case 156: // Holy Shock
1512 if(!unitTarget)
1513 return;
1515 int hurt = 0;
1516 int heal = 0;
1518 switch(m_spellInfo->Id)
1520 case 20473: hurt = 25912; heal = 25914; break;
1521 case 20929: hurt = 25911; heal = 25913; break;
1522 case 20930: hurt = 25902; heal = 25903; break;
1523 case 27174: hurt = 27176; heal = 27175; break;
1524 case 33072: hurt = 33073; heal = 33074; break;
1525 case 48824: hurt = 48822; heal = 48820; break;
1526 case 48825: hurt = 48823; heal = 48821; break;
1527 default:
1528 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1529 return;
1532 if(m_caster->IsFriendlyTo(unitTarget))
1533 m_caster->CastSpell(unitTarget, heal, true, 0);
1534 else
1535 m_caster->CastSpell(unitTarget, hurt, true, 0);
1537 return;
1539 case 561: // Judgement of command
1541 if(!unitTarget)
1542 return;
1544 uint32 spell_id = m_currentBasePoints[i]+1;
1545 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1546 if(!spell_proto)
1547 return;
1549 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1551 // decreased damage (/2) for non-stunned target.
1552 SpellModifier *mod = new SpellModifier;
1553 mod->op = SPELLMOD_DAMAGE;
1554 mod->value = -50;
1555 mod->type = SPELLMOD_PCT;
1556 mod->spellId = m_spellInfo->Id;
1557 mod->mask = 0x0000020000000000LL;
1558 mod->mask2= 0LL;
1560 ((Player*)m_caster)->AddSpellMod(mod, true);
1561 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1562 // mod deleted
1563 ((Player*)m_caster)->AddSpellMod(mod, false);
1565 else
1566 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1568 return;
1572 switch(m_spellInfo->Id)
1574 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1575 case 20187:
1577 if (!unitTarget)
1578 return;
1579 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1580 return;
1582 case 31789: // Righteous Defense (step 1)
1584 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1586 // non-standard cast requirement check
1587 if (!unitTarget || unitTarget->getAttackers().empty())
1589 // clear cooldown at fail
1590 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1592 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1594 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1595 data << uint32(m_spellInfo->Id);
1596 data << uint64(m_caster->GetGUID());
1597 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1600 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1601 return;
1604 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1605 // Clear targets for eff 1
1606 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1607 ihit->effectMask &= ~(1<<1);
1609 // not empty (checked)
1610 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1612 // chance to be selected from list
1613 float chance = 100.0f/attackers.size();
1614 uint32 count=0;
1615 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1617 if(!roll_chance_f(chance))
1618 continue;
1619 ++count;
1620 AddUnitTarget((*aItr), 1);
1623 // now let next effect cast spell at each target.
1624 return;
1626 case 37877: // Blessing of Faith
1628 if(!unitTarget)
1629 return;
1631 uint32 spell_id = 0;
1632 switch(unitTarget->getClass())
1634 case CLASS_DRUID: spell_id = 37878; break;
1635 case CLASS_PALADIN: spell_id = 37879; break;
1636 case CLASS_PRIEST: spell_id = 37880; break;
1637 case CLASS_SHAMAN: spell_id = 37881; break;
1638 default: return; // ignore for not healing classes
1641 m_caster->CastSpell(m_caster,spell_id,true);
1642 return;
1645 break;
1646 case SPELLFAMILY_SHAMAN:
1647 //Shaman Rockbiter Weapon
1648 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1650 // TODO: use expect spell for enchant (if exist talent)
1651 // In 3.0.3 no mods present for rockbiter
1652 uint32 spell_id = 0;
1653 switch(m_spellInfo->Id)
1655 case 8017: spell_id = 36494; break; // Rank 1
1656 case 8018: spell_id = 36750; break; // Rank 2
1657 case 8019: spell_id = 36755; break; // Rank 3
1658 case 10399: spell_id = 36759; break; // Rank 4
1659 default:
1660 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1661 return;
1664 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1666 if(!spellInfo)
1668 sLog.outError("WORLD: unknown spell id %i", spell_id);
1669 return;
1672 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1673 return;
1675 for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1677 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1679 if(item->IsFitToSpellRequirements(m_spellInfo))
1681 Spell *spell = new Spell(m_caster, spellInfo, true);
1683 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1684 // at calculation applied affect from Elemental Weapons talent
1685 // real enchantment damage-1
1686 spell->m_currentBasePoints[1] = damage-1;
1688 SpellCastTargets targets;
1689 targets.setItemTarget( item );
1690 spell->prepare(&targets);
1694 return;
1696 // Healing Stream Totem
1697 if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
1699 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1700 return;
1702 // Mana Spring Totem
1703 if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
1705 if(unitTarget->getPowerType()!=POWER_MANA)
1706 return;
1707 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1708 return;
1710 if(m_spellInfo->Id == 39610) // Mana Tide Totem effect
1712 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1713 return;
1714 // Glyph of Mana Tide
1715 Unit *owner = m_caster->GetOwner();
1716 if (owner)
1717 if (Aura *dummy = owner->GetDummyAura(55441))
1718 damage+=dummy->GetModifier()->m_amount;
1719 // Regenerate 6% of Total Mana Every 3 secs
1720 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1721 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1722 return;
1724 // Lava Lash
1725 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1727 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1728 return;
1729 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1730 if (item)
1732 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1733 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1734 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1736 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1737 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000200000LL &&
1738 (*itr)->GetCastItemGUID() == item->GetGUID())
1740 m_damage += m_damage * damage / 100;
1741 return;
1745 return;
1747 break;
1748 case SPELLFAMILY_DEATHKNIGHT:
1749 // Death Coil
1750 if(m_spellInfo->SpellFamilyFlags & 0x002000LL)
1752 if(m_caster->IsFriendlyTo(unitTarget))
1754 if(unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
1755 return;
1757 int32 bp = damage * 1.5f;
1758 m_caster->CastCustomSpell(unitTarget,47633,&bp,NULL,NULL,true);
1760 else
1762 int32 bp = damage;
1763 m_caster->CastCustomSpell(unitTarget,47632,&bp,NULL,NULL,true);
1765 return;
1767 break;
1770 // pet auras
1771 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1773 m_caster->AddPetAura(petSpell);
1774 return;
1777 // Script based implementation. Must be used only for not good for implementation in core spell effects
1778 // So called only for not proccessed cases
1779 if(gameObjTarget)
1780 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
1781 else if(unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
1782 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
1783 else if(itemTarget)
1784 Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
1787 void Spell::EffectTriggerSpellWithValue(uint32 i)
1789 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1791 // normal case
1792 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1794 if(!spellInfo)
1796 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1797 return;
1800 int32 bp = damage;
1801 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1804 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1806 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1807 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1809 if(!spellInfo)
1811 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1812 return;
1815 finish();
1816 Spell *spell = new Spell(m_caster, spellInfo, true);
1818 SpellCastTargets targets;
1819 targets.setUnitTarget( unitTarget);
1820 spell->prepare(&targets);
1822 m_caster->SetCurrentCastedSpell(spell);
1823 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1827 void Spell::EffectForceCast(uint32 i)
1829 if( !unitTarget )
1830 return;
1832 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1834 // normal case
1835 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1837 if(!spellInfo)
1839 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1840 return;
1843 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1846 void Spell::EffectTriggerSpell(uint32 i)
1848 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1850 // special cases
1851 switch(triggered_spell_id)
1853 // Vanish
1854 case 18461:
1856 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1857 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1858 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1860 // if this spell is given to NPC it must handle rest by it's own AI
1861 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1862 return;
1864 // get highest rank of the Stealth spell
1865 uint32 spellId = 0;
1866 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1867 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1869 // only highest rank is shown in spell book, so simply check if shown in spell book
1870 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1871 continue;
1873 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1874 if (!spellInfo)
1875 continue;
1877 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1879 spellId = spellInfo->Id;
1880 break;
1884 // no Stealth spell found
1885 if (!spellId)
1886 return;
1888 // reset cooldown on it if needed
1889 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1890 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1892 m_caster->CastSpell(m_caster, spellId, true);
1893 return;
1895 // just skip
1896 case 23770: // Sayge's Dark Fortune of *
1897 // not exist, common cooldown can be implemented in scripts if need.
1898 return;
1899 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1900 case 29284:
1902 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1903 if (!spell)
1904 return;
1906 for (int i=0; i < spell->StackAmount; ++i)
1907 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1908 return;
1910 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1911 case 29286:
1913 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1914 if (!spell)
1915 return;
1917 for (int i=0; i < spell->StackAmount; ++i)
1918 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1919 return;
1921 // Righteous Defense
1922 case 31980:
1924 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1925 return;
1927 // Cloak of Shadows
1928 case 35729 :
1930 Unit::AuraMap& Auras = m_caster->GetAuras();
1931 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1933 // remove all harmful spells on you...
1934 if( // ignore positive and passive auras
1935 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1936 // ignore physical auras
1937 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
1939 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1940 iter = Auras.begin();
1943 return;
1945 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1946 case 41967:
1948 if (Unit *pet = m_caster->GetPet())
1949 pet->CastSpell(pet, 28305, true);
1950 return;
1954 // normal case
1955 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1957 if(!spellInfo)
1959 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1960 return;
1963 // some triggered spells require specific equipment
1964 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1966 // main hand weapon required
1967 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1969 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1971 // skip spell if no weapon in slot or broken
1972 if(!item || item->IsBroken() )
1973 return;
1975 // skip spell if weapon not fit to triggered spell
1976 if(!item->IsFitToSpellRequirements(spellInfo))
1977 return;
1980 // offhand hand weapon required
1981 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1983 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1985 // skip spell if no weapon in slot or broken
1986 if(!item || item->IsBroken() )
1987 return;
1989 // skip spell if weapon not fit to triggered spell
1990 if(!item->IsFitToSpellRequirements(spellInfo))
1991 return;
1995 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1996 bool instant = false;
1997 for(uint32 j = i+1; j < 3; ++j)
1999 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
2001 instant = true;
2002 break;
2006 if(instant)
2008 if (unitTarget)
2009 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
2011 else
2012 m_TriggerSpells.push_back(spellInfo);
2015 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2017 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2019 // normal case
2020 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2022 if(!spellInfo)
2024 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2025 m_spellInfo->Id,effect_idx,triggered_spell_id);
2026 return;
2029 if (m_CastItem)
2030 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2032 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2035 void Spell::EffectJump(uint32 i)
2037 if(m_caster->isInFlight())
2038 return;
2040 // Init dest coordinates
2041 float x,y,z,o;
2042 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2044 x = m_targets.m_destX;
2045 y = m_targets.m_destY;
2046 z = m_targets.m_destZ;
2048 if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
2050 // explicit cast data from client or server-side cast
2051 // some spell at client send caster
2052 Unit* pTarget = NULL;
2053 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2054 pTarget = m_targets.getUnitTarget();
2055 else if(unitTarget->getVictim())
2056 pTarget = m_caster->getVictim();
2057 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2058 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2060 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2062 else
2063 o = m_caster->GetOrientation();
2065 else if(unitTarget)
2067 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2068 o = m_caster->GetOrientation();
2070 else if(gameObjTarget)
2072 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2073 o = m_caster->GetOrientation();
2075 else
2077 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2078 return;
2081 m_caster->NearTeleportTo(x,y,z,o,true);
2084 void Spell::EffectTeleportUnits(uint32 i)
2086 if(!unitTarget || unitTarget->isInFlight())
2087 return;
2089 switch (m_spellInfo->EffectImplicitTargetB[i])
2091 case TARGET_INNKEEPER_COORDINATES:
2093 // Only players can teleport to innkeeper
2094 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2095 return;
2097 ((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);
2098 return;
2100 case TARGET_TABLE_X_Y_Z_COORDINATES:
2102 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2103 if(!st)
2105 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2106 return;
2109 if(st->target_mapId==unitTarget->GetMapId())
2110 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2111 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2112 ((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);
2113 break;
2115 case TARGET_BEHIND_VICTIM:
2117 Unit *pTarget = NULL;
2119 // explicit cast data from client or server-side cast
2120 // some spell at client send caster
2121 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2122 pTarget = m_targets.getUnitTarget();
2123 else if(unitTarget->getVictim())
2124 pTarget = unitTarget->getVictim();
2125 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2126 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2128 // Init dest coordinates
2129 float x = m_targets.m_destX;
2130 float y = m_targets.m_destY;
2131 float z = m_targets.m_destZ;
2132 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2133 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2134 return;
2136 default:
2138 // If not exist data for dest location - return
2139 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2141 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2142 return;
2144 // Init dest coordinates
2145 uint32 mapid = m_caster->GetMapId();
2146 float x = m_targets.m_destX;
2147 float y = m_targets.m_destY;
2148 float z = m_targets.m_destZ;
2149 float orientation = unitTarget->GetOrientation();
2150 // Teleport
2151 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2152 return;
2156 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2157 switch ( m_spellInfo->Id )
2159 // Dimensional Ripper - Everlook
2160 case 23442:
2162 int32 r = irand(0, 119);
2163 if ( r >= 70 ) // 7/12 success
2165 if ( r < 100 ) // 4/12 evil twin
2166 m_caster->CastSpell(m_caster,23445,true);
2167 else // 1/12 fire
2168 m_caster->CastSpell(m_caster,23449,true);
2170 return;
2172 // Ultrasafe Transporter: Toshley's Station
2173 case 36941:
2175 if ( roll_chance_i(50) ) // 50% success
2177 int32 rand_eff = urand(1,7);
2178 switch ( rand_eff )
2180 case 1:
2181 // soul split - evil
2182 m_caster->CastSpell(m_caster,36900,true);
2183 break;
2184 case 2:
2185 // soul split - good
2186 m_caster->CastSpell(m_caster,36901,true);
2187 break;
2188 case 3:
2189 // Increase the size
2190 m_caster->CastSpell(m_caster,36895,true);
2191 break;
2192 case 4:
2193 // Decrease the size
2194 m_caster->CastSpell(m_caster,36893,true);
2195 break;
2196 case 5:
2197 // Transform
2199 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2200 m_caster->CastSpell(m_caster,36897,true);
2201 else
2202 m_caster->CastSpell(m_caster,36899,true);
2203 break;
2205 case 6:
2206 // chicken
2207 m_caster->CastSpell(m_caster,36940,true);
2208 break;
2209 case 7:
2210 // evil twin
2211 m_caster->CastSpell(m_caster,23445,true);
2212 break;
2215 return;
2217 // Dimensional Ripper - Area 52
2218 case 36890:
2220 if ( roll_chance_i(50) ) // 50% success
2222 int32 rand_eff = urand(1,4);
2223 switch ( rand_eff )
2225 case 1:
2226 // soul split - evil
2227 m_caster->CastSpell(m_caster,36900,true);
2228 break;
2229 case 2:
2230 // soul split - good
2231 m_caster->CastSpell(m_caster,36901,true);
2232 break;
2233 case 3:
2234 // Increase the size
2235 m_caster->CastSpell(m_caster,36895,true);
2236 break;
2237 case 4:
2238 // Transform
2240 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2241 m_caster->CastSpell(m_caster,36897,true);
2242 else
2243 m_caster->CastSpell(m_caster,36899,true);
2244 break;
2248 return;
2253 void Spell::EffectApplyAura(uint32 i)
2255 if(!unitTarget)
2256 return;
2258 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2259 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2260 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2261 return;
2263 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2264 if(!caster)
2265 return;
2267 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2269 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2271 // Now Reduce spell duration using data received at spell hit
2272 int32 duration = Aur->GetAuraMaxDuration();
2273 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2274 Aur->setDiminishGroup(m_diminishGroup);
2276 // if Aura removed and deleted, do not continue.
2277 if(duration== 0 && !(Aur->IsPermanent()))
2279 delete Aur;
2280 return;
2283 if(duration != Aur->GetAuraMaxDuration())
2285 Aur->SetAuraMaxDuration(duration);
2286 Aur->SetAuraDuration(duration);
2289 bool added = unitTarget->AddAura(Aur);
2291 // Aura not added and deleted in AddAura call;
2292 if (!added)
2293 return;
2295 // found crash at character loading, broken pointer to Aur...
2296 // Aur was deleted in AddAura()...
2297 if(!Aur)
2298 return;
2300 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2301 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2302 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2305 void Spell::EffectUnlearnSpecialization( uint32 i )
2307 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2308 return;
2310 Player *_player = (Player*)unitTarget;
2311 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2313 _player->removeSpell(spellToUnlearn);
2315 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2318 void Spell::EffectPowerDrain(uint32 i)
2320 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2321 return;
2323 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2325 if(!unitTarget)
2326 return;
2327 if(!unitTarget->isAlive())
2328 return;
2329 if(unitTarget->getPowerType() != drain_power)
2330 return;
2331 if(damage < 0)
2332 return;
2334 uint32 curPower = unitTarget->GetPower(drain_power);
2336 //add spell damage bonus
2337 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2339 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2340 uint32 power = damage;
2341 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2342 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2344 int32 new_damage;
2345 if(curPower < power)
2346 new_damage = curPower;
2347 else
2348 new_damage = power;
2350 unitTarget->ModifyPower(drain_power,-new_damage);
2352 // Don`t restore from self drain
2353 if(drain_power == POWER_MANA && m_caster != unitTarget)
2355 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2356 if(manaMultiplier==0)
2357 manaMultiplier = 1;
2359 if(Player *modOwner = m_caster->GetSpellModOwner())
2360 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2362 int32 gain = int32(new_damage*manaMultiplier);
2364 m_caster->ModifyPower(POWER_MANA,gain);
2365 //send log
2366 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2370 void Spell::EffectSendEvent(uint32 EffectIndex)
2373 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2375 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2376 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2379 void Spell::EffectPowerBurn(uint32 i)
2381 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2382 return;
2384 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2386 if(!unitTarget)
2387 return;
2388 if(!unitTarget->isAlive())
2389 return;
2390 if(unitTarget->getPowerType()!=powertype)
2391 return;
2392 if(damage < 0)
2393 return;
2395 int32 curPower = int32(unitTarget->GetPower(powertype));
2397 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2398 uint32 power = damage;
2399 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2400 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2402 int32 new_damage = (curPower < power) ? curPower : power;
2404 unitTarget->ModifyPower(powertype,-new_damage);
2405 float multiplier = m_spellInfo->EffectMultipleValue[i];
2407 if(Player *modOwner = m_caster->GetSpellModOwner())
2408 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2410 new_damage = int32(new_damage*multiplier);
2411 m_damage+=new_damage;
2414 void Spell::EffectHeal( uint32 /*i*/ )
2416 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2418 // Try to get original caster
2419 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2421 // Skip if m_originalCaster not available
2422 if (!caster)
2423 return;
2425 int32 addhealth = damage;
2427 // Vessel of the Naaru (Vial of the Sunwell trinket)
2428 if (m_spellInfo->Id == 45064)
2430 // Amount of heal - depends from stacked Holy Energy
2431 int damageAmount = 0;
2432 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2433 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2434 if((*i)->GetId() == 45062)
2435 damageAmount+=(*i)->GetModifier()->m_amount;
2436 if (damageAmount)
2437 m_caster->RemoveAurasDueToSpell(45062);
2439 addhealth += damageAmount;
2441 // Swiftmend - consumes Regrowth or Rejuvenation
2442 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2444 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2445 // find most short by duration
2446 Aura *targetAura = NULL;
2447 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2449 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2450 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2452 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2453 targetAura = *i;
2457 if(!targetAura)
2459 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2460 return;
2462 int idx = 0;
2463 while(idx < 3)
2465 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2466 break;
2467 idx++;
2470 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2471 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2472 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2474 addhealth += tickheal * tickcount;
2476 else
2477 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2479 m_healing+=addhealth;
2483 void Spell::EffectHealPct( uint32 /*i*/ )
2485 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2487 // Try to get original caster
2488 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2490 // Skip if m_originalCaster not available
2491 if (!caster)
2492 return;
2494 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2495 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2497 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2498 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2500 if(caster->GetTypeId()==TYPEID_PLAYER)
2501 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2502 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2506 void Spell::EffectHealMechanical( uint32 /*i*/ )
2508 // Mechanic creature type should be correctly checked by targetCreatureType field
2509 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2511 // Try to get original caster
2512 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2514 // Skip if m_originalCaster not available
2515 if (!caster)
2516 return;
2518 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2519 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2520 unitTarget->ModifyHealth( int32(damage) );
2524 void Spell::EffectHealthLeech(uint32 i)
2526 if(!unitTarget)
2527 return;
2528 if(!unitTarget->isAlive())
2529 return;
2531 if(damage < 0)
2532 return;
2534 sLog.outDebug("HealthLeech :%i", damage);
2536 float multiplier = m_spellInfo->EffectMultipleValue[i];
2538 if(Player *modOwner = m_caster->GetSpellModOwner())
2539 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2541 int32 new_damage = int32(damage*multiplier);
2542 uint32 curHealth = unitTarget->GetHealth();
2543 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2544 if(curHealth < new_damage)
2545 new_damage = curHealth;
2547 if(m_caster->isAlive())
2549 new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
2551 m_caster->ModifyHealth(new_damage);
2553 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2554 m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2556 // m_healthLeech+=tmpvalue;
2557 // m_damage+=new_damage;
2560 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2562 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2563 return;
2565 Player* player = (Player*)unitTarget;
2567 uint32 newitemid = itemtype;
2568 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2569 if(!pProto)
2571 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2572 return;
2575 uint32 num_to_add;
2577 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2578 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2580 int32 basePoints = m_currentBasePoints[i];
2581 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2582 if (randomPoints)
2583 num_to_add = basePoints + irand(1, randomPoints);
2584 else
2585 num_to_add = basePoints + 1;
2587 else if (pProto->MaxCount == 1)
2588 num_to_add = 1;
2589 else if(player->getLevel() >= m_spellInfo->spellLevel)
2591 int32 basePoints = m_currentBasePoints[i];
2592 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2593 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2595 else
2596 num_to_add = 2;
2598 if (num_to_add < 1)
2599 num_to_add = 1;
2600 if (num_to_add > pProto->GetMaxStackSize())
2601 num_to_add = pProto->GetMaxStackSize();
2603 // init items_count to 1, since 1 item will be created regardless of specialization
2604 int items_count=1;
2605 // the chance to create additional items
2606 float additionalCreateChance=0.0f;
2607 // the maximum number of created additional items
2608 uint8 additionalMaxNum=0;
2609 // get the chance and maximum number for creating extra items
2610 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2612 // roll with this chance till we roll not to create or we create the max num
2613 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2614 ++items_count;
2617 // really will be created more items
2618 num_to_add *= items_count;
2620 // can the player store the new item?
2621 ItemPosCountVec dest;
2622 uint32 no_space = 0;
2623 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2624 if( msg != EQUIP_ERR_OK )
2626 // convert to possible store amount
2627 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2628 num_to_add -= no_space;
2629 else
2631 // if not created by another reason from full inventory or unique items amount limitation
2632 player->SendEquipError( msg, NULL, NULL );
2633 return;
2637 if(num_to_add)
2639 // create the new item and store it
2640 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2642 // was it successful? return error if not
2643 if(!pItem)
2645 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2646 return;
2649 // set the "Crafted by ..." property of the item
2650 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2651 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2653 // send info to the client
2654 if(pItem)
2655 player->SendNewItem(pItem, num_to_add, true, true);
2657 // we succeeded in creating at least one item, so a levelup is possible
2658 player->UpdateCraftSkill(m_spellInfo->Id);
2661 // for battleground marks send by mail if not add all expected
2662 if(no_space > 0 )
2664 BattleGroundTypeId bgType;
2665 switch(m_spellInfo->Id)
2667 case SPELL_AV_MARK_WINNER:
2668 case SPELL_AV_MARK_LOSER:
2669 bgType = BATTLEGROUND_AV;
2670 break;
2671 case SPELL_WS_MARK_WINNER:
2672 case SPELL_WS_MARK_LOSER:
2673 bgType = BATTLEGROUND_WS;
2674 break;
2675 case SPELL_AB_MARK_WINNER:
2676 case SPELL_AB_MARK_LOSER:
2677 bgType = BATTLEGROUND_AB;
2678 break;
2679 default:
2680 return;
2683 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2684 bg->SendRewardMarkByMail(player,newitemid,no_space);
2688 void Spell::EffectCreateItem(uint32 i)
2690 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2693 void Spell::EffectCreateItem2(uint32 i)
2695 // special case: generate using spell_loot_template
2696 if(!m_spellInfo->EffectItemType[i])
2698 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
2699 return;
2701 // create some random items
2702 ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
2703 return;
2705 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2708 void Spell::EffectPersistentAA(uint32 i)
2710 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2712 if(Player* modOwner = m_caster->GetSpellModOwner())
2713 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2715 int32 duration = GetSpellDuration(m_spellInfo);
2716 DynamicObject* dynObj = new DynamicObject;
2717 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))
2719 delete dynObj;
2720 return;
2722 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2723 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2724 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2725 m_caster->AddDynObject(dynObj);
2726 dynObj->GetMap()->Add(dynObj);
2729 void Spell::EffectEnergize(uint32 i)
2731 if(!unitTarget)
2732 return;
2733 if(!unitTarget->isAlive())
2734 return;
2736 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2737 return;
2739 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2741 // Some level depends spells
2742 int multiplier = 0;
2743 int level_diff = 0;
2744 switch (m_spellInfo->Id)
2746 // Restore Energy
2747 case 9512:
2748 level_diff = m_caster->getLevel() - 40;
2749 multiplier = 2;
2750 break;
2751 // Blood Fury
2752 case 24571:
2753 level_diff = m_caster->getLevel() - 60;
2754 multiplier = 10;
2755 break;
2756 // Burst of Energy
2757 case 24532:
2758 level_diff = m_caster->getLevel() - 60;
2759 multiplier = 4;
2760 break;
2761 default:
2762 break;
2765 if (level_diff > 0)
2766 damage -= multiplier * level_diff;
2768 if(damage < 0)
2769 return;
2771 if(unitTarget->GetMaxPower(power) == 0)
2772 return;
2774 unitTarget->ModifyPower(power,damage);
2775 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2777 // Mad Alchemist's Potion
2778 if (m_spellInfo->Id == 45051)
2780 // find elixirs on target
2781 uint32 elixir_mask = 0;
2782 Unit::AuraMap& Auras = unitTarget->GetAuras();
2783 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2785 uint32 spell_id = itr->second->GetId();
2786 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2787 elixir_mask |= mask;
2790 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2791 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2793 // get all available elixirs by mask and spell level
2794 std::vector<uint32> elixirs;
2795 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2796 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2798 if (itr->second & elixir_mask)
2800 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2801 continue;
2803 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2804 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2805 continue;
2807 elixirs.push_back(itr->first);
2811 if (!elixirs.empty())
2813 // cast random elixir on target
2814 uint32 rand_spell = urand(0,elixirs.size()-1);
2815 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2820 void Spell::EffectEnergisePct(uint32 i)
2822 if(!unitTarget)
2823 return;
2824 if(!unitTarget->isAlive())
2825 return;
2827 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2828 return;
2830 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2832 uint32 maxPower = unitTarget->GetMaxPower(power);
2833 if(maxPower == 0)
2834 return;
2836 uint32 gain = damage * maxPower / 100;
2837 unitTarget->ModifyPower(power, gain);
2838 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
2841 void Spell::SendLoot(uint64 guid, LootType loottype)
2843 Player* player = (Player*)m_caster;
2844 if (!player)
2845 return;
2847 if (gameObjTarget)
2849 if (Script->GOHello(player, gameObjTarget))
2850 return;
2852 switch (gameObjTarget->GetGoType())
2854 case GAMEOBJECT_TYPE_DOOR:
2855 case GAMEOBJECT_TYPE_BUTTON:
2856 gameObjTarget->UseDoorOrButton();
2857 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2858 return;
2860 case GAMEOBJECT_TYPE_QUESTGIVER:
2861 // start or end quest
2862 player->PrepareQuestMenu(guid);
2863 player->SendPreparedQuest(guid);
2864 return;
2866 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2867 // triggering linked GO
2868 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2869 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2870 return;
2872 case GAMEOBJECT_TYPE_GOOBER:
2873 // goober_scripts can be triggered if the player don't have the quest
2874 if (gameObjTarget->GetGOInfo()->goober.eventId)
2876 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2877 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2880 // cast goober spell
2881 if (gameObjTarget->GetGOInfo()->goober.questId)
2882 ///Quest require to be active for GO using
2883 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2884 return;
2886 gameObjTarget->AddUniqueUse(player);
2887 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2889 //TODO? Objective counting called without spell check but with quest objective check
2890 // if send spell id then this line will duplicate to spell casting call (double counting)
2891 // So we or have this line and not required in quest_template have reqSpellIdN
2892 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2893 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2895 // triggering linked GO
2896 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2897 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2899 return;
2901 case GAMEOBJECT_TYPE_CHEST:
2902 // TODO: possible must be moved to loot release (in different from linked triggering)
2903 if (gameObjTarget->GetGOInfo()->chest.eventId)
2905 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2906 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2909 // triggering linked GO
2910 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2911 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2913 // Don't return, let loots been taken
2917 // Send loot
2918 player->SendLoot(guid, loottype);
2921 void Spell::EffectOpenLock(uint32 effIndex)
2923 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2925 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2926 return;
2929 Player* player = (Player*)m_caster;
2931 uint32 lockId = 0;
2932 uint64 guid = 0;
2934 // Get lockId
2935 if(gameObjTarget)
2937 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2938 // Arathi Basin banner opening !
2939 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2940 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2942 //CanUseBattleGroundObject() already called in CheckCast()
2943 // in battleground check
2944 if(BattleGround *bg = player->GetBattleGround())
2946 // check if it's correct bg
2947 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2948 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2949 return;
2952 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2954 //CanUseBattleGroundObject() already called in CheckCast()
2955 // in battleground check
2956 if(BattleGround *bg = player->GetBattleGround())
2958 if(bg->GetTypeID() == BATTLEGROUND_EY)
2959 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2960 return;
2963 lockId = gameObjTarget->GetLockId();
2964 guid = gameObjTarget->GetGUID();
2966 else if(itemTarget)
2968 lockId = itemTarget->GetProto()->LockID;
2969 guid = itemTarget->GetGUID();
2971 else
2973 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2974 return;
2977 SkillType skillId = SKILL_NONE;
2978 int32 reqSkillValue = 0;
2979 int32 skillValue;
2981 SpellCastResult res = CanOpenLock(effIndex,lockId,skillId,reqSkillValue,skillValue);
2982 if(res != SPELL_CAST_OK)
2984 SendCastResult(res);
2985 return;
2988 SendLoot(guid, LOOT_SKINNING);
2990 // not allow use skill grow at item base open
2991 if(!m_CastItem && skillId != SKILL_NONE)
2993 // update skill if really known
2994 if(uint32 pureSkillValue = player->GetPureSkillValue(skillId))
2996 if(gameObjTarget)
2998 // Allow one skill-up until respawned
2999 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3000 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue) )
3001 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3003 else if(itemTarget)
3005 // Do one skill-up
3006 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3012 void Spell::EffectSummonChangeItem(uint32 i)
3014 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3015 return;
3017 Player *player = (Player*)m_caster;
3019 // applied only to using item
3020 if(!m_CastItem)
3021 return;
3023 // ... only to item in own inventory/bank/equip_slot
3024 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3025 return;
3027 uint32 newitemid = m_spellInfo->EffectItemType[i];
3028 if(!newitemid)
3029 return;
3031 uint16 pos = m_CastItem->GetPos();
3033 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3034 if( !pNewItem )
3035 return;
3037 for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3039 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3040 pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3043 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3045 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3046 player->DurabilityLoss(pNewItem, loosePercent);
3049 if( player->IsInventoryPos( pos ) )
3051 ItemPosCountVec dest;
3052 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3053 if( msg == EQUIP_ERR_OK )
3055 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3057 // prevent crash at access and unexpected charges counting with item update queue corrupt
3058 if(m_CastItem==m_targets.getItemTarget())
3059 m_targets.setItemTarget(NULL);
3061 m_CastItem = NULL;
3063 player->StoreItem( dest, pNewItem, true);
3064 return;
3067 else if( player->IsBankPos ( pos ) )
3069 ItemPosCountVec dest;
3070 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3071 if( msg == EQUIP_ERR_OK )
3073 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3075 // prevent crash at access and unexpected charges counting with item update queue corrupt
3076 if(m_CastItem==m_targets.getItemTarget())
3077 m_targets.setItemTarget(NULL);
3079 m_CastItem = NULL;
3081 player->BankItem( dest, pNewItem, true);
3082 return;
3085 else if( player->IsEquipmentPos ( pos ) )
3087 uint16 dest;
3088 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3089 if( msg == EQUIP_ERR_OK )
3091 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3093 // prevent crash at access and unexpected charges counting with item update queue corrupt
3094 if(m_CastItem==m_targets.getItemTarget())
3095 m_targets.setItemTarget(NULL);
3097 m_CastItem = NULL;
3099 player->EquipItem( dest, pNewItem, true);
3100 player->AutoUnequipOffhandIfNeed();
3101 return;
3105 // fail
3106 delete pNewItem;
3109 void Spell::EffectOpenSecretSafe(uint32 i)
3111 EffectOpenLock(i); //no difference for now
3114 void Spell::EffectProficiency(uint32 /*i*/)
3116 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3117 return;
3118 Player *p_target = (Player*)unitTarget;
3120 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3121 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3123 p_target->AddWeaponProficiency(subClassMask);
3124 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3126 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3128 p_target->AddArmorProficiency(subClassMask);
3129 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3133 void Spell::EffectApplyAreaAura(uint32 i)
3135 if(!unitTarget)
3136 return;
3137 if(!unitTarget->isAlive())
3138 return;
3140 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3141 unitTarget->AddAura(Aur);
3144 void Spell::EffectSummonType(uint32 i)
3146 switch(m_spellInfo->EffectMiscValueB[i])
3148 case SUMMON_TYPE_GUARDIAN:
3149 case SUMMON_TYPE_POSESSED:
3150 case SUMMON_TYPE_POSESSED2:
3151 case SUMMON_TYPE_FORCE_OF_NATURE:
3152 case SUMMON_TYPE_GUARDIAN2:
3153 EffectSummonGuardian(i);
3154 break;
3155 case SUMMON_TYPE_WILD:
3156 EffectSummonWild(i);
3157 break;
3158 case SUMMON_TYPE_DEMON:
3159 EffectSummonDemon(i);
3160 break;
3161 case SUMMON_TYPE_SUMMON:
3162 EffectSummon(i);
3163 break;
3164 case SUMMON_TYPE_CRITTER:
3165 case SUMMON_TYPE_CRITTER2:
3166 case SUMMON_TYPE_CRITTER3:
3167 EffectSummonCritter(i);
3168 break;
3169 case SUMMON_TYPE_TOTEM_SLOT1:
3170 case SUMMON_TYPE_TOTEM_SLOT2:
3171 case SUMMON_TYPE_TOTEM_SLOT3:
3172 case SUMMON_TYPE_TOTEM_SLOT4:
3173 case SUMMON_TYPE_TOTEM:
3174 EffectSummonTotem(i);
3175 break;
3176 case SUMMON_TYPE_UNKNOWN1:
3177 case SUMMON_TYPE_UNKNOWN2:
3178 case SUMMON_TYPE_UNKNOWN3:
3179 case SUMMON_TYPE_UNKNOWN4:
3180 case SUMMON_TYPE_UNKNOWN5:
3181 break;
3182 default:
3183 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3184 break;
3188 void Spell::EffectSummon(uint32 i)
3190 if(m_caster->GetPetGUID())
3191 return;
3193 if(!unitTarget)
3194 return;
3195 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3196 if(!pet_entry)
3197 return;
3198 uint32 level = m_caster->getLevel();
3199 Pet* spawnCreature = new Pet(SUMMON_PET);
3201 if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3203 // set timer for unsummon
3204 int32 duration = GetSpellDuration(m_spellInfo);
3205 if(duration > 0)
3206 spawnCreature->SetDuration(duration);
3208 return;
3211 Map *map = m_caster->GetMap();
3212 uint32 pet_number = objmgr.GeneratePetNumber();
3213 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_caster->GetPhaseMask(),
3214 m_spellInfo->EffectMiscValue[i], pet_number))
3216 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3217 delete spawnCreature;
3218 return;
3221 // Summon in dest location
3222 float x,y,z;
3223 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3225 x = m_targets.m_destX;
3226 y = m_targets.m_destY;
3227 z = m_targets.m_destZ;
3229 else
3230 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3232 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3234 if(!spawnCreature->IsPositionValid())
3236 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3237 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3238 delete spawnCreature;
3239 return;
3242 // set timer for unsummon
3243 int32 duration = GetSpellDuration(m_spellInfo);
3244 if(duration > 0)
3245 spawnCreature->SetDuration(duration);
3247 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3248 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3249 spawnCreature->setPowerType(POWER_MANA);
3250 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3251 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3252 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3253 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3254 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3255 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3256 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3257 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3258 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3260 spawnCreature->InitStatsForLevel(level);
3262 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3264 spawnCreature->AIM_Initialize();
3265 spawnCreature->InitPetCreateSpells();
3266 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3267 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3269 std::string name = m_caster->GetName();
3270 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3271 spawnCreature->SetName( name );
3273 map->Add((Creature*)spawnCreature);
3275 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3277 m_caster->SetPet(spawnCreature);
3278 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3279 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3280 ((Player*)m_caster)->PetSpellInitialize();
3284 void Spell::EffectLearnSpell(uint32 i)
3286 if(!unitTarget)
3287 return;
3289 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3291 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3292 EffectLearnPetSpell(i);
3294 return;
3297 Player *player = (Player*)unitTarget;
3299 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3300 player->learnSpell(spellToLearn,false);
3302 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3305 void Spell::EffectDispel(uint32 i)
3307 if(!unitTarget)
3308 return;
3310 // Fill possible dispell list
3311 std::vector <Aura *> dispel_list;
3313 // Create dispel mask by dispel type
3314 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3315 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3316 Unit::AuraMap const& auras = unitTarget->GetAuras();
3317 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3319 Aura *aur = (*itr).second;
3320 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3322 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3324 bool positive = true;
3325 if (!aur->IsPositive())
3326 positive = false;
3327 else
3328 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3330 // do not remove positive auras if friendly target
3331 // negative auras if non-friendly target
3332 if(positive == unitTarget->IsFriendlyTo(m_caster))
3333 continue;
3335 // Add aura to dispel list
3336 dispel_list.push_back(aur);
3339 // Ok if exist some buffs for dispel try dispel it
3340 if (!dispel_list.empty())
3342 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3343 std::list < uint32 > fail_list; // spell_id
3344 int32 list_size = dispel_list.size();
3345 // Dispell N = damage buffs (or while exist buffs for dispel)
3346 for (int32 count=0; count < damage && list_size > 0; ++count)
3348 // Random select buff for dispel
3349 Aura *aur = dispel_list[urand(0, list_size-1)];
3351 SpellEntry const* spellInfo = aur->GetSpellProto();
3352 // Base dispel chance
3353 // TODO: possible chance depend from spell level??
3354 int32 miss_chance = 0;
3355 // Apply dispel mod from aura caster
3356 if (Unit *caster = aur->GetCaster())
3358 if ( Player* modOwner = caster->GetSpellModOwner() )
3359 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3361 // Try dispel
3362 if (roll_chance_i(miss_chance))
3363 fail_list.push_back(aur->GetId());
3364 else
3365 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3366 // Remove buff from list for prevent doubles
3367 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3369 Aura *dispeled = *j;
3370 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3372 j = dispel_list.erase(j);
3373 --list_size;
3375 else
3376 ++j;
3379 // Send success log and really remove auras
3380 if (!success_list.empty())
3382 int32 count = success_list.size();
3383 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3384 data.append(unitTarget->GetPackGUID()); // Victim GUID
3385 data.append(m_caster->GetPackGUID()); // Caster GUID
3386 data << uint32(m_spellInfo->Id); // Dispell spell id
3387 data << uint8(0); // not used
3388 data << uint32(count); // count
3389 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3391 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3392 data << uint32(spellInfo->Id); // Spell Id
3393 data << uint8(0); // 0 - dispeled !=0 cleansed
3394 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3396 m_caster->SendMessageToSet(&data, true);
3398 // On succes dispel
3399 // Devour Magic
3400 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3402 uint32 heal_spell = 0;
3403 switch (m_spellInfo->Id)
3405 case 19505: heal_spell = 19658; break;
3406 case 19731: heal_spell = 19732; break;
3407 case 19734: heal_spell = 19733; break;
3408 case 19736: heal_spell = 19735; break;
3409 case 27276: heal_spell = 27278; break;
3410 case 27277: heal_spell = 27279; break;
3411 default:
3412 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3413 break;
3415 if (heal_spell)
3416 m_caster->CastSpell(m_caster, heal_spell, true);
3419 // Send fail log to client
3420 if (!fail_list.empty())
3422 // Failed to dispell
3423 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3424 data << uint64(m_caster->GetGUID()); // Caster GUID
3425 data << uint64(unitTarget->GetGUID()); // Victim GUID
3426 data << uint32(m_spellInfo->Id); // Dispell spell id
3427 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3428 data << uint32(*j); // Spell Id
3429 m_caster->SendMessageToSet(&data, true);
3434 void Spell::EffectDualWield(uint32 /*i*/)
3436 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3437 ((Player*)unitTarget)->SetCanDualWield(true);
3440 void Spell::EffectPull(uint32 /*i*/)
3442 // TODO: create a proper pull towards distract spell center for distract
3443 sLog.outDebug("WORLD: Spell Effect DUMMY");
3446 void Spell::EffectDistract(uint32 /*i*/)
3448 // Check for possible target
3449 if (!unitTarget || unitTarget->isInCombat())
3450 return;
3452 // target must be OK to do this
3453 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3454 return;
3456 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3458 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3460 // For players just turn them
3461 WorldPacket data;
3462 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3463 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3464 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3466 else
3468 // Set creature Distracted, Stop it, And turn it
3469 unitTarget->SetOrientation(angle);
3470 unitTarget->StopMoving();
3471 unitTarget->GetMotionMaster()->MoveDistract(damage*IN_MILISECONDS);
3475 void Spell::EffectPickPocket(uint32 /*i*/)
3477 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3478 return;
3480 // victim must be creature and attackable
3481 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3482 return;
3484 // victim have to be alive and humanoid or undead
3485 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3487 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3489 if (chance > irand(0, 19))
3491 // Stealing successful
3492 //sLog.outDebug("Sending loot from pickpocket");
3493 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3495 else
3497 // Reveal action + get attack
3498 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3499 if (((Creature*)unitTarget)->AI())
3500 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3505 void Spell::EffectAddFarsight(uint32 i)
3507 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3508 int32 duration = GetSpellDuration(m_spellInfo);
3509 DynamicObject* dynObj = new DynamicObject;
3510 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))
3512 delete dynObj;
3513 return;
3515 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3516 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3517 m_caster->AddDynObject(dynObj);
3518 dynObj->GetMap()->Add(dynObj);
3519 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3520 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3523 void Spell::EffectSummonWild(uint32 i)
3525 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3526 if(!creature_entry)
3527 return;
3529 uint32 level = m_caster->getLevel();
3531 // level of creature summoned using engineering item based at engineering skill level
3532 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3534 ItemPrototype const *proto = m_CastItem->GetProto();
3535 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3537 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3538 if(skill202)
3540 level = skill202/5;
3545 // select center of summon position
3546 float center_x = m_targets.m_destX;
3547 float center_y = m_targets.m_destY;
3548 float center_z = m_targets.m_destZ;
3550 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3552 int32 amount = damage > 0 ? damage : 1;
3554 for(int32 count = 0; count < amount; ++count)
3556 float px, py, pz;
3557 // If dest location if present
3558 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3560 // Summon 1 unit in dest location
3561 if (count == 0)
3563 px = m_targets.m_destX;
3564 py = m_targets.m_destY;
3565 pz = m_targets.m_destZ;
3567 // Summon in random point all other units if location present
3568 else
3569 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3571 // Summon if dest location not present near caster
3572 else
3573 m_caster->GetClosePoint(px,py,pz,3.0f);
3575 int32 duration = GetSpellDuration(m_spellInfo);
3577 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3579 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3583 void Spell::EffectSummonGuardian(uint32 i)
3585 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3586 if(!pet_entry)
3587 return;
3589 // Jewelery statue case (totem like)
3590 if(m_spellInfo->SpellIconID==2056)
3592 EffectSummonTotem(i);
3593 return;
3596 // set timer for unsummon
3597 int32 duration = GetSpellDuration(m_spellInfo);
3599 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3600 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3601 // so this code hack in fact
3602 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3603 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3604 return; // find old guardian, ignore summon
3606 // in another case summon new
3607 uint32 level = m_caster->getLevel();
3609 // level of pet summoned using engineering item based at engineering skill level
3610 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3612 ItemPrototype const *proto = m_CastItem->GetProto();
3613 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3615 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3616 if(skill202)
3618 level = skill202/5;
3623 // select center of summon position
3624 float center_x = m_targets.m_destX;
3625 float center_y = m_targets.m_destY;
3626 float center_z = m_targets.m_destZ;
3628 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3630 int32 amount = damage > 0 ? damage : 1;
3632 for(int32 count = 0; count < amount; ++count)
3634 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3636 Map *map = m_caster->GetMap();
3637 uint32 pet_number = objmgr.GeneratePetNumber();
3638 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3639 m_spellInfo->EffectMiscValue[i], pet_number))
3641 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3642 delete spawnCreature;
3643 return;
3646 float px, py, pz;
3647 // If dest location if present
3648 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3650 // Summon 1 unit in dest location
3651 if (count == 0)
3653 px = m_targets.m_destX;
3654 py = m_targets.m_destY;
3655 pz = m_targets.m_destZ;
3657 // Summon in random point all other units if location present
3658 else
3659 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3661 // Summon if dest location not present near caster
3662 else
3663 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3665 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3667 if(!spawnCreature->IsPositionValid())
3669 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3670 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3671 delete spawnCreature;
3672 return;
3675 if(duration > 0)
3676 spawnCreature->SetDuration(duration);
3678 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3679 spawnCreature->setPowerType(POWER_MANA);
3680 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3681 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3682 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3683 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3684 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3685 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3686 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3688 spawnCreature->InitStatsForLevel(level);
3689 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3691 spawnCreature->AIM_Initialize();
3693 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3694 ((Player*)m_caster)->AddGuardian(spawnCreature);
3696 map->Add((Creature*)spawnCreature);
3700 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3702 if(!unitTarget)
3703 return;
3705 if(unitTarget->isInFlight())
3706 return;
3708 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3710 float fx,fy,fz;
3711 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3713 unitTarget->NearTeleportTo(fx,fy,fz,-m_caster->GetOrientation(),unitTarget==m_caster);
3716 void Spell::EffectLearnSkill(uint32 i)
3718 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3719 return;
3721 if(damage < 0)
3722 return;
3724 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3725 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3726 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3729 void Spell::EffectAddHonor(uint32 /*i*/)
3731 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3732 return;
3734 // not scale value for item based reward (/10 value expected)
3735 if(m_CastItem)
3737 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage/10);
3738 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
3739 return;
3742 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3743 if( damage <= 50)
3745 uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
3746 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
3747 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
3749 else
3751 //maybe we have correct honor_gain in damage already
3752 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3753 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3757 void Spell::EffectTradeSkill(uint32 /*i*/)
3759 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3760 return;
3761 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3762 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3763 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3766 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
3768 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3769 return;
3770 if (!itemTarget)
3771 return;
3773 Player* p_caster = (Player*)m_caster;
3775 // not grow at item use at item case
3776 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3778 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3779 if (!enchant_id)
3780 return;
3782 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3783 if(!pEnchant)
3784 return;
3786 // item can be in trade slot and have owner diff. from caster
3787 Player* item_owner = itemTarget->GetOwner();
3788 if(!item_owner)
3789 return;
3791 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3793 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3794 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3795 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3796 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3799 // remove old enchanting before applying new if equipped
3800 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3802 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3804 // add new enchanting if equipped
3805 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3808 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
3810 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3811 return;
3812 if (!itemTarget)
3813 return;
3815 Player* p_caster = (Player*)m_caster;
3817 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3818 if (!enchant_id)
3819 return;
3821 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3822 if(!pEnchant)
3823 return;
3825 // support only enchantings with add socket in this slot
3827 bool add_socket = false;
3828 for(int i = 0; i < 3; ++i)
3830 if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
3832 add_socket = true;
3833 break;
3836 if(!add_socket)
3838 sLog.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (u), not suppoted yet.",
3839 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
3840 return;
3844 // item can be in trade slot and have owner diff. from caster
3845 Player* item_owner = itemTarget->GetOwner();
3846 if(!item_owner)
3847 return;
3849 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3851 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3852 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3853 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3854 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3857 // remove old enchanting before applying new if equipped
3858 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
3860 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3862 // add new enchanting if equipped
3863 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
3866 void Spell::EffectEnchantItemTmp(uint32 i)
3868 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3869 return;
3871 Player* p_caster = (Player*)m_caster;
3873 if(!itemTarget)
3874 return;
3876 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3878 // Shaman Rockbiter Weapon
3879 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3881 int32 enchnting_damage = m_currentBasePoints[1]+1;
3883 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3884 // with already applied percent bonus from Elemental Weapons talent
3885 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3886 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3887 switch(enchnting_damage)
3889 // Rank 1
3890 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3891 // Rank 2
3892 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3893 case 5: enchant_id = 3025; break; // 20%
3894 // Rank 3
3895 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3896 case 7: enchant_id = 3027; break; // 20%
3897 // Rank 4
3898 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3899 case 10: enchant_id = 503; break; // 14%
3900 case 11: enchant_id = 3031; break; // 20%
3901 // Rank 5
3902 case 15: enchant_id = 3035; break; // 0%
3903 case 16: enchant_id = 1663; break; // 7%
3904 case 17: enchant_id = 3033; break; // 14%
3905 case 18: enchant_id = 3034; break; // 20%
3906 // Rank 6
3907 case 28: enchant_id = 3038; break; // 0%
3908 case 29: enchant_id = 683; break; // 7%
3909 case 31: enchant_id = 3036; break; // 14%
3910 case 33: enchant_id = 3037; break; // 20%
3911 // Rank 7
3912 case 40: enchant_id = 3041; break; // 0%
3913 case 42: enchant_id = 1664; break; // 7%
3914 case 45: enchant_id = 3039; break; // 14%
3915 case 48: enchant_id = 3040; break; // 20%
3916 // Rank 8
3917 case 49: enchant_id = 3044; break; // 0%
3918 case 52: enchant_id = 2632; break; // 7%
3919 case 55: enchant_id = 3042; break; // 14%
3920 case 58: enchant_id = 3043; break; // 20%
3921 // Rank 9
3922 case 62: enchant_id = 2633; break; // 0%
3923 case 66: enchant_id = 3018; break; // 7%
3924 case 70: enchant_id = 3019; break; // 14%
3925 case 74: enchant_id = 3020; break; // 20%
3926 default:
3927 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3928 return;
3932 if (!enchant_id)
3934 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3935 return;
3938 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3939 if(!pEnchant)
3941 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3942 return;
3945 // select enchantment duration
3946 uint32 duration;
3948 // rogue family enchantments exception by duration
3949 if(m_spellInfo->Id==38615)
3950 duration = 1800; // 30 mins
3951 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3952 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3953 duration = 3600; // 1 hour
3954 // shaman family enchantments
3955 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3956 duration = 1800; // 30 mins
3957 // other cases with this SpellVisual already selected
3958 else if(m_spellInfo->SpellVisual[0]==215)
3959 duration = 1800; // 30 mins
3960 // some fishing pole bonuses
3961 else if(m_spellInfo->SpellVisual[0]==563)
3962 duration = 600; // 10 mins
3963 // shaman rockbiter enchantments
3964 else if(m_spellInfo->SpellVisual[0]==0)
3965 duration = 1800; // 30 mins
3966 else if(m_spellInfo->Id==29702)
3967 duration = 300; // 5 mins
3968 else if(m_spellInfo->Id==37360)
3969 duration = 300; // 5 mins
3970 // default case
3971 else
3972 duration = 3600; // 1 hour
3974 // item can be in trade slot and have owner diff. from caster
3975 Player* item_owner = itemTarget->GetOwner();
3976 if(!item_owner)
3977 return;
3979 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3981 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3982 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3983 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3984 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3987 // remove old enchanting before applying new if equipped
3988 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3990 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3992 // add new enchanting if equipped
3993 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3996 void Spell::EffectTameCreature(uint32 /*i*/)
3998 if(m_caster->GetPetGUID())
3999 return;
4001 if(!unitTarget)
4002 return;
4004 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4005 return;
4007 Creature* creatureTarget = (Creature*)unitTarget;
4009 if(creatureTarget->isPet())
4010 return;
4012 if(m_caster->getClass() != CLASS_HUNTER)
4013 return;
4015 // cast finish successfully
4016 //SendChannelUpdate(0);
4017 finish();
4019 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
4021 // kill original creature
4022 creatureTarget->setDeathState(JUST_DIED);
4023 creatureTarget->RemoveCorpse();
4024 creatureTarget->SetHealth(0); // just for nice GM-mode view
4026 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4028 // prepare visual effect for levelup
4029 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4031 // add to world
4032 pet->GetMap()->Add((Creature*)pet);
4034 // visual effect for levelup
4035 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4037 // caster have pet now
4038 m_caster->SetPet(pet);
4040 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4042 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4043 ((Player*)m_caster)->PetSpellInitialize();
4047 void Spell::EffectSummonPet(uint32 i)
4049 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4051 Pet *OldSummon = m_caster->GetPet();
4053 // if pet requested type already exist
4054 if( OldSummon )
4056 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4058 // pet in corpse state can't be summoned
4059 if( OldSummon->isDead() )
4060 return;
4062 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4063 OldSummon->SetMapId(m_caster->GetMapId());
4065 float px, py, pz;
4066 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4068 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4069 m_caster->GetMap()->Add((Creature*)OldSummon);
4071 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4073 ((Player*)m_caster)->PetSpellInitialize();
4075 return;
4078 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4079 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4080 else
4081 return;
4084 Pet* NewSummon = new Pet;
4086 // petentry==0 for hunter "call pet" (current pet summoned if any)
4087 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4089 if(NewSummon->getPetType()==SUMMON_PET)
4091 // Remove Demonic Sacrifice auras (known pet)
4092 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4093 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4095 if((*itr)->GetModifier()->m_miscvalue==2228)
4097 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4098 itr = auraClassScripts.begin();
4100 else
4101 ++itr;
4105 return;
4108 // not error in case fail hunter call pet
4109 if(!petentry)
4111 delete NewSummon;
4112 return;
4115 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4117 if(!cInfo)
4119 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4120 delete NewSummon;
4121 return;
4124 Map *map = m_caster->GetMap();
4125 uint32 pet_number = objmgr.GeneratePetNumber();
4126 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4127 petentry, pet_number))
4129 delete NewSummon;
4130 return;
4133 float px, py, pz;
4134 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4136 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4138 if(!NewSummon->IsPositionValid())
4140 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4141 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4142 delete NewSummon;
4143 return;
4146 uint32 petlevel = m_caster->getLevel();
4147 NewSummon->setPetType(SUMMON_PET);
4149 uint32 faction = m_caster->getFaction();
4150 if(m_caster->GetTypeId() == TYPEID_UNIT)
4152 if ( ((Creature*)m_caster)->isTotem() )
4153 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4154 else
4155 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4158 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4159 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4160 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4161 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4162 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4163 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4164 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4165 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4166 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4167 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4169 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4170 // this enables pet details window (Shift+P)
4172 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4173 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4174 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4176 NewSummon->InitStatsForLevel(petlevel);
4177 NewSummon->InitPetCreateSpells();
4178 NewSummon->InitTalentForLevel();
4180 if(NewSummon->getPetType()==SUMMON_PET)
4182 // Remove Demonic Sacrifice auras (new pet)
4183 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4184 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4186 if((*itr)->GetModifier()->m_miscvalue==2228)
4188 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4189 itr = auraClassScripts.begin();
4191 else
4192 ++itr;
4195 // generate new name for summon pet
4196 std::string new_name=objmgr.GeneratePetName(petentry);
4197 if(!new_name.empty())
4198 NewSummon->SetName(new_name);
4200 else if(NewSummon->getPetType()==HUNTER_PET)
4201 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4203 NewSummon->AIM_Initialize();
4204 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4205 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4207 map->Add((Creature*)NewSummon);
4209 m_caster->SetPet(NewSummon);
4210 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4212 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4214 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4215 ((Player*)m_caster)->PetSpellInitialize();
4219 void Spell::EffectLearnPetSpell(uint32 i)
4221 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4222 return;
4224 Player *_player = (Player*)m_caster;
4226 Pet *pet = _player->GetPet();
4227 if(!pet)
4228 return;
4229 if(!pet->isAlive())
4230 return;
4232 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4233 if(!learn_spellproto)
4234 return;
4236 pet->learnSpell(learn_spellproto->Id);
4238 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4239 _player->PetSpellInitialize();
4242 void Spell::EffectTaunt(uint32 /*i*/)
4244 // this effect use before aura Taunt apply for prevent taunt already attacking target
4245 // for spell as marked "non effective at already attacking target"
4246 if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4248 if(unitTarget->getVictim()==m_caster)
4250 SendCastResult(SPELL_FAILED_DONT_REPORT);
4251 return;
4255 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4256 if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4257 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4260 void Spell::EffectWeaponDmg(uint32 i)
4262 if(!unitTarget)
4263 return;
4264 if(!unitTarget->isAlive())
4265 return;
4267 // multiple weapon dmg effect workaround
4268 // execute only the last weapon damage
4269 // and handle all effects at once
4270 for (int j = 0; j < 3; j++)
4272 switch(m_spellInfo->Effect[j])
4274 case SPELL_EFFECT_WEAPON_DAMAGE:
4275 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4276 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4277 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4278 if (j < i) // we must calculate only at last weapon effect
4279 return;
4280 break;
4284 // some spell specific modifiers
4285 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4287 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4288 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4289 bool normalized = false;
4291 int32 spell_bonus = 0; // bonus specific for spell
4292 switch(m_spellInfo->SpellFamilyName)
4294 case SPELLFAMILY_WARRIOR:
4296 // Whirlwind, single only spell with 2 weapon white damage apply if have
4297 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4299 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4300 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4302 // Devastate bonus and sunder armor refresh
4303 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4305 uint32 stack = 0;
4306 // Need refresh all Sunder Armor auras from this caster
4307 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4308 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4310 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4311 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4312 spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
4313 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4315 (*itr).second->RefreshAura();
4316 stack = (*itr).second->GetStackAmount();
4319 if (stack)
4320 spell_bonus += stack * CalculateDamage(2, unitTarget);
4322 break;
4324 case SPELLFAMILY_ROGUE:
4326 // Mutilate (for each hand)
4327 if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4329 bool found = false;
4330 // fast check
4331 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4332 found = true;
4333 // full aura scan
4334 else
4336 Unit::AuraMap const& auras = unitTarget->GetAuras();
4337 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4339 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4341 found = true;
4342 break;
4347 if(found)
4348 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4350 break;
4352 case SPELLFAMILY_PALADIN:
4354 // Seal of Command - receive benefit from Spell Damage and Healing
4355 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4357 spellBonusNeedWeaponDamagePercentMod = true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4358 spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4359 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4361 break;
4363 case SPELLFAMILY_SHAMAN:
4365 // Skyshatter Harness item set bonus
4366 // Stormstrike
4367 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4369 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4370 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4372 // Stormstrike AP Buff
4373 if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4375 m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4376 break;
4383 int32 fixed_bonus = 0;
4384 for (int j = 0; j < 3; j++)
4386 switch(m_spellInfo->Effect[j])
4388 case SPELL_EFFECT_WEAPON_DAMAGE:
4389 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4390 fixed_bonus += CalculateDamage(j,unitTarget);
4391 break;
4392 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4393 fixed_bonus += CalculateDamage(j,unitTarget);
4394 normalized = true;
4395 break;
4396 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4397 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4399 // applied only to prev.effects fixed damage
4400 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4401 break;
4402 default:
4403 break; // not weapon damage effect, just skip
4407 // apply weaponDamagePercentMod to spell bonus also
4408 if(spellBonusNeedWeaponDamagePercentMod)
4409 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4411 // non-weapon damage
4412 int32 bonus = spell_bonus + fixed_bonus;
4414 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4415 if(bonus)
4417 UnitMods unitMod;
4418 switch(m_attackType)
4420 default:
4421 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4422 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4423 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4426 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4427 bonus = int32(bonus*weapon_total_pct);
4430 // + weapon damage with applied weapon% dmg to base weapon damage in call
4431 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4433 // total damage
4434 bonus = int32(bonus*totalDamagePercentMod);
4436 // prevent negative damage
4437 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4439 // Add melee damage bonuses (also check for negative)
4440 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4441 m_damage+= eff_damage;
4443 // Hemorrhage
4444 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4446 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4447 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4450 // Mangle (Cat): CP
4451 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4453 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4454 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4457 // take ammo
4458 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4460 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4462 // wands don't have ammo
4463 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4464 return;
4466 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4468 if(pItem->GetMaxStackCount()==1)
4470 // decrease durability for non-stackable throw weapon
4471 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4473 else
4475 // decrease items amount for stackable throw weapon
4476 uint32 count = 1;
4477 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4480 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4481 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4485 void Spell::EffectThreat(uint32 /*i*/)
4487 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4488 return;
4490 if(!unitTarget->CanHaveThreatList())
4491 return;
4493 unitTarget->AddThreat(m_caster, float(damage));
4496 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4498 if(!unitTarget)
4499 return;
4500 if(!unitTarget->isAlive())
4501 return;
4503 uint32 heal = m_caster->GetMaxHealth();
4505 m_healing+=heal;
4508 void Spell::EffectInterruptCast(uint32 /*i*/)
4510 if(!unitTarget)
4511 return;
4512 if(!unitTarget->isAlive())
4513 return;
4515 // TODO: not all spells that used this effect apply cooldown at school spells
4516 // also exist case: apply cooldown to interrupted cast only and to all spells
4517 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4519 if (unitTarget->m_currentSpells[i])
4521 // check if we can interrupt spell
4522 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4524 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4525 unitTarget->InterruptSpell(i,false);
4531 void Spell::EffectSummonObjectWild(uint32 i)
4533 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4535 GameObject* pGameObj = new GameObject;
4537 WorldObject* target = focusObject;
4538 if( !target )
4539 target = m_caster;
4541 float x,y,z;
4542 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4544 x = m_targets.m_destX;
4545 y = m_targets.m_destY;
4546 z = m_targets.m_destZ;
4548 else
4549 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4551 Map *map = target->GetMap();
4553 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4554 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
4556 delete pGameObj;
4557 return;
4560 int32 duration = GetSpellDuration(m_spellInfo);
4561 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4562 pGameObj->SetSpellId(m_spellInfo->Id);
4564 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4565 m_caster->AddGameObject(pGameObj);
4566 map->Add(pGameObj);
4568 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4570 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4572 Player *pl = (Player*)m_caster;
4573 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4574 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4576 uint32 team = ALLIANCE;
4578 if(pl->GetTeam() == team)
4579 team = HORDE;
4581 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4586 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4588 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4590 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4591 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4593 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4598 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4600 GameObject* linkedGO = new GameObject;
4601 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4602 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
4604 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4605 linkedGO->SetSpellId(m_spellInfo->Id);
4607 m_caster->AddGameObject(linkedGO);
4608 map->Add(linkedGO);
4610 else
4612 delete linkedGO;
4613 linkedGO = NULL;
4614 return;
4619 void Spell::EffectScriptEffect(uint32 effIndex)
4621 // TODO: we must implement hunter pet summon at login there (spell 6962)
4623 switch(m_spellInfo->SpellFamilyName)
4625 case SPELLFAMILY_GENERIC:
4627 switch(m_spellInfo->Id)
4629 // PX-238 Winter Wondervolt TRAP
4630 case 26275:
4632 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4634 // check presence
4635 for(int j = 0; j < 4; ++j)
4636 if(unitTarget->HasAura(spells[j],0))
4637 return;
4639 // select spell
4640 uint32 iTmpSpellId = spells[urand(0,3)];
4642 // cast
4643 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4644 return;
4646 // Bending Shinbone
4647 case 8856:
4649 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4650 return;
4652 uint32 spell_id = 0;
4653 switch(urand(1,5))
4655 case 1: spell_id = 8854; break;
4656 default: spell_id = 8855; break;
4659 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4660 return;
4662 // Brittle Armor - need remove one 24575 Brittle Armor aura
4663 case 24590:
4664 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4665 return;
4666 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4667 case 26465:
4668 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4669 return;
4670 // Orb teleport spells
4671 case 25140:
4672 case 25143:
4673 case 25650:
4674 case 25652:
4675 case 29128:
4676 case 29129:
4677 case 35376:
4678 case 35727:
4680 if(!unitTarget)
4681 return;
4683 uint32 spellid;
4684 switch(m_spellInfo->Id)
4686 case 25140: spellid = 32571; break;
4687 case 25143: spellid = 32572; break;
4688 case 25650: spellid = 30140; break;
4689 case 25652: spellid = 30141; break;
4690 case 29128: spellid = 32568; break;
4691 case 29129: spellid = 32569; break;
4692 case 35376: spellid = 25649; break;
4693 case 35727: spellid = 35730; break;
4694 default:
4695 return;
4698 unitTarget->CastSpell(unitTarget,spellid,false);
4699 return;
4701 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4702 case 22539:
4703 case 22972:
4704 case 22975:
4705 case 22976:
4706 case 22977:
4707 case 22978:
4708 case 22979:
4709 case 22980:
4710 case 22981:
4711 case 22982:
4712 case 22983:
4713 case 22984:
4714 case 22985:
4716 if(!unitTarget || !unitTarget->isAlive())
4717 return;
4719 // Onyxia Scale Cloak
4720 if(unitTarget->GetDummyAura(22683))
4721 return;
4723 // Shadow Flame
4724 m_caster->CastSpell(unitTarget, 22682, true);
4725 return;
4727 // Summon Black Qiraji Battle Tank
4728 case 26656:
4730 if(!unitTarget)
4731 return;
4733 // Prevent stacking of mounts
4734 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4736 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4737 if (unitTarget->GetAreaId() == 3428)
4738 unitTarget->CastSpell(unitTarget, 25863, false);
4739 else
4740 unitTarget->CastSpell(unitTarget, 26655, false);
4741 return;
4743 // Piccolo of the Flaming Fire
4744 case 17512:
4746 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4747 return;
4748 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4749 return;
4751 // Escape artist
4752 case 20589:
4754 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4755 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
4756 return;
4758 // Mirren's Drinking Hat
4759 case 29830:
4761 uint32 item = 0;
4762 switch ( urand(1,6) )
4764 case 1:case 2:case 3:
4765 item = 23584;break; // Loch Modan Lager
4766 case 4:case 5:
4767 item = 23585;break; // Stouthammer Lite
4768 case 6:
4769 item = 23586;break; // Aerie Peak Pale Ale
4771 if (item)
4772 DoCreateItem(effIndex,item);
4773 break;
4775 // Improved Sprint
4776 case 30918:
4778 // Removes snares and roots.
4779 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4780 Unit::AuraMap& Auras = unitTarget->GetAuras();
4781 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4783 next = iter;
4784 ++next;
4785 Aura *aur = iter->second;
4786 if (!aur->IsPositive()) //only remove negative spells
4788 // check for mechanic mask
4789 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4791 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4792 if(Auras.empty())
4793 break;
4794 else
4795 next = Auras.begin();
4799 break;
4801 // Flame Crash
4802 case 41126:
4804 if(!unitTarget)
4805 return;
4807 unitTarget->CastSpell(unitTarget, 41131, true);
4808 break;
4810 // Force Cast - Portal Effect: Sunwell Isle
4811 case 44876:
4813 if(!unitTarget)
4814 return;
4816 unitTarget->CastSpell(unitTarget, 44870, true);
4817 break;
4819 // Goblin Weather Machine
4820 case 46203:
4822 if(!unitTarget)
4823 return;
4825 uint32 spellId;
4826 switch(rand()%4)
4828 case 0: spellId = 46740; break;
4829 case 1: spellId = 46739; break;
4830 case 2: spellId = 46738; break;
4831 case 3: spellId = 46736; break;
4833 unitTarget->CastSpell(unitTarget, spellId, true);
4834 break;
4836 //5,000 Gold
4837 case 46642:
4839 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4840 return;
4842 ((Player*)unitTarget)->ModifyMoney(50000000);
4844 break;
4846 // Emblazon Runeblade
4847 case 51770:
4849 if(!unitTarget)
4850 return;
4852 unitTarget->CastSpell(unitTarget,51771,false);
4853 break;
4855 // Death Gate
4856 case 52751:
4858 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
4859 return;
4860 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4861 unitTarget->CastSpell(unitTarget, damage, false);
4862 break;
4864 case 58418: // Portal to Orgrimmar
4865 case 58420: // Portal to Stormwind
4867 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0)
4868 return;
4870 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
4871 uint32 questID = m_spellInfo->CalculateSimpleValue(1);
4873 if( ((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID) )
4874 unitTarget->CastSpell(unitTarget, spellID, true);
4876 return;
4878 // random spell learn instead placeholder
4879 case 60893: // Northrend Alchemy Research
4880 case 61177: // Northrend Inscription Research
4881 case 61288: // Minor Inscription Research
4882 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4884 if(!IsExplicitDiscoverySpell(m_spellInfo))
4886 sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id);
4887 return;
4890 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
4891 return;
4892 Player* player = (Player*)m_caster;
4894 // need replace effect 0 item by loot
4895 uint32 reagent_id = m_spellInfo->EffectItemType[0];
4897 if(!player->HasItemCount(reagent_id,1))
4898 return;
4900 // remove reagent
4901 uint32 count = 1;
4902 player->DestroyItemCount (reagent_id,count,true);
4904 // create some random items
4905 player->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
4907 // learn random explicit discovery recipe (if any)
4908 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
4909 player->learnSpell(discoveredSpell,false);
4910 return;
4913 break;
4915 case SPELLFAMILY_WARLOCK:
4917 switch(m_spellInfo->Id)
4919 // Healthstone creating spells
4920 case 6201:
4921 case 6202:
4922 case 5699:
4923 case 11729:
4924 case 11730:
4925 case 27230:
4926 case 47871:
4927 case 47878:
4929 uint32 itemtype;
4930 uint32 rank = 0;
4931 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4932 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4934 if((*i)->GetId() == 18692)
4936 rank = 1;
4937 break;
4939 else if((*i)->GetId() == 18693)
4941 rank = 2;
4942 break;
4946 static uint32 const itypes[8][3] = {
4947 { 5512,19004,19005}, // Minor Healthstone
4948 { 5511,19006,19007}, // Lesser Healthstone
4949 { 5509,19008,19009}, // Healthstone
4950 { 5510,19010,19011}, // Greater Healthstone
4951 { 9421,19012,19013}, // Major Healthstone
4952 {22103,22104,22105}, // Master Healthstone
4953 {36889,36890,36891}, // Demonic Healthstone
4954 {36892,36893,36894} // Fel Healthstone
4957 switch(m_spellInfo->Id)
4959 case 6201:
4960 itemtype=itypes[0][rank];break; // Minor Healthstone
4961 case 6202:
4962 itemtype=itypes[1][rank];break; // Lesser Healthstone
4963 case 5699:
4964 itemtype=itypes[2][rank];break; // Healthstone
4965 case 11729:
4966 itemtype=itypes[3][rank];break; // Greater Healthstone
4967 case 11730:
4968 itemtype=itypes[4][rank];break; // Major Healthstone
4969 case 27230:
4970 itemtype=itypes[5][rank];break; // Master Healthstone
4971 case 47871:
4972 itemtype=itypes[6][rank];break; // Demonic Healthstone
4973 case 47878:
4974 itemtype=itypes[7][rank];break; // Fel Healthstone
4975 default:
4976 return;
4978 DoCreateItem( effIndex, itemtype );
4979 return;
4982 break;
4984 case SPELLFAMILY_PRIEST:
4986 switch(m_spellInfo->Id)
4988 // Pain and Suffering
4989 case 47948:
4991 if (!unitTarget)
4992 return;
4993 // Refresh Shadow Word: Pain on target
4994 Unit::AuraMap& auras = unitTarget->GetAuras();
4995 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
4997 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4998 if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
4999 spellInfo->SpellFamilyFlags & 0x0000000000008000LL &&
5000 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5002 (*itr).second->RefreshAura();
5003 return;
5006 return;
5008 default:
5009 break;
5011 break;
5013 case SPELLFAMILY_HUNTER:
5015 switch(m_spellInfo->Id)
5017 // Chimera Shot
5018 case 53209:
5020 uint32 spellId = 0;
5021 int32 basePoint = 0;
5022 Unit::AuraMap& Auras = unitTarget->GetAuras();
5023 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5025 Aura *aura = (*i).second;
5026 if (aura->GetCasterGUID() != m_caster->GetGUID())
5027 continue;
5028 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5029 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5030 if (!(familyFlag & 0x000000800000C000LL))
5031 continue;
5032 // Refresh aura duration
5033 aura->RefreshAura();
5035 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5036 if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
5038 spellId = 53353; // 53353 Chimera Shot - Serpent
5039 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5041 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5042 if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
5044 spellId = 53358; // 53358 Chimera Shot - Viper
5045 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
5047 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5048 if (familyFlag & 0x0000000000008000LL)
5049 spellId = 53359; // 53359 Chimera Shot - Scorpid
5050 // ?? nothing say in spell desc (possibly need addition check)
5051 //if (familyFlag & 0x0000010000000000LL || // dot
5052 // familyFlag & 0x0000100000000000LL) // stun
5054 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5057 if (spellId)
5058 m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
5059 return;
5061 default:
5062 break;
5064 break;
5066 case SPELLFAMILY_PALADIN:
5068 // Judgement
5069 if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
5071 if(!unitTarget || !unitTarget->isAlive())
5072 return;
5073 uint32 spellId1 = 0;
5074 uint32 spellId2 = 0;
5076 // Judgement self add switch
5077 switch (m_spellInfo->Id)
5079 case 41467: break; // Judgement
5080 case 53407: spellId1 = 20184; break; // Judgement of Justice
5081 case 20271: // Judgement of Light
5082 case 57774: spellId1 = 20185; break; // Judgement of Light
5083 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5084 default:
5085 return;
5087 // all seals have aura dummy in 2 effect
5088 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5089 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5091 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5092 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5093 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5094 continue;
5095 spellId2 = (*itr)->GetModifier()->m_amount;
5096 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5097 if (!judge)
5098 continue;
5099 break;
5101 if (spellId1)
5102 m_caster->CastSpell(unitTarget, spellId1, true);
5103 if (spellId2)
5104 m_caster->CastSpell(unitTarget, spellId2, true);
5105 return;
5108 case SPELLFAMILY_POTION:
5110 switch(m_spellInfo->Id)
5112 // Dreaming Glory
5113 case 28698:
5115 if(!unitTarget)
5116 return;
5117 unitTarget->CastSpell(unitTarget, 28694, true);
5118 break;
5120 // Netherbloom
5121 case 28702:
5123 if(!unitTarget)
5124 return;
5125 // 25% chance of casting a random buff
5126 if(roll_chance_i(75))
5127 return;
5129 // triggered spells are 28703 to 28707
5130 // Note: some sources say, that there was the possibility of
5131 // receiving a debuff. However, this seems to be removed by a patch.
5132 const uint32 spellid = 28703;
5134 // don't overwrite an existing aura
5135 for(uint8 i=0; i<5; i++)
5136 if(unitTarget->HasAura(spellid+i, 0))
5137 return;
5138 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5139 break;
5142 // Nightmare Vine
5143 case 28720:
5145 if(!unitTarget)
5146 return;
5147 // 25% chance of casting Nightmare Pollen
5148 if(roll_chance_i(75))
5149 return;
5150 unitTarget->CastSpell(unitTarget, 28721, true);
5151 break;
5154 break;
5158 // normal DB scripted effect
5159 if(!unitTarget)
5160 return;
5162 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5163 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5166 void Spell::EffectSanctuary(uint32 /*i*/)
5168 if(!unitTarget)
5169 return;
5170 //unitTarget->CombatStop();
5172 unitTarget->CombatStop();
5173 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5174 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5175 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5177 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5181 void Spell::EffectAddComboPoints(uint32 /*i*/)
5183 if(!unitTarget)
5184 return;
5186 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5187 return;
5189 if(damage <= 0)
5190 return;
5192 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5195 void Spell::EffectDuel(uint32 i)
5197 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5198 return;
5200 Player *caster = (Player*)m_caster;
5201 Player *target = (Player*)unitTarget;
5203 // caster or target already have requested duel
5204 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5205 return;
5207 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5208 // Don't have to check the target's map since you cannot challenge someone across maps
5209 uint32 mapid = caster->GetMapId();
5210 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5212 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5213 return;
5216 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5217 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5219 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5220 return;
5223 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5224 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5226 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5227 return;
5230 //CREATE DUEL FLAG OBJECT
5231 GameObject* pGameObj = new GameObject;
5233 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5235 Map *map = m_caster->GetMap();
5236 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5237 map, m_caster->GetPhaseMask(),
5238 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5239 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5240 m_caster->GetPositionZ(),
5241 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1))
5243 delete pGameObj;
5244 return;
5247 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5248 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5249 int32 duration = GetSpellDuration(m_spellInfo);
5250 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5251 pGameObj->SetSpellId(m_spellInfo->Id);
5253 m_caster->AddGameObject(pGameObj);
5254 map->Add(pGameObj);
5255 //END
5257 // Send request
5258 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5259 data << pGameObj->GetGUID();
5260 data << caster->GetGUID();
5261 caster->GetSession()->SendPacket(&data);
5262 target->GetSession()->SendPacket(&data);
5264 // create duel-info
5265 DuelInfo *duel = new DuelInfo;
5266 duel->initiator = caster;
5267 duel->opponent = target;
5268 duel->startTime = 0;
5269 duel->startTimer = 0;
5270 caster->duel = duel;
5272 DuelInfo *duel2 = new DuelInfo;
5273 duel2->initiator = caster;
5274 duel2->opponent = caster;
5275 duel2->startTime = 0;
5276 duel2->startTimer = 0;
5277 target->duel = duel2;
5279 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5280 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5283 void Spell::EffectStuck(uint32 /*i*/)
5285 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5286 return;
5288 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5289 return;
5291 Player* pTarget = (Player*)unitTarget;
5293 sLog.outDebug("Spell Effect: Stuck");
5294 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());
5296 if(pTarget->isInFlight())
5297 return;
5299 // homebind location is loaded always
5300 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5302 // Stuck spell trigger Hearthstone cooldown
5303 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5304 if(!spellInfo)
5305 return;
5306 Spell spell(pTarget,spellInfo,true,0);
5307 spell.SendSpellCooldown();
5310 void Spell::EffectSummonPlayer(uint32 /*i*/)
5312 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5313 return;
5315 // Evil Twin (ignore player summon, but hide this for summoner)
5316 if(unitTarget->GetDummyAura(23445))
5317 return;
5319 float x,y,z;
5320 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5322 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5324 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5325 data << uint64(m_caster->GetGUID()); // summoner guid
5326 data << uint32(m_caster->GetZoneId()); // summoner zone
5327 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5328 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5331 static ScriptInfo generateActivateCommand()
5333 ScriptInfo si;
5334 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5335 return si;
5338 void Spell::EffectActivateObject(uint32 effect_idx)
5340 if(!gameObjTarget)
5341 return;
5343 static ScriptInfo activateCommand = generateActivateCommand();
5345 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5347 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5350 void Spell::EffectApplyGlyph(uint32 i)
5352 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5353 return;
5355 Player *player = (Player*)m_caster;
5357 // apply new one
5358 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5360 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5362 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5364 if(gp->TypeFlags != gs->TypeFlags)
5366 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5367 return; // glyph slot mismatch
5371 // remove old glyph
5372 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5374 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5376 player->RemoveAurasDueToSpell(old_gp->SpellId);
5377 player->SetGlyph(m_glyphIndex, 0);
5381 player->CastSpell(m_caster, gp->SpellId, true);
5382 player->SetGlyph(m_glyphIndex, glyph);
5387 void Spell::EffectSummonTotem(uint32 i)
5389 uint8 slot = 0;
5390 switch(m_spellInfo->EffectMiscValueB[i])
5392 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5393 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5394 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5395 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5396 // Battle standard case
5397 case SUMMON_TYPE_TOTEM: slot = 254; break;
5398 // jewelery statue case, like totem without slot
5399 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5400 default: return;
5403 if(slot < MAX_TOTEM)
5405 uint64 guid = m_caster->m_TotemSlot[slot];
5406 if(guid != 0)
5408 Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5409 if(OldTotem && OldTotem->isTotem())
5410 ((Totem*)OldTotem)->UnSummon();
5414 uint32 team = 0;
5415 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5416 team = ((Player*)m_caster)->GetTeam();
5418 Totem* pTotem = new Totem;
5420 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5421 m_spellInfo->EffectMiscValue[i], team ))
5423 delete pTotem;
5424 return;
5427 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5429 float x,y,z;
5430 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5432 // totem must be at same Z in case swimming caster and etc.
5433 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5434 z = m_caster->GetPositionZ();
5436 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5438 if(slot < MAX_TOTEM)
5439 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5441 pTotem->SetOwner(m_caster->GetGUID());
5442 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5444 int32 duration=GetSpellDuration(m_spellInfo);
5445 if(Player* modOwner = m_caster->GetSpellModOwner())
5446 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5447 pTotem->SetDuration(duration);
5449 if (damage) // if not spell info, DB values used
5451 pTotem->SetMaxHealth(damage);
5452 pTotem->SetHealth(damage);
5455 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5457 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5458 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5460 pTotem->Summon(m_caster);
5462 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5464 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5465 data << uint8(slot);
5466 data << uint64(pTotem->GetGUID());
5467 data << uint32(duration);
5468 data << uint32(m_spellInfo->Id);
5469 ((Player*)m_caster)->SendDirectMessage(&data);
5473 void Spell::EffectEnchantHeldItem(uint32 i)
5475 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5476 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5477 return;
5479 Player* item_owner = (Player*)unitTarget;
5480 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5482 if(!item )
5483 return;
5485 // must be equipped
5486 if(!item ->IsEquipped())
5487 return;
5489 if (m_spellInfo->EffectMiscValue[i])
5491 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5492 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5493 if(!duration)
5494 duration = m_currentBasePoints[i]+1; //Base points after ..
5495 if(!duration)
5496 duration = 10; //10 seconds for enchants which don't have listed duration
5498 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5499 if(!pEnchant)
5500 return;
5502 // Always go to temp enchantment slot
5503 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5505 // Enchantment will not be applied if a different one already exists
5506 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5507 return;
5509 // Apply the temporary enchantment
5510 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
5511 item_owner->ApplyEnchantment(item,slot,true);
5515 void Spell::EffectDisEnchant(uint32 /*i*/)
5517 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5518 return;
5520 Player* p_caster = (Player*)m_caster;
5521 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5522 return;
5524 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5526 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5528 // item will be removed at disenchanting end
5531 void Spell::EffectInebriate(uint32 /*i*/)
5533 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5534 return;
5536 Player *player = (Player*)unitTarget;
5537 uint16 currentDrunk = player->GetDrunkValue();
5538 uint16 drunkMod = damage * 256;
5539 if (currentDrunk + drunkMod > 0xFFFF)
5540 currentDrunk = 0xFFFF;
5541 else
5542 currentDrunk += drunkMod;
5543 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5546 void Spell::EffectFeedPet(uint32 i)
5548 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5549 return;
5551 Player *_player = (Player*)m_caster;
5553 Item* foodItem = m_targets.getItemTarget();
5554 if(!foodItem)
5555 return;
5557 Pet *pet = _player->GetPet();
5558 if(!pet)
5559 return;
5561 if(!pet->isAlive())
5562 return;
5564 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5565 if(benefit <= 0)
5566 return;
5568 uint32 count = 1;
5569 _player->DestroyItemCount(foodItem,count,true);
5570 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5572 m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5575 void Spell::EffectDismissPet(uint32 /*i*/)
5577 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5578 return;
5580 Pet* pet = m_caster->GetPet();
5582 // not let dismiss dead pet
5583 if(!pet||!pet->isAlive())
5584 return;
5586 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5589 void Spell::EffectSummonObject(uint32 i)
5591 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5593 uint8 slot = 0;
5594 switch(m_spellInfo->Effect[i])
5596 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5597 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5598 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5599 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5600 default: return;
5603 uint64 guid = m_caster->m_ObjectSlot[slot];
5604 if(guid != 0)
5606 GameObject* obj = NULL;
5607 if( m_caster )
5608 obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5610 if(obj) obj->Delete();
5611 m_caster->m_ObjectSlot[slot] = 0;
5614 GameObject* pGameObj = new GameObject;
5616 float x,y,z;
5617 // If dest location if present
5618 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5620 x = m_targets.m_destX;
5621 y = m_targets.m_destY;
5622 z = m_targets.m_destZ;
5624 // Summon in random point all other units if location present
5625 else
5626 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5628 Map *map = m_caster->GetMap();
5629 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
5630 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1))
5632 delete pGameObj;
5633 return;
5636 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5637 int32 duration = GetSpellDuration(m_spellInfo);
5638 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5639 pGameObj->SetSpellId(m_spellInfo->Id);
5640 m_caster->AddGameObject(pGameObj);
5642 map->Add(pGameObj);
5643 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5644 data << pGameObj->GetGUID();
5645 m_caster->SendMessageToSet(&data,true);
5647 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5650 void Spell::EffectResurrect(uint32 /*effIndex*/)
5652 if(!unitTarget)
5653 return;
5654 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5655 return;
5657 if(unitTarget->isAlive())
5658 return;
5659 if(!unitTarget->IsInWorld())
5660 return;
5662 switch (m_spellInfo->Id)
5664 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5665 case 8342:
5666 if (roll_chance_i(67))
5668 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5669 return;
5671 break;
5672 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5673 case 22999:
5674 if (roll_chance_i(50))
5676 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5677 return;
5679 break;
5680 default:
5681 break;
5684 Player* pTarget = ((Player*)unitTarget);
5686 if(pTarget->isRessurectRequested()) // already have one active request
5687 return;
5689 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5690 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5692 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5693 SendResurrectRequest(pTarget);
5696 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5698 if(!unitTarget || !unitTarget->isAlive())
5699 return;
5701 if( unitTarget->m_extraAttacks )
5702 return;
5704 unitTarget->m_extraAttacks = damage;
5707 void Spell::EffectParry(uint32 /*i*/)
5709 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5710 ((Player*)unitTarget)->SetCanParry(true);
5713 void Spell::EffectBlock(uint32 /*i*/)
5715 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5716 ((Player*)unitTarget)->SetCanBlock(true);
5719 void Spell::EffectMomentMove(uint32 i)
5721 if(unitTarget->isInFlight())
5722 return;
5724 if( m_spellInfo->rangeIndex== 1) //self range
5726 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5728 // before caster
5729 float fx,fy,fz;
5730 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5731 float ox,oy,oz;
5732 unitTarget->GetPosition(ox,oy,oz);
5734 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5735 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5737 fx = fx2;
5738 fy = fy2;
5739 fz = fz2;
5740 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5743 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(),unitTarget==m_caster);
5747 void Spell::EffectReputation(uint32 i)
5749 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5750 return;
5752 Player *_player = (Player*)unitTarget;
5754 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5756 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5758 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5760 if(!factionEntry)
5761 return;
5763 _player->GetReputationMgr().ModifyReputation(factionEntry,rep_change);
5766 void Spell::EffectQuestComplete(uint32 i)
5768 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5769 return;
5771 Player *_player = (Player*)m_caster;
5773 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5774 _player->AreaExploredOrEventHappens(quest_id);
5777 void Spell::EffectSelfResurrect(uint32 i)
5779 if(!unitTarget || unitTarget->isAlive())
5780 return;
5781 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5782 return;
5783 if(!unitTarget->IsInWorld())
5784 return;
5786 uint32 health = 0;
5787 uint32 mana = 0;
5789 // flat case
5790 if(damage < 0)
5792 health = uint32(-damage);
5793 mana = m_spellInfo->EffectMiscValue[i];
5795 // percent case
5796 else
5798 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5799 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5800 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5803 Player *plr = ((Player*)unitTarget);
5804 plr->ResurrectPlayer(0.0f);
5806 plr->SetHealth( health );
5807 plr->SetPower(POWER_MANA, mana );
5808 plr->SetPower(POWER_RAGE, 0 );
5809 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5811 plr->SpawnCorpseBones();
5813 plr->SaveToDB();
5816 void Spell::EffectSkinning(uint32 /*i*/)
5818 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5819 return;
5820 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5821 return;
5823 Creature* creature = (Creature*) unitTarget;
5824 int32 targetLevel = creature->getLevel();
5826 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5828 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5829 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5831 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5833 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5835 // Double chances for elites
5836 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5839 void Spell::EffectCharge(uint32 /*i*/)
5841 if(!unitTarget || !m_caster)
5842 return;
5844 float x, y, z;
5845 unitTarget->GetContactPoint(m_caster, x, y, z);
5846 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5847 ((Creature *)unitTarget)->StopMoving();
5849 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5850 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5852 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5853 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5855 // not all charge effects used in negative spells
5856 if ( !IsPositiveSpell(m_spellInfo->Id))
5857 m_caster->Attack(unitTarget,true);
5860 void Spell::EffectSummonCritter(uint32 i)
5862 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5863 return;
5864 Player* player = (Player*)m_caster;
5866 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5867 if(!pet_entry)
5868 return;
5870 Pet* old_critter = player->GetMiniPet();
5872 // for same pet just despawn
5873 if(old_critter && old_critter->GetEntry() == pet_entry)
5875 player->RemoveMiniPet();
5876 return;
5879 // despawn old pet before summon new
5880 if(old_critter)
5881 player->RemoveMiniPet();
5883 // summon new pet
5884 Pet* critter = new Pet(MINI_PET);
5886 Map *map = m_caster->GetMap();
5887 uint32 pet_number = objmgr.GeneratePetNumber();
5888 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
5889 pet_entry, pet_number))
5891 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5892 delete critter;
5893 return;
5896 float x,y,z;
5897 // If dest location if present
5898 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5900 x = m_targets.m_destX;
5901 y = m_targets.m_destY;
5902 z = m_targets.m_destZ;
5904 // Summon if dest location not present near caster
5905 else
5906 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5908 critter->Relocate(x,y,z,m_caster->GetOrientation());
5910 if(!critter->IsPositionValid())
5912 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5913 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5914 delete critter;
5915 return;
5918 critter->SetOwnerGUID(m_caster->GetGUID());
5919 critter->SetCreatorGUID(m_caster->GetGUID());
5920 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5921 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5923 critter->AIM_Initialize();
5924 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5925 critter->SetMaxHealth(1);
5926 critter->SetHealth(1);
5927 critter->SetLevel(1);
5929 // set timer for unsummon
5930 int32 duration = GetSpellDuration(m_spellInfo);
5931 if(duration > 0)
5932 critter->SetDuration(duration);
5934 std::string name = player->GetName();
5935 name.append(petTypeSuffix[critter->getPetType()]);
5936 critter->SetName( name );
5937 player->SetMiniPet(critter);
5939 map->Add((Creature*)critter);
5942 void Spell::EffectKnockBack(uint32 i)
5944 if(!unitTarget || !m_caster)
5945 return;
5947 // Effect only works on players
5948 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5949 return;
5951 float vsin = sin(m_caster->GetAngle(unitTarget));
5952 float vcos = cos(m_caster->GetAngle(unitTarget));
5954 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5955 data.append(unitTarget->GetPackGUID());
5956 data << uint32(0); // Sequence
5957 data << float(vcos); // x direction
5958 data << float(vsin); // y direction
5959 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
5960 data << float(damage/-10); // Z Movement speed (vertical)
5962 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5965 void Spell::EffectSendTaxi(uint32 i)
5967 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5968 return;
5970 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5971 if(!entry)
5972 return;
5974 std::vector<uint32> nodes;
5976 nodes.resize(2);
5977 nodes[0] = entry->from;
5978 nodes[1] = entry->to;
5980 uint32 mountid = 0;
5981 switch(m_spellInfo->Id)
5983 case 31606: //Stormcrow Amulet
5984 mountid = 17447;
5985 break;
5986 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5987 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5988 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5989 mountid = 22840;
5990 break;
5991 case 34905: //Stealth Flight
5992 mountid = 6851;
5993 break;
5994 case 45883: //Amber Ledge to Beryl Point
5995 mountid = 23524;
5996 break;
5997 case 46064: //Amber Ledge to Coldarra
5998 mountid = 6371;
5999 break;
6000 case 53335: //Stormwind Harbor Flight - Peaceful
6001 mountid = 6852;
6002 break;
6005 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
6009 void Spell::EffectPlayerPull(uint32 i)
6011 if(!unitTarget || !m_caster)
6012 return;
6014 // Effect only works on players
6015 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
6016 return;
6018 float vsin = sin(unitTarget->GetAngle(m_caster));
6019 float vcos = cos(unitTarget->GetAngle(m_caster));
6021 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
6022 data.append(unitTarget->GetPackGUID());
6023 data << uint32(0); // Sequence
6024 data << float(vcos); // x direction
6025 data << float(vsin); // y direction
6026 // Horizontal speed
6027 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
6028 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
6030 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6033 void Spell::EffectDispelMechanic(uint32 i)
6035 if(!unitTarget)
6036 return;
6038 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6040 Unit::AuraMap& Auras = unitTarget->GetAuras();
6041 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6043 next = iter;
6044 ++next;
6045 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6046 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6048 unitTarget->RemoveAurasDueToSpell(spell->Id);
6049 if(Auras.empty())
6050 break;
6051 else
6052 next = Auras.begin();
6055 return;
6058 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6060 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6061 return;
6062 Player *_player = (Player*)m_caster;
6063 Pet *pet = _player->GetPet();
6064 if(!pet)
6065 return;
6066 if(pet->isAlive())
6067 return;
6068 if(damage < 0)
6069 return;
6070 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6071 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6072 pet->setDeathState( ALIVE );
6073 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6074 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6076 pet->AIM_Initialize();
6078 _player->PetSpellInitialize();
6079 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6082 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6084 float mana = 0;
6085 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6087 if(!m_caster->m_TotemSlot[slot])
6088 continue;
6090 Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
6091 if(totem && totem->isTotem())
6093 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6094 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6095 if(spellInfo)
6096 mana += spellInfo->manaCost * damage / 100;
6097 ((Totem*)totem)->UnSummon();
6101 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
6102 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
6105 void Spell::EffectDurabilityDamage(uint32 i)
6107 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6108 return;
6110 int32 slot = m_spellInfo->EffectMiscValue[i];
6112 // FIXME: some spells effects have value -1/-2
6113 // Possibly its mean -1 all player equipped items and -2 all items
6114 if(slot < 0)
6116 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
6117 return;
6120 // invalid slot value
6121 if(slot >= INVENTORY_SLOT_BAG_END)
6122 return;
6124 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6125 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
6128 void Spell::EffectDurabilityDamagePCT(uint32 i)
6130 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6131 return;
6133 int32 slot = m_spellInfo->EffectMiscValue[i];
6135 // FIXME: some spells effects have value -1/-2
6136 // Possibly its mean -1 all player equipped items and -2 all items
6137 if(slot < 0)
6139 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
6140 return;
6143 // invalid slot value
6144 if(slot >= INVENTORY_SLOT_BAG_END)
6145 return;
6147 if(damage <= 0)
6148 return;
6150 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6151 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
6154 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6156 if(!unitTarget)
6157 return;
6159 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6162 void Spell::EffectTransmitted(uint32 effIndex)
6164 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6166 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6168 if (!goinfo)
6170 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6171 return;
6174 float fx,fy,fz;
6176 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6178 fx = m_targets.m_destX;
6179 fy = m_targets.m_destY;
6180 fz = m_targets.m_destZ;
6182 //FIXME: this can be better check for most objects but still hack
6183 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6185 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6186 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6188 else
6190 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6191 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6192 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6194 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6197 Map *cMap = m_caster->GetMap();
6199 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6201 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6202 { // but this is not proper, we really need to ignore not materialized objects
6203 SendCastResult(SPELL_FAILED_NOT_HERE);
6204 SendChannelUpdate(0);
6205 return;
6208 // replace by water level in this case
6209 fz = cMap->GetWaterLevel(fx,fy);
6211 // if gameobject is summoning object, it should be spawned right on caster's position
6212 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6214 m_caster->GetPosition(fx,fy,fz);
6217 GameObject* pGameObj = new GameObject;
6219 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6220 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
6222 delete pGameObj;
6223 return;
6226 int32 duration = GetSpellDuration(m_spellInfo);
6228 switch(goinfo->type)
6230 case GAMEOBJECT_TYPE_FISHINGNODE:
6232 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6233 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6235 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6236 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6237 int32 lastSec;
6238 switch(urand(0, 3))
6240 case 0: lastSec = 3; break;
6241 case 1: lastSec = 7; break;
6242 case 2: lastSec = 13; break;
6243 case 3: lastSec = 17; break;
6246 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6247 break;
6249 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6251 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6253 pGameObj->AddUniqueUse((Player*)m_caster);
6254 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6256 break;
6258 case GAMEOBJECT_TYPE_FISHINGHOLE:
6259 case GAMEOBJECT_TYPE_CHEST:
6260 default:
6262 break;
6266 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6268 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6270 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6271 pGameObj->SetSpellId(m_spellInfo->Id);
6273 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6274 //m_caster->AddGameObject(pGameObj);
6275 //m_ObjToDel.push_back(pGameObj);
6277 cMap->Add(pGameObj);
6279 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6280 data << uint64(pGameObj->GetGUID());
6281 m_caster->SendMessageToSet(&data,true);
6283 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6285 GameObject* linkedGO = new GameObject;
6286 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6287 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1))
6289 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6290 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6291 linkedGO->SetSpellId(m_spellInfo->Id);
6292 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6294 linkedGO->GetMap()->Add(linkedGO);
6296 else
6298 delete linkedGO;
6299 linkedGO = NULL;
6300 return;
6305 void Spell::EffectProspecting(uint32 /*i*/)
6307 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6308 return;
6310 Player* p_caster = (Player*)m_caster;
6311 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6312 return;
6314 if(itemTarget->GetCount() < 5)
6315 return;
6317 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6319 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6320 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6321 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6324 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6327 void Spell::EffectMilling(uint32 /*i*/)
6329 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6330 return;
6332 Player* p_caster = (Player*)m_caster;
6333 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6334 return;
6336 if(itemTarget->GetCount() < 5)
6337 return;
6339 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6341 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6342 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6343 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6346 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6349 void Spell::EffectSkill(uint32 /*i*/)
6351 sLog.outDebug("WORLD: SkillEFFECT");
6354 void Spell::EffectSummonDemon(uint32 i)
6356 // select center of summon position
6357 float center_x = m_targets.m_destX;
6358 float center_y = m_targets.m_destY;
6359 float center_z = m_targets.m_destZ;
6361 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6363 int32 amount = damage > 0 ? damage : 1;
6365 for(int32 count = 0; count < amount; ++count)
6367 float px, py, pz;
6368 // If dest location if present
6369 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6371 // Summon 1 unit in dest location
6372 if (count == 0)
6374 px = m_targets.m_destX;
6375 py = m_targets.m_destY;
6376 pz = m_targets.m_destZ;
6378 // Summon in random point all other units if location present
6379 else
6380 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
6382 // Summon if dest location not present near caster
6383 else
6384 m_caster->GetClosePoint(px,py,pz,3.0f);
6386 int32 duration = GetSpellDuration(m_spellInfo);
6388 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration);
6389 if (!Charmed) // something fatal, not attempt more
6390 return;
6392 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6393 Charmed->SetLevel(m_caster->getLevel());
6395 // TODO: Add damage/mana/hp according to level
6397 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6399 // Enslave demon effect, without mana cost and cooldown
6400 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6402 // Inferno effect
6403 Charmed->CastSpell(Charmed, 22703, true, 0);
6408 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6409 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6410 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6411 This is why we use a half sec delay between the visual effect and the resurrection itself */
6412 void Spell::EffectSpiritHeal(uint32 /*i*/)
6415 if(!unitTarget || unitTarget->isAlive())
6416 return;
6417 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6418 return;
6419 if(!unitTarget->IsInWorld())
6420 return;
6422 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6423 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6424 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6425 ((Player*)unitTarget)->SpawnCorpseBones();
6429 // remove insignia spell effect
6430 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6432 sLog.outDebug("Effect: SkinPlayerCorpse");
6433 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6434 return;
6436 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6439 void Spell::EffectStealBeneficialBuff(uint32 i)
6441 sLog.outDebug("Effect: StealBeneficialBuff");
6443 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6444 return;
6446 std::vector <Aura *> steal_list;
6447 // Create dispel mask by dispel type
6448 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6449 Unit::AuraMap const& auras = unitTarget->GetAuras();
6450 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6452 Aura *aur = (*itr).second;
6453 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6455 // Need check for passive? this
6456 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6457 steal_list.push_back(aur);
6460 // Ok if exist some buffs for dispel try dispel it
6461 if (!steal_list.empty())
6463 std::list < std::pair<uint32,uint64> > success_list;
6464 int32 list_size = steal_list.size();
6465 // Dispell N = damage buffs (or while exist buffs for dispel)
6466 for (int32 count=0; count < damage && list_size > 0; ++count)
6468 // Random select buff for dispel
6469 Aura *aur = steal_list[urand(0, list_size-1)];
6470 // Not use chance for steal
6471 // TODO possible need do it
6472 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6474 // Remove buff from list for prevent doubles
6475 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6477 Aura *stealed = *j;
6478 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6480 j = steal_list.erase(j);
6481 --list_size;
6483 else
6484 ++j;
6487 // Really try steal and send log
6488 if (!success_list.empty())
6490 int32 count = success_list.size();
6491 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6492 data.append(unitTarget->GetPackGUID()); // Victim GUID
6493 data.append(m_caster->GetPackGUID()); // Caster GUID
6494 data << uint32(m_spellInfo->Id); // Dispell spell id
6495 data << uint8(0); // not used
6496 data << uint32(count); // count
6497 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6499 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6500 data << uint32(spellInfo->Id); // Spell Id
6501 data << uint8(0); // 0 - steals !=0 transfers
6502 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6504 m_caster->SendMessageToSet(&data, true);
6509 void Spell::EffectKillCredit(uint32 i)
6511 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6512 return;
6514 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[i], unitTarget);
6517 void Spell::EffectQuestFail(uint32 i)
6519 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6520 return;
6522 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6525 void Spell::EffectActivateRune(uint32 eff_idx)
6527 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6528 return;
6530 Player *plr = (Player*)m_caster;
6532 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6533 return;
6535 for(uint32 j = 0; j < MAX_RUNES; ++j)
6537 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6539 plr->SetRuneCooldown(j, 0);
6544 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6546 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6547 ((Player*)unitTarget)->SetCanTitanGrip(true);
6550 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6552 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6553 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6554 return;
6556 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);