[7921] Set pet and for creature owner in Spell::EffectSummon similar other summon...
[getmangos.git] / src / game / SpellEffects.cpp
blob4a60e7620f52aa204d03732fb236a904f5cdf1cd
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 m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
285 void Spell::EffectEnvirinmentalDMG(uint32 i)
287 uint32 absorb = 0;
288 uint32 resist = 0;
290 // Note: this hack with damage replace required until GO casting not implemented
291 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
292 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
293 damage = m_spellInfo->CalculateSimpleValue(i);
295 m_caster->CalcAbsorbResist(m_caster, GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
297 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
298 if(m_caster->GetTypeId() == TYPEID_PLAYER)
299 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage);
302 void Spell::EffectSchoolDMG(uint32 effect_idx)
304 if( unitTarget && unitTarget->isAlive())
306 switch(m_spellInfo->SpellFamilyName)
308 case SPELLFAMILY_GENERIC:
310 //Gore
311 if (m_spellInfo->SpellIconID == 2269 )
313 damage+= rand()%2 ? damage : 0;
316 switch(m_spellInfo->Id) // better way to check unknown
318 // Meteor like spells (divided damage to targets)
319 case 24340: case 26558: case 28884: // Meteor
320 case 36837: case 38903: case 41276: // Meteor
321 case 26789: // Shard of the Fallen Star
322 case 31436: // Malevolent Cleave
323 case 35181: // Dive Bomb
324 case 40810: case 43267: case 43268: // Saber Lash
325 case 42384: // Brutal Swipe
326 case 45150: // Meteor Slash
328 uint32 count = 0;
329 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
330 if(ihit->effectMask & (1<<effect_idx))
331 ++count;
333 damage /= count; // divide to all targets
334 break;
336 // percent from health with min
337 case 25599: // Thundercrash
339 damage = unitTarget->GetHealth() / 2;
340 if(damage < 200)
341 damage = 200;
342 break;
344 // Intercept (warrior spell trigger)
345 case 20253:
346 case 61491:
348 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
349 break;
351 // Cataclysmic Bolt
352 case 38441:
353 damage = unitTarget->GetMaxHealth() / 2;
354 break;
356 break;
359 case SPELLFAMILY_MAGE:
361 // Arcane Blast
362 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
364 m_caster->CastSpell(m_caster, 36032, true);
366 break;
368 case SPELLFAMILY_WARRIOR:
370 // Bloodthirst
371 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000000))
373 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
375 // Shield Slam
376 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000020000000000)) && m_spellInfo->Category==1209)
377 damage += int32(m_caster->GetShieldBlockValue());
378 // Victory Rush
379 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x10000000000))
381 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
382 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
384 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
385 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
386 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
387 // Heroic Throw ${$m1+$AP*.50}
388 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000100000000))
389 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
390 // Shockwave ${$m3/100*$AP}
391 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000000))
393 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
394 if (pct > 0)
395 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
396 break;
398 break;
400 case SPELLFAMILY_WARLOCK:
402 // Incinerate Rank 1 & 2
403 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
405 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
406 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
407 damage += int32(damage*0.25f);
409 break;
411 case SPELLFAMILY_PRIEST:
413 // Shadow Word: Death - deals damage equal to damage done to caster
414 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000))
415 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
416 break;
418 case SPELLFAMILY_DRUID:
420 // Ferocious Bite
421 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000800000)) && m_spellInfo->SpellVisual[0]==6587)
423 // converts each extra point of energy into ($f1+$AP/410) additional damage
424 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
425 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
426 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
427 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
428 m_caster->SetPower(POWER_ENERGY,0);
430 // Rake
431 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000))
433 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
435 // Swipe
436 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
438 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
440 //Mangle Bonus for the initial damage of Lacerate and Rake
441 if ((m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000000000001000) && m_spellInfo->SpellIconID==494) ||
442 (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000010000000000) && m_spellInfo->SpellIconID==2246))
444 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
445 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
446 if(((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000044000000000)) && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
448 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
449 break;
452 break;
454 case SPELLFAMILY_ROGUE:
456 // Envenom
457 if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)))
459 // consume from stack dozes not more that have combo-points
460 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
462 Aura *poison = 0;
463 // Lookup for Deadly poison (only attacker applied)
464 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
465 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
466 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
467 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x10000)) &&
468 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
470 poison = *itr;
471 break;
473 // count consumed deadly poison doses at target
474 if (poison)
476 uint32 spellId = poison->GetId();
477 uint32 doses = poison->GetStackAmount();
478 if (doses > combo)
479 doses = combo;
480 for (int i=0; i< doses; i++)
481 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
482 damage *= doses;
483 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
485 // Eviscerate and Envenom Bonus Damage (item set effect)
486 if(m_caster->GetDummyAura(37169))
487 damage += ((Player*)m_caster)->GetComboPoints()*40;
490 // Eviscerate
491 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00020000)) && m_caster->GetTypeId()==TYPEID_PLAYER)
493 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
495 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
496 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
498 // Eviscerate and Envenom Bonus Damage (item set effect)
499 if(m_caster->GetDummyAura(37169))
500 damage += combo*40;
503 // Gouge
504 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000008))
506 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.21f);
508 // Instant Poison
509 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
511 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
513 // Wound Poison
514 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000010000000))
516 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
518 break;
520 case SPELLFAMILY_HUNTER:
522 // Mongoose Bite
523 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342)
525 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
527 // Counterattack
528 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0008000000000000))
530 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
532 // Arcane Shot
533 else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000800)) && m_spellInfo->maxLevel > 0)
535 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
537 // Steady Shot
538 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
540 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
541 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
543 // Explosive Trap Effect
544 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000004))
546 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
548 break;
550 case SPELLFAMILY_PALADIN:
552 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
553 if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x800000000)) && m_spellInfo->SpellIconID==2292)
555 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
556 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
557 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
558 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
559 // Get stack of Holy Vengeance on the target added by caster
560 uint32 stacks = 0;
561 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
562 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
563 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
565 stacks = (*itr)->GetStackAmount();
566 break;
568 // + 10% for each application of Holy Vengeance on the target
569 if(stacks)
570 damage += damage * stacks * 10 /100;
572 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
573 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
575 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
576 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
577 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
578 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
580 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
581 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
583 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
584 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
585 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
586 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
588 // Hammer of the Righteous
589 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))
591 // Add main hand dps * effect[2] amount
592 float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
593 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
594 damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
596 // Shield of Righteousness
597 else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0010000000000000))
599 damage+=int32(m_caster->GetShieldBlockValue());
601 break;
605 if(damage >= 0)
606 m_damage += damage;
610 void Spell::EffectDummy(uint32 i)
612 if(!unitTarget && !gameObjTarget && !itemTarget)
613 return;
615 // selection by spell family
616 switch(m_spellInfo->SpellFamilyName)
618 case SPELLFAMILY_GENERIC:
620 switch(m_spellInfo->Id )
622 case 8063: // Deviate Fish
624 if(m_caster->GetTypeId() != TYPEID_PLAYER)
625 return;
627 uint32 spell_id = 0;
628 switch(urand(1,5))
630 case 1: spell_id = 8064; break; // Sleepy
631 case 2: spell_id = 8065; break; // Invigorate
632 case 3: spell_id = 8066; break; // Shrink
633 case 4: spell_id = 8067; break; // Party Time!
634 case 5: spell_id = 8068; break; // Healthy Spirit
636 m_caster->CastSpell(m_caster, spell_id, true, NULL);
637 return;
639 case 8213: // Savory Deviate Delight
641 if(m_caster->GetTypeId() != TYPEID_PLAYER)
642 return;
644 uint32 spell_id = 0;
645 switch(urand(1,2))
647 // Flip Out - ninja
648 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
649 // Yaaarrrr - pirate
650 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
652 m_caster->CastSpell(m_caster,spell_id,true,NULL);
653 return;
655 case 8593: // Symbol of life (restore creature to life)
656 case 31225: // Shimmering Vessel (restore creature to life)
658 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
659 return;
660 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
661 return;
663 case 12162: // Deep wounds
664 case 12850: // (now good common check for this spells)
665 case 12868:
667 if(!unitTarget)
668 return;
670 float damage;
671 // DW should benefit of attack power, damage percent mods etc.
672 // TODO: check if using offhand damage is correct and if it should be divided by 2
673 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
674 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
675 else
676 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
678 switch (m_spellInfo->Id)
680 case 12850: damage *= 0.2f; break;
681 case 12162: damage *= 0.4f; break;
682 case 12868: damage *= 0.6f; break;
683 default:
684 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
685 return;
688 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
689 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
690 return;
692 case 13120: // net-o-matic
694 if(!unitTarget)
695 return;
697 uint32 spell_id = 0;
699 uint32 roll = urand(0, 99);
701 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
702 spell_id = 16566;
703 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
704 spell_id = 13119;
705 else // normal root
706 spell_id = 13099;
708 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
709 return;
711 case 13567: // Dummy Trigger
713 // can be used for different aura triggering, so select by aura
714 if(!m_triggeredByAuraSpell || !unitTarget)
715 return;
717 switch(m_triggeredByAuraSpell->Id)
719 case 26467: // Persistent Shield
720 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
721 break;
722 default:
723 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
724 break;
726 return;
728 case 15998: // Capture Worg Pup
729 case 29435: // Capture Female Kaliri Hatchling
731 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
732 return;
734 Creature* creatureTarget = (Creature*)unitTarget;
735 creatureTarget->setDeathState(JUST_DIED);
736 creatureTarget->RemoveCorpse();
737 creatureTarget->SetHealth(0); // just for nice GM-mode view
738 return;
740 case 16589: // Noggenfogger Elixir
742 if(m_caster->GetTypeId() != TYPEID_PLAYER)
743 return;
745 uint32 spell_id = 0;
746 switch(urand(1, 3))
748 case 1: spell_id = 16595; break;
749 case 2: spell_id = 16593; break;
750 default:spell_id = 16591; break;
753 m_caster->CastSpell(m_caster, spell_id, true, NULL);
754 return;
756 case 17251: // Spirit Healer Res
758 if(!unitTarget || !m_originalCaster)
759 return;
761 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
763 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
764 data << uint64(unitTarget->GetGUID());
765 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
767 return;
769 case 17271: // Test Fetid Skull
771 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
772 return;
774 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
776 m_caster->CastSpell(m_caster, spell_id, true, NULL);
777 return;
779 case 20577: // Cannibalize
780 if (unitTarget)
781 m_caster->CastSpell(m_caster, 20578, false, NULL);
782 return;
783 case 23019: // Crystal Prison Dummy DND
785 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
786 return;
788 Creature* creatureTarget = (Creature*)unitTarget;
789 if(creatureTarget->isPet())
790 return;
792 GameObject* pGameObj = new GameObject;
794 Map *map = creatureTarget->GetMap();
796 // create before death for get proper coordinates
797 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
798 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
799 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
801 delete pGameObj;
802 return;
805 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
806 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
807 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
808 pGameObj->SetSpellId(m_spellInfo->Id);
810 creatureTarget->setDeathState(JUST_DIED);
811 creatureTarget->RemoveCorpse();
812 creatureTarget->SetHealth(0); // just for nice GM-mode view
814 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
815 map->Add(pGameObj);
817 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
818 data << uint64(pGameObj->GetGUID());
819 m_caster->SendMessageToSet(&data, true);
821 return;
823 case 23074: // Arcanite Dragonling
824 if (!m_CastItem) return;
825 m_caster->CastSpell(m_caster, 19804, true, m_CastItem);
826 return;
827 case 23075: // Mithril Mechanical Dragonling
828 if (!m_CastItem) return;
829 m_caster->CastSpell(m_caster, 12749, true, m_CastItem);
830 return;
831 case 23076: // Mechanical Dragonling
832 if (!m_CastItem) return;
833 m_caster->CastSpell(m_caster, 4073, true, m_CastItem);
834 return;
835 case 23133: // Gnomish Battle Chicken
836 if (!m_CastItem) return;
837 m_caster->CastSpell(m_caster, 13166, true, m_CastItem);
838 return;
839 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
841 int32 r = irand(0, 119);
842 if ( r < 20 ) // 1/6 polymorph
843 m_caster->CastSpell(m_caster, 23444, true);
844 else if ( r < 100 ) // 4/6 evil twin
845 m_caster->CastSpell(m_caster, 23445, true);
846 else // 1/6 miss the target
847 m_caster->CastSpell(m_caster, 36902, true);
848 return;
850 case 23453: // Ultrasafe Transporter: Gadgetzan
851 if ( roll_chance_i(50) ) // success
852 m_caster->CastSpell(m_caster, 23441, true);
853 else // failure
854 m_caster->CastSpell(m_caster, 23446, true);
855 return;
856 case 23645: // Hourglass Sand
857 m_caster->RemoveAurasDueToSpell(23170);
858 return;
859 case 23725: // Gift of Life (warrior bwl trinket)
860 m_caster->CastSpell(m_caster, 23782, true);
861 m_caster->CastSpell(m_caster, 23783, true);
862 return;
863 case 25860: // Reindeer Transformation
865 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
866 return;
868 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
869 float speed = m_caster->GetSpeedRate(MOVE_RUN);
871 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
873 //5 different spells used depending on mounted speed and if mount can fly or not
874 if (flyspeed >= 4.1f)
875 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
876 else if (flyspeed >= 3.8f)
877 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
878 else if (flyspeed >= 1.6f)
879 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
880 else if (speed >= 2.0f)
881 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
882 else
883 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
885 return;
887 //case 26074: // Holiday Cheer
888 // return; -- implemented at client side
889 case 28006: // Arcane Cloaking
891 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
892 m_caster->CastSpell(unitTarget, 29294, true);
893 return;
895 case 28730: // Arcane Torrent (Mana)
897 Aura * dummy = m_caster->GetDummyAura(28734);
898 if (dummy)
900 int32 bp = damage * dummy->GetStackAmount();
901 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
902 m_caster->RemoveAurasDueToSpell(28734);
904 return;
906 case 29200: // Purify Helboar Meat
908 if( m_caster->GetTypeId() != TYPEID_PLAYER )
909 return;
911 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
913 m_caster->CastSpell(m_caster,spell_id,true,NULL);
914 return;
916 case 29858: // Soulshatter
917 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
918 m_caster->CastSpell(unitTarget,32835,true);
919 return;
920 case 30458: // Nigh Invulnerability
921 if (!m_CastItem) return;
922 if(roll_chance_i(86)) // success
923 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
924 else // backfire in 14% casts
925 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
926 return;
927 case 30507: // Poultryizer
928 if (!m_CastItem) return;
929 if(roll_chance_i(80)) // success
930 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
931 else // backfire 20%
932 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
933 return;
934 case 33060: // Make a Wish
936 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
937 return;
939 uint32 spell_id = 0;
941 switch(urand(1,5))
943 case 1: spell_id = 33053; break;
944 case 2: spell_id = 33057; break;
945 case 3: spell_id = 33059; break;
946 case 4: spell_id = 33062; break;
947 case 5: spell_id = 33064; break;
950 m_caster->CastSpell(m_caster, spell_id, true, NULL);
951 return;
953 case 35745:
955 uint32 spell_id;
956 switch(m_caster->GetAreaId())
958 case 3900: spell_id = 35743; break;
959 case 3742: spell_id = 35744; break;
960 default: return;
963 m_caster->CastSpell(m_caster, spell_id, true);
964 return;
966 case 37674: // Chaos Blast
968 if(!unitTarget)
969 return;
971 int32 basepoints0 = 100;
972 m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true);
973 return;
975 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
977 // selecting one from Bloodstained Fortune item
978 uint32 newitemid;
979 switch(urand(1, 20))
981 case 1: newitemid = 32688; break;
982 case 2: newitemid = 32689; break;
983 case 3: newitemid = 32690; break;
984 case 4: newitemid = 32691; break;
985 case 5: newitemid = 32692; break;
986 case 6: newitemid = 32693; break;
987 case 7: newitemid = 32700; break;
988 case 8: newitemid = 32701; break;
989 case 9: newitemid = 32702; break;
990 case 10: newitemid = 32703; break;
991 case 11: newitemid = 32704; break;
992 case 12: newitemid = 32705; break;
993 case 13: newitemid = 32706; break;
994 case 14: newitemid = 32707; break;
995 case 15: newitemid = 32708; break;
996 case 16: newitemid = 32709; break;
997 case 17: newitemid = 32710; break;
998 case 18: newitemid = 32711; break;
999 case 19: newitemid = 32712; break;
1000 case 20: newitemid = 32713; break;
1001 default:
1002 return;
1005 DoCreateItem(i, newitemid);
1006 return;
1008 // Demon Broiled Surprise
1009 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1010 case 43723:
1012 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1013 return;
1015 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1016 return;
1019 case 44875: // Complete Raptor Capture
1021 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1022 return;
1024 Creature* creatureTarget = (Creature*)unitTarget;
1026 creatureTarget->setDeathState(JUST_DIED);
1027 creatureTarget->RemoveCorpse();
1028 creatureTarget->SetHealth(0); // just for nice GM-mode view
1030 //cast spell Raptor Capture Credit
1031 m_caster->CastSpell(m_caster, 42337, true, NULL);
1032 return;
1034 case 34665: //Administer Antidote
1036 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1037 return;
1039 if(!unitTarget)
1040 return;
1042 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1043 if(!tempSummon)
1044 return;
1046 uint32 health = tempSummon->GetHealth();
1048 float x = tempSummon->GetPositionX();
1049 float y = tempSummon->GetPositionY();
1050 float z = tempSummon->GetPositionZ();
1051 float o = tempSummon->GetOrientation();
1052 tempSummon->UnSummon();
1054 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1055 if (!pCreature)
1056 return;
1058 pCreature->SetHealth(health);
1059 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, pCreature);
1061 if (pCreature->AI())
1062 pCreature->AI()->AttackStart(m_caster);
1064 return;
1066 case 44997: // Converting Sentry
1068 //Converted Sentry Credit
1069 m_caster->CastSpell(m_caster, 45009, true);
1070 return;
1072 case 45030: // Impale Emissary
1074 // Emissary of Hate Credit
1075 m_caster->CastSpell(m_caster, 45088, true);
1076 return;
1078 case 50243: // Teach Language
1080 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1081 return;
1083 // spell has a 1/3 chance to trigger one of the below
1084 if(roll_chance_i(66))
1085 return;
1086 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1088 // 1000001 - gnomish binary
1089 m_caster->CastSpell(m_caster, 50242, true);
1091 else
1093 // 01001000 - goblin binary
1094 m_caster->CastSpell(m_caster, 50246, true);
1097 return;
1099 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1101 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1102 return;
1104 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1105 bg->EventPlayerDroppedFlag((Player*)m_caster);
1107 m_caster->CastSpell(m_caster, 30452, true, NULL);
1108 return;
1110 case 51592: // Pickup Primordial Hatchling
1112 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1113 return;
1115 Creature* creatureTarget = (Creature*)unitTarget;
1117 creatureTarget->setDeathState(JUST_DIED);
1118 creatureTarget->RemoveCorpse();
1119 creatureTarget->SetHealth(0); // just for nice GM-mode view
1120 return;
1123 case 52308:
1125 switch(i)
1127 case 0:
1129 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
1130 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1);
1132 if (m_caster->HasAura(reqAuraID,0))
1133 m_caster->CastSpell(m_caster, spellID, true, NULL);
1134 return;
1136 case 1:
1137 return; // additional data for dummy[0]
1139 return;
1141 case 52759: // Ancestral Awakening
1142 if (!unitTarget)
1143 return;
1144 m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true);
1145 return;
1146 case 53341:
1147 case 53343:
1149 m_caster->CastSpell(m_caster, 54586, true);
1150 return;
1152 case 58418: // Portal to Orgrimmar
1153 case 58420: // Portal to Stormwind
1154 return; // implemented in EffectScript[0]
1157 //All IconID Check in there
1158 switch(m_spellInfo->SpellIconID)
1160 // Berserking (troll racial traits)
1161 case 1661:
1163 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1164 int32 melee_mod = 10;
1165 if (healthPerc <= 40)
1166 melee_mod = 30;
1167 if (healthPerc < 100 && healthPerc > 40)
1168 melee_mod = 10+(100-healthPerc)/3;
1170 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1171 int32 hasteModBasePoints1 = (5-melee_mod);
1172 int32 hasteModBasePoints2 = 5;
1174 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1175 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1176 m_caster->CastCustomSpell(m_caster, 26635, &hasteModBasePoints0, &hasteModBasePoints1, &hasteModBasePoints2, true, NULL);
1177 return;
1180 break;
1182 case SPELLFAMILY_MAGE:
1183 switch(m_spellInfo->Id )
1185 case 11958: // Cold Snap
1187 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1188 return;
1190 // immediately finishes the cooldown on Frost spells
1191 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1192 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1194 if (itr->second->state == PLAYERSPELL_REMOVED)
1195 continue;
1197 uint32 classspell = itr->first;
1198 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1200 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1201 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1202 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1204 ((Player*)m_caster)->RemoveSpellCooldown(classspell, true);
1207 return;
1209 case 32826:
1211 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1213 //Polymorph Cast Visual Rank 1
1214 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1215 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1217 return;
1220 break;
1221 case SPELLFAMILY_WARRIOR:
1222 // Charge
1223 if((m_spellInfo->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867)
1225 int32 chargeBasePoints0 = damage;
1226 m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
1227 return;
1229 // Execute
1230 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000))
1232 if(!unitTarget)
1233 return;
1235 uint32 rage = m_caster->GetPower(POWER_RAGE);
1236 // Glyph of Execution bonus
1237 if (Aura *aura = m_caster->GetDummyAura(58367))
1238 rage+=aura->GetModifier()->m_amount;
1240 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1241 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1242 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1243 m_caster->SetPower(POWER_RAGE, 0);
1244 return;
1246 // Slam
1247 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000200000))
1249 if(!unitTarget)
1250 return;
1251 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1252 m_damage+=damage;
1253 return;
1255 // Concussion Blow
1256 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000))
1258 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1259 return;
1261 switch(m_spellInfo->Id)
1263 // Warrior's Wrath
1264 case 21977:
1266 if(!unitTarget)
1267 return;
1268 m_caster->CastSpell(unitTarget, 21887, true);// spell mod
1269 return;
1271 // Last Stand
1272 case 12975:
1274 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1275 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1276 return;
1278 // Bloodthirst
1279 case 23881:
1281 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1282 return;
1285 break;
1286 case SPELLFAMILY_WARLOCK:
1287 // Life Tap
1288 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000040000))
1290 // In 303 exist spirit depend
1291 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1292 switch (m_spellInfo->Id)
1294 case 1454: damage+=spirit; break;
1295 case 1455: damage+=spirit*15/10; break;
1296 case 1456: damage+=spirit*2; break;
1297 case 11687: damage+=spirit*25/10; break;
1298 case 11688:
1299 case 11689:
1300 case 27222:
1301 case 57946: damage+=spirit*3; break;
1302 default:
1303 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1304 return;
1306 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1307 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1308 if(unitTarget && (int32(unitTarget->GetHealth()) > damage))
1310 // Shouldn't Appear in Combat Log
1311 unitTarget->ModifyHealth(-damage);
1313 int32 mana = damage;
1314 // Improved Life Tap mod
1315 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1316 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1318 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1319 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1321 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1323 // Mana Feed
1324 int32 manaFeedVal = 0;
1325 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1326 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1328 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1329 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1331 if(manaFeedVal > 0)
1333 manaFeedVal = manaFeedVal * mana / 100;
1334 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1337 else
1338 SendCastResult(SPELL_FAILED_FIZZLE);
1339 return;
1341 break;
1342 case SPELLFAMILY_PRIEST:
1343 // Penance
1344 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0080000000000000))
1346 if (!unitTarget)
1347 return;
1349 int hurt = 0;
1350 int heal = 0;
1351 switch(m_spellInfo->Id)
1353 case 47540: hurt = 47758; heal = 47757; break;
1354 case 53005: hurt = 53001; heal = 52986; break;
1355 case 53006: hurt = 53002; heal = 52987; break;
1356 case 53007: hurt = 53003; heal = 52988; break;
1357 default:
1358 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1359 return;
1361 if (m_caster->IsFriendlyTo(unitTarget))
1362 m_caster->CastSpell(unitTarget, heal, true, 0);
1363 else
1364 m_caster->CastSpell(unitTarget, hurt, true, 0);
1365 return;
1367 break;
1368 case SPELLFAMILY_DRUID:
1369 // Starfall
1370 if (m_spellInfo->SpellFamilyFlags2 & UI64LIT(0x00000100))
1372 //Shapeshifting into an animal form or mounting cancels the effect.
1373 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1375 if(m_triggeredByAuraSpell)
1376 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1377 return;
1380 //Any effect which causes you to lose control of your character will supress the starfall effect.
1381 if(m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
1382 return;
1384 switch(m_spellInfo->Id)
1386 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1387 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1388 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1389 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1390 default:
1391 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1392 return;
1395 break;
1396 case SPELLFAMILY_ROGUE:
1397 switch(m_spellInfo->Id )
1399 case 5938: // Shiv
1401 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1402 return;
1404 Player *pCaster = ((Player*)m_caster);
1406 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1407 if(!item)
1408 return;
1410 // all poison enchantments is temporary
1411 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1412 if(!enchant_id)
1413 return;
1415 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1416 if(!pEnchant)
1417 return;
1419 for (int s=0;s<3;s++)
1421 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1422 continue;
1424 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1425 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1426 continue;
1428 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1431 m_caster->CastSpell(unitTarget, 5940, true);
1432 return;
1434 case 14185: // Preparation Rogue
1436 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1437 return;
1439 //immediately finishes the cooldown on certain Rogue abilities
1440 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1441 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1443 uint32 classspell = itr->first;
1444 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1446 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
1447 ((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
1449 return;
1451 case 31231: // Cheat Death
1453 m_caster->CastSpell(m_caster, 45182, true);
1454 return;
1457 break;
1458 case SPELLFAMILY_HUNTER:
1459 // Steady Shot
1460 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x100000000))
1462 if( !unitTarget || !unitTarget->isAlive())
1463 return;
1465 bool found = false;
1467 // check dazed affect
1468 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1469 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1471 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1473 found = true;
1474 break;
1478 if(found)
1479 m_damage+= damage;
1480 return;
1483 switch(m_spellInfo->Id)
1485 case 23989: //Readiness talent
1487 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1488 return;
1490 //immediately finishes the cooldown for hunter abilities
1491 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1492 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1494 uint32 classspell = itr->first;
1495 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1497 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1498 ((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
1500 return;
1502 case 37506: // Scatter Shot
1504 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1505 return;
1507 // break Auto Shot and autohit
1508 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1509 m_caster->AttackStop();
1510 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1511 return;
1514 break;
1515 case SPELLFAMILY_PALADIN:
1516 switch(m_spellInfo->SpellIconID)
1518 case 156: // Holy Shock
1520 if(!unitTarget)
1521 return;
1523 int hurt = 0;
1524 int heal = 0;
1526 switch(m_spellInfo->Id)
1528 case 20473: hurt = 25912; heal = 25914; break;
1529 case 20929: hurt = 25911; heal = 25913; break;
1530 case 20930: hurt = 25902; heal = 25903; break;
1531 case 27174: hurt = 27176; heal = 27175; break;
1532 case 33072: hurt = 33073; heal = 33074; break;
1533 case 48824: hurt = 48822; heal = 48820; break;
1534 case 48825: hurt = 48823; heal = 48821; break;
1535 default:
1536 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1537 return;
1540 if(m_caster->IsFriendlyTo(unitTarget))
1541 m_caster->CastSpell(unitTarget, heal, true, 0);
1542 else
1543 m_caster->CastSpell(unitTarget, hurt, true, 0);
1545 return;
1547 case 561: // Judgement of command
1549 if(!unitTarget)
1550 return;
1552 uint32 spell_id = m_currentBasePoints[i]+1;
1553 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1554 if(!spell_proto)
1555 return;
1557 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1559 // decreased damage (/2) for non-stunned target.
1560 SpellModifier *mod = new SpellModifier;
1561 mod->op = SPELLMOD_DAMAGE;
1562 mod->value = -50;
1563 mod->type = SPELLMOD_PCT;
1564 mod->spellId = m_spellInfo->Id;
1565 mod->mask = UI64LIT(0x0000020000000000);
1566 mod->mask2= UI64LIT(0x0);
1568 ((Player*)m_caster)->AddSpellMod(mod, true);
1569 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
1570 // mod deleted
1571 ((Player*)m_caster)->AddSpellMod(mod, false);
1573 else
1574 m_caster->CastSpell(unitTarget, spell_proto, true, NULL);
1576 return;
1580 switch(m_spellInfo->Id)
1582 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1583 case 20187:
1585 if (!unitTarget)
1586 return;
1587 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1588 return;
1590 case 31789: // Righteous Defense (step 1)
1592 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1594 // non-standard cast requirement check
1595 if (!unitTarget || unitTarget->getAttackers().empty())
1597 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1598 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
1599 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1600 return;
1603 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1604 // Clear targets for eff 1
1605 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1606 ihit->effectMask &= ~(1<<1);
1608 // not empty (checked)
1609 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1611 // chance to be selected from list
1612 float chance = 100.0f/attackers.size();
1613 uint32 count=0;
1614 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1616 if(!roll_chance_f(chance))
1617 continue;
1618 ++count;
1619 AddUnitTarget((*aItr), 1);
1622 // now let next effect cast spell at each target.
1623 return;
1625 case 37877: // Blessing of Faith
1627 if(!unitTarget)
1628 return;
1630 uint32 spell_id = 0;
1631 switch(unitTarget->getClass())
1633 case CLASS_DRUID: spell_id = 37878; break;
1634 case CLASS_PALADIN: spell_id = 37879; break;
1635 case CLASS_PRIEST: spell_id = 37880; break;
1636 case CLASS_SHAMAN: spell_id = 37881; break;
1637 default: return; // ignore for not healing classes
1640 m_caster->CastSpell(m_caster, spell_id, true);
1641 return;
1644 break;
1645 case SPELLFAMILY_SHAMAN:
1646 //Shaman Rockbiter Weapon
1647 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1649 // TODO: use expect spell for enchant (if exist talent)
1650 // In 3.0.3 no mods present for rockbiter
1651 uint32 spell_id = 0;
1652 switch(m_spellInfo->Id)
1654 case 8017: spell_id = 36494; break; // Rank 1
1655 case 8018: spell_id = 36750; break; // Rank 2
1656 case 8019: spell_id = 36755; break; // Rank 3
1657 case 10399: spell_id = 36759; break; // Rank 4
1658 default:
1659 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW", m_spellInfo->Id);
1660 return;
1663 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1665 if(!spellInfo)
1667 sLog.outError("WORLD: unknown spell id %i", spell_id);
1668 return;
1671 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1672 return;
1674 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
1676 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(j)))
1678 if(item->IsFitToSpellRequirements(m_spellInfo))
1680 Spell *spell = new Spell(m_caster, spellInfo, true);
1682 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1683 // at calculation applied affect from Elemental Weapons talent
1684 // real enchantment damage-1
1685 spell->m_currentBasePoints[1] = damage-1;
1687 SpellCastTargets targets;
1688 targets.setItemTarget( item );
1689 spell->prepare(&targets);
1693 return;
1695 // Cleansing Totem
1696 if((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000004000000)) && m_spellInfo->SpellIconID==1673)
1698 m_caster->CastSpell(unitTarget, 52025, true);
1699 return;
1701 // Healing Stream Totem
1702 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002000))
1704 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1705 return;
1707 // Mana Spring Totem
1708 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
1710 if(unitTarget->getPowerType()!=POWER_MANA)
1711 return;
1712 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1713 return;
1715 if(m_spellInfo->Id == 39610) // Mana Tide Totem effect
1717 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1718 return;
1719 // Glyph of Mana Tide
1720 Unit *owner = m_caster->GetOwner();
1721 if (owner)
1722 if (Aura *dummy = owner->GetDummyAura(55441))
1723 damage+=dummy->GetModifier()->m_amount;
1724 // Regenerate 6% of Total Mana Every 3 secs
1725 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1726 m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
1727 return;
1729 // Lava Lash
1730 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1732 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1733 return;
1734 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1735 if (item)
1737 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1738 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1739 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1741 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1742 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000200000)) &&
1743 (*itr)->GetCastItemGUID() == item->GetGUID())
1745 m_damage += m_damage * damage / 100;
1746 return;
1750 return;
1752 break;
1753 case SPELLFAMILY_DEATHKNIGHT:
1754 // Death Coil
1755 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x002000))
1757 if(m_caster->IsFriendlyTo(unitTarget))
1759 if(unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
1760 return;
1762 int32 bp = damage * 1.5f;
1763 m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true);
1765 else
1767 int32 bp = damage;
1768 m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true);
1770 return;
1772 break;
1775 // pet auras
1776 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1778 m_caster->AddPetAura(petSpell);
1779 return;
1782 // Script based implementation. Must be used only for not good for implementation in core spell effects
1783 // So called only for not proccessed cases
1784 if(gameObjTarget)
1785 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
1786 else if(unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
1787 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
1788 else if(itemTarget)
1789 Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
1792 void Spell::EffectTriggerSpellWithValue(uint32 i)
1794 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1796 // normal case
1797 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1799 if(!spellInfo)
1801 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1802 return;
1805 int32 bp = damage;
1806 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1809 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1811 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1812 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1814 if(!spellInfo)
1816 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1817 return;
1820 finish();
1821 Spell *spell = new Spell(m_caster, spellInfo, true);
1823 SpellCastTargets targets;
1824 targets.setUnitTarget( unitTarget);
1825 spell->prepare(&targets);
1827 m_caster->SetCurrentCastedSpell(spell);
1828 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1832 void Spell::EffectForceCast(uint32 i)
1834 if( !unitTarget )
1835 return;
1837 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1839 // normal case
1840 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1842 if(!spellInfo)
1844 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1845 return;
1848 unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
1851 void Spell::EffectTriggerSpell(uint32 i)
1853 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1855 // special cases
1856 switch(triggered_spell_id)
1858 // Vanish
1859 case 18461:
1861 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1862 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1863 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1865 // if this spell is given to NPC it must handle rest by it's own AI
1866 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1867 return;
1869 // get highest rank of the Stealth spell
1870 uint32 spellId = 0;
1871 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1872 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1874 // only highest rank is shown in spell book, so simply check if shown in spell book
1875 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1876 continue;
1878 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1879 if (!spellInfo)
1880 continue;
1882 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1884 spellId = spellInfo->Id;
1885 break;
1889 // no Stealth spell found
1890 if (!spellId)
1891 return;
1893 // reset cooldown on it if needed
1894 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1895 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1897 m_caster->CastSpell(m_caster, spellId, true);
1898 return;
1900 // just skip
1901 case 23770: // Sayge's Dark Fortune of *
1902 // not exist, common cooldown can be implemented in scripts if need.
1903 return;
1904 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1905 case 29284:
1907 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1908 if (!spell)
1909 return;
1911 for (int j=0; j < spell->StackAmount; ++j)
1912 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1913 return;
1915 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1916 case 29286:
1918 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1919 if (!spell)
1920 return;
1922 for (int j=0; j < spell->StackAmount; ++j)
1923 m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1924 return;
1926 // Righteous Defense
1927 case 31980:
1929 m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID);
1930 return;
1932 // Cloak of Shadows
1933 case 35729 :
1935 Unit::AuraMap& Auras = m_caster->GetAuras();
1936 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1938 // remove all harmful spells on you...
1939 if( // ignore positive and passive auras
1940 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1941 // ignore physical auras
1942 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
1944 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1945 iter = Auras.begin();
1948 return;
1950 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1951 case 41967:
1953 if (Unit *pet = m_caster->GetPet())
1954 pet->CastSpell(pet, 28305, true);
1955 return;
1959 // normal case
1960 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1962 if(!spellInfo)
1964 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1965 return;
1968 // some triggered spells require specific equipment
1969 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1971 // main hand weapon required
1972 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1974 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1976 // skip spell if no weapon in slot or broken
1977 if(!item || item->IsBroken() )
1978 return;
1980 // skip spell if weapon not fit to triggered spell
1981 if(!item->IsFitToSpellRequirements(spellInfo))
1982 return;
1985 // offhand hand weapon required
1986 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1988 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1990 // skip spell if no weapon in slot or broken
1991 if(!item || item->IsBroken() )
1992 return;
1994 // skip spell if weapon not fit to triggered spell
1995 if(!item->IsFitToSpellRequirements(spellInfo))
1996 return;
2000 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
2001 bool instant = false;
2002 for(uint32 j = i+1; j < 3; ++j)
2004 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
2006 instant = true;
2007 break;
2011 if(instant)
2013 if (unitTarget)
2014 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
2016 else
2017 m_TriggerSpells.push_back(spellInfo);
2020 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2022 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2024 // normal case
2025 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2027 if(!spellInfo)
2029 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2030 m_spellInfo->Id,effect_idx,triggered_spell_id);
2031 return;
2034 if (m_CastItem)
2035 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2037 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2040 void Spell::EffectJump(uint32 i)
2042 if(m_caster->isInFlight())
2043 return;
2045 // Init dest coordinates
2046 float x,y,z,o;
2047 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2049 x = m_targets.m_destX;
2050 y = m_targets.m_destY;
2051 z = m_targets.m_destZ;
2053 if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
2055 // explicit cast data from client or server-side cast
2056 // some spell at client send caster
2057 Unit* pTarget = NULL;
2058 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2059 pTarget = m_targets.getUnitTarget();
2060 else if(unitTarget->getVictim())
2061 pTarget = m_caster->getVictim();
2062 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2063 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2065 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2067 else
2068 o = m_caster->GetOrientation();
2070 else if(unitTarget)
2072 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2073 o = m_caster->GetOrientation();
2075 else if(gameObjTarget)
2077 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2078 o = m_caster->GetOrientation();
2080 else
2082 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2083 return;
2086 m_caster->NearTeleportTo(x, y, z, o, true);
2089 void Spell::EffectTeleportUnits(uint32 i)
2091 if(!unitTarget || unitTarget->isInFlight())
2092 return;
2094 switch (m_spellInfo->EffectImplicitTargetB[i])
2096 case TARGET_INNKEEPER_COORDINATES:
2098 // Only players can teleport to innkeeper
2099 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2100 return;
2102 ((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);
2103 return;
2105 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2106 case TARGET_TABLE_X_Y_Z_COORDINATES:
2108 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2109 if(!st)
2111 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2112 return;
2115 if(st->target_mapId==unitTarget->GetMapId())
2116 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2117 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2118 ((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);
2119 break;
2121 case TARGET_BEHIND_VICTIM:
2123 Unit *pTarget = NULL;
2125 // explicit cast data from client or server-side cast
2126 // some spell at client send caster
2127 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2128 pTarget = m_targets.getUnitTarget();
2129 else if(unitTarget->getVictim())
2130 pTarget = unitTarget->getVictim();
2131 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2132 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2134 // Init dest coordinates
2135 float x = m_targets.m_destX;
2136 float y = m_targets.m_destY;
2137 float z = m_targets.m_destZ;
2138 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2139 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2140 return;
2142 default:
2144 // If not exist data for dest location - return
2145 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2147 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2148 return;
2150 // Init dest coordinates
2151 float x = m_targets.m_destX;
2152 float y = m_targets.m_destY;
2153 float z = m_targets.m_destZ;
2154 float orientation = unitTarget->GetOrientation();
2155 // Teleport
2156 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2157 return;
2161 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2162 switch ( m_spellInfo->Id )
2164 // Dimensional Ripper - Everlook
2165 case 23442:
2167 int32 r = irand(0, 119);
2168 if ( r >= 70 ) // 7/12 success
2170 if ( r < 100 ) // 4/12 evil twin
2171 m_caster->CastSpell(m_caster, 23445, true);
2172 else // 1/12 fire
2173 m_caster->CastSpell(m_caster, 23449, true);
2175 return;
2177 // Ultrasafe Transporter: Toshley's Station
2178 case 36941:
2180 if ( roll_chance_i(50) ) // 50% success
2182 int32 rand_eff = urand(1, 7);
2183 switch ( rand_eff )
2185 case 1:
2186 // soul split - evil
2187 m_caster->CastSpell(m_caster, 36900, true);
2188 break;
2189 case 2:
2190 // soul split - good
2191 m_caster->CastSpell(m_caster, 36901, true);
2192 break;
2193 case 3:
2194 // Increase the size
2195 m_caster->CastSpell(m_caster, 36895, true);
2196 break;
2197 case 4:
2198 // Decrease the size
2199 m_caster->CastSpell(m_caster, 36893, true);
2200 break;
2201 case 5:
2202 // Transform
2204 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2205 m_caster->CastSpell(m_caster, 36897, true);
2206 else
2207 m_caster->CastSpell(m_caster, 36899, true);
2208 break;
2210 case 6:
2211 // chicken
2212 m_caster->CastSpell(m_caster, 36940, true);
2213 break;
2214 case 7:
2215 // evil twin
2216 m_caster->CastSpell(m_caster, 23445, true);
2217 break;
2220 return;
2222 // Dimensional Ripper - Area 52
2223 case 36890:
2225 if ( roll_chance_i(50) ) // 50% success
2227 int32 rand_eff = urand(1, 4);
2228 switch ( rand_eff )
2230 case 1:
2231 // soul split - evil
2232 m_caster->CastSpell(m_caster, 36900, true);
2233 break;
2234 case 2:
2235 // soul split - good
2236 m_caster->CastSpell(m_caster, 36901, true);
2237 break;
2238 case 3:
2239 // Increase the size
2240 m_caster->CastSpell(m_caster, 36895, true);
2241 break;
2242 case 4:
2243 // Transform
2245 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2246 m_caster->CastSpell(m_caster, 36897, true);
2247 else
2248 m_caster->CastSpell(m_caster, 36899, true);
2249 break;
2253 return;
2258 void Spell::EffectApplyAura(uint32 i)
2260 if(!unitTarget)
2261 return;
2263 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2264 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2265 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2266 return;
2268 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2269 if(!caster)
2270 return;
2272 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2274 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2276 // Now Reduce spell duration using data received at spell hit
2277 int32 duration = Aur->GetAuraMaxDuration();
2278 unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel);
2279 Aur->setDiminishGroup(m_diminishGroup);
2281 // if Aura removed and deleted, do not continue.
2282 if(duration== 0 && !(Aur->IsPermanent()))
2284 delete Aur;
2285 return;
2288 if(duration != Aur->GetAuraMaxDuration())
2290 Aur->SetAuraMaxDuration(duration);
2291 Aur->SetAuraDuration(duration);
2294 bool added = unitTarget->AddAura(Aur);
2296 // Aura not added and deleted in AddAura call;
2297 if (!added)
2298 return;
2300 // found crash at character loading, broken pointer to Aur...
2301 // Aur was deleted in AddAura()...
2302 if(!Aur)
2303 return;
2305 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2306 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000000000)))
2307 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2310 void Spell::EffectUnlearnSpecialization( uint32 i )
2312 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2313 return;
2315 Player *_player = (Player*)unitTarget;
2316 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2318 _player->removeSpell(spellToUnlearn);
2320 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2323 void Spell::EffectPowerDrain(uint32 i)
2325 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2326 return;
2328 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2330 if(!unitTarget)
2331 return;
2332 if(!unitTarget->isAlive())
2333 return;
2334 if(unitTarget->getPowerType() != drain_power)
2335 return;
2336 if(damage < 0)
2337 return;
2339 uint32 curPower = unitTarget->GetPower(drain_power);
2341 //add spell damage bonus
2342 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2344 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2345 uint32 power = damage;
2346 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2347 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2349 int32 new_damage;
2350 if(curPower < power)
2351 new_damage = curPower;
2352 else
2353 new_damage = power;
2355 unitTarget->ModifyPower(drain_power,-new_damage);
2357 // Don`t restore from self drain
2358 if(drain_power == POWER_MANA && m_caster != unitTarget)
2360 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2361 if(manaMultiplier==0)
2362 manaMultiplier = 1;
2364 if(Player *modOwner = m_caster->GetSpellModOwner())
2365 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2367 int32 gain = int32(new_damage * manaMultiplier);
2369 m_caster->ModifyPower(POWER_MANA,gain);
2370 //send log
2371 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
2375 void Spell::EffectSendEvent(uint32 EffectIndex)
2378 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2380 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2381 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2384 void Spell::EffectPowerBurn(uint32 i)
2386 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2387 return;
2389 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2391 if(!unitTarget)
2392 return;
2393 if(!unitTarget->isAlive())
2394 return;
2395 if(unitTarget->getPowerType()!=powertype)
2396 return;
2397 if(damage < 0)
2398 return;
2400 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2401 if(m_spellInfo->ManaCostPercentage)
2403 uint32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2404 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2405 if(damage > maxdamage) damage = maxdamage;
2408 int32 curPower = int32(unitTarget->GetPower(powertype));
2410 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2411 uint32 power = damage;
2412 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2413 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2415 int32 new_damage = (curPower < power) ? curPower : power;
2417 unitTarget->ModifyPower(powertype, -new_damage);
2418 float multiplier = m_spellInfo->EffectMultipleValue[i];
2420 if(Player *modOwner = m_caster->GetSpellModOwner())
2421 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2423 new_damage = int32(new_damage * multiplier);
2424 m_damage += new_damage;
2427 void Spell::EffectHeal( uint32 /*i*/ )
2429 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2431 // Try to get original caster
2432 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2434 // Skip if m_originalCaster not available
2435 if (!caster)
2436 return;
2438 int32 addhealth = damage;
2440 // Vessel of the Naaru (Vial of the Sunwell trinket)
2441 if (m_spellInfo->Id == 45064)
2443 // Amount of heal - depends from stacked Holy Energy
2444 int damageAmount = 0;
2445 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2446 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
2447 if((*i)->GetId() == 45062)
2448 damageAmount+=(*i)->GetModifier()->m_amount;
2449 if (damageAmount)
2450 m_caster->RemoveAurasDueToSpell(45062);
2452 addhealth += damageAmount;
2454 // Swiftmend - consumes Regrowth or Rejuvenation
2455 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2457 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2458 // find most short by duration
2459 Aura *targetAura = NULL;
2460 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2462 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2463 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2465 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2466 targetAura = *i;
2470 if(!targetAura)
2472 sLog.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUIDLow(), unitTarget->GetTypeId());
2473 return;
2475 int idx = 0;
2476 while(idx < 3)
2478 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2479 break;
2480 idx++;
2483 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2484 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2485 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2487 addhealth += tickheal * tickcount;
2489 else
2490 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2492 m_healing+=addhealth;
2496 void Spell::EffectHealPct( uint32 /*i*/ )
2498 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2500 // Try to get original caster
2501 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2503 // Skip if m_originalCaster not available
2504 if (!caster)
2505 return;
2507 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2508 if(Player* modOwner = m_caster->GetSpellModOwner())
2509 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
2511 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2512 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2516 void Spell::EffectHealMechanical( uint32 /*i*/ )
2518 // Mechanic creature type should be correctly checked by targetCreatureType field
2519 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2521 // Try to get original caster
2522 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2524 // Skip if m_originalCaster not available
2525 if (!caster)
2526 return;
2528 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2529 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2533 void Spell::EffectHealthLeech(uint32 i)
2535 if(!unitTarget)
2536 return;
2537 if(!unitTarget->isAlive())
2538 return;
2540 if(damage < 0)
2541 return;
2543 sLog.outDebug("HealthLeech :%i", damage);
2545 float multiplier = m_spellInfo->EffectMultipleValue[i];
2547 if(Player *modOwner = m_caster->GetSpellModOwner())
2548 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2550 int32 new_damage = int32(damage*multiplier);
2551 uint32 curHealth = unitTarget->GetHealth();
2552 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage );
2553 if(curHealth < new_damage)
2554 new_damage = curHealth;
2556 if(m_caster->isAlive())
2558 new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
2559 m_caster->DealHeal(m_caster, uint32(new_damage), m_spellInfo);
2561 // m_healthLeech+=tmpvalue;
2562 // m_damage+=new_damage;
2565 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2567 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2568 return;
2570 Player* player = (Player*)unitTarget;
2572 uint32 newitemid = itemtype;
2573 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2574 if(!pProto)
2576 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2577 return;
2580 uint32 num_to_add;
2582 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2583 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2585 int32 basePoints = m_currentBasePoints[i];
2586 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2587 if (randomPoints)
2588 num_to_add = basePoints + irand(1, randomPoints);
2589 else
2590 num_to_add = basePoints + 1;
2592 else if (pProto->MaxCount == 1)
2593 num_to_add = 1;
2594 else if(player->getLevel() >= m_spellInfo->spellLevel)
2596 int32 basePoints = m_currentBasePoints[i];
2597 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2598 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2600 else
2601 num_to_add = 2;
2603 if (num_to_add < 1)
2604 num_to_add = 1;
2605 if (num_to_add > pProto->GetMaxStackSize())
2606 num_to_add = pProto->GetMaxStackSize();
2608 // init items_count to 1, since 1 item will be created regardless of specialization
2609 int items_count=1;
2610 // the chance to create additional items
2611 float additionalCreateChance=0.0f;
2612 // the maximum number of created additional items
2613 uint8 additionalMaxNum=0;
2614 // get the chance and maximum number for creating extra items
2615 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2617 // roll with this chance till we roll not to create or we create the max num
2618 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2619 ++items_count;
2622 // really will be created more items
2623 num_to_add *= items_count;
2625 // can the player store the new item?
2626 ItemPosCountVec dest;
2627 uint32 no_space = 0;
2628 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2629 if( msg != EQUIP_ERR_OK )
2631 // convert to possible store amount
2632 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2633 num_to_add -= no_space;
2634 else
2636 // if not created by another reason from full inventory or unique items amount limitation
2637 player->SendEquipError( msg, NULL, NULL );
2638 return;
2642 if(num_to_add)
2644 // create the new item and store it
2645 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2647 // was it successful? return error if not
2648 if(!pItem)
2650 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2651 return;
2654 // set the "Crafted by ..." property of the item
2655 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2656 pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
2658 // send info to the client
2659 if(pItem)
2660 player->SendNewItem(pItem, num_to_add, true, true);
2662 // we succeeded in creating at least one item, so a levelup is possible
2663 player->UpdateCraftSkill(m_spellInfo->Id);
2666 // for battleground marks send by mail if not add all expected
2667 if(no_space > 0 )
2669 BattleGroundTypeId bgType;
2670 switch(m_spellInfo->Id)
2672 case SPELL_AV_MARK_WINNER:
2673 case SPELL_AV_MARK_LOSER:
2674 bgType = BATTLEGROUND_AV;
2675 break;
2676 case SPELL_WS_MARK_WINNER:
2677 case SPELL_WS_MARK_LOSER:
2678 bgType = BATTLEGROUND_WS;
2679 break;
2680 case SPELL_AB_MARK_WINNER:
2681 case SPELL_AB_MARK_LOSER:
2682 bgType = BATTLEGROUND_AB;
2683 break;
2684 default:
2685 return;
2688 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2689 bg->SendRewardMarkByMail(player, newitemid, no_space);
2693 void Spell::EffectCreateItem(uint32 i)
2695 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2698 void Spell::EffectCreateItem2(uint32 i)
2700 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
2701 return;
2702 Player* player = (Player*)m_caster;
2704 uint32 item_id = m_spellInfo->EffectItemType[i];
2705 if(item_id)
2706 DoCreateItem(i, item_id);
2708 // special case: fake item replaced by generate using spell_loot_template
2709 if(IsLootCraftingSpell(m_spellInfo))
2711 if(item_id)
2713 if(!player->HasItemCount(item_id, 1))
2714 return;
2716 // remove reagent
2717 uint32 count = 1;
2718 player->DestroyItemCount(item_id, count, true);
2721 // create some random items
2722 player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
2726 void Spell::EffectPersistentAA(uint32 i)
2728 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2730 if(Player* modOwner = m_caster->GetSpellModOwner())
2731 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2733 int32 duration = GetSpellDuration(m_spellInfo);
2734 DynamicObject* dynObj = new DynamicObject;
2735 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))
2737 delete dynObj;
2738 return;
2740 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2741 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2742 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2743 m_caster->AddDynObject(dynObj);
2744 dynObj->GetMap()->Add(dynObj);
2747 void Spell::EffectEnergize(uint32 i)
2749 if(!unitTarget)
2750 return;
2751 if(!unitTarget->isAlive())
2752 return;
2754 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2755 return;
2757 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2759 // Some level depends spells
2760 int multiplier = 0;
2761 int level_diff = 0;
2762 switch (m_spellInfo->Id)
2764 // Restore Energy
2765 case 9512:
2766 level_diff = m_caster->getLevel() - 40;
2767 multiplier = 2;
2768 break;
2769 // Blood Fury
2770 case 24571:
2771 level_diff = m_caster->getLevel() - 60;
2772 multiplier = 10;
2773 break;
2774 // Burst of Energy
2775 case 24532:
2776 level_diff = m_caster->getLevel() - 60;
2777 multiplier = 4;
2778 break;
2779 default:
2780 break;
2783 if (level_diff > 0)
2784 damage -= multiplier * level_diff;
2786 if(damage < 0)
2787 return;
2789 if(unitTarget->GetMaxPower(power) == 0)
2790 return;
2792 unitTarget->ModifyPower(power,damage);
2793 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2795 // Mad Alchemist's Potion
2796 if (m_spellInfo->Id == 45051)
2798 // find elixirs on target
2799 uint32 elixir_mask = 0;
2800 Unit::AuraMap& Auras = unitTarget->GetAuras();
2801 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2803 uint32 spell_id = itr->second->GetId();
2804 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2805 elixir_mask |= mask;
2808 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2809 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2811 // get all available elixirs by mask and spell level
2812 std::vector<uint32> elixirs;
2813 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2814 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2816 if (itr->second & elixir_mask)
2818 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2819 continue;
2821 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2822 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2823 continue;
2825 elixirs.push_back(itr->first);
2829 if (!elixirs.empty())
2831 // cast random elixir on target
2832 uint32 rand_spell = urand(0,elixirs.size()-1);
2833 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2838 void Spell::EffectEnergisePct(uint32 i)
2840 if(!unitTarget)
2841 return;
2842 if(!unitTarget->isAlive())
2843 return;
2845 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2846 return;
2848 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2850 uint32 maxPower = unitTarget->GetMaxPower(power);
2851 if(maxPower == 0)
2852 return;
2854 uint32 gain = damage * maxPower / 100;
2855 unitTarget->ModifyPower(power, gain);
2856 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
2859 void Spell::SendLoot(uint64 guid, LootType loottype)
2861 Player* player = (Player*)m_caster;
2862 if (!player)
2863 return;
2865 if (gameObjTarget)
2867 if (Script->GOHello(player, gameObjTarget))
2868 return;
2870 switch (gameObjTarget->GetGoType())
2872 case GAMEOBJECT_TYPE_DOOR:
2873 case GAMEOBJECT_TYPE_BUTTON:
2874 gameObjTarget->UseDoorOrButton();
2875 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2876 return;
2878 case GAMEOBJECT_TYPE_QUESTGIVER:
2879 // start or end quest
2880 player->PrepareQuestMenu(guid);
2881 player->SendPreparedQuest(guid);
2882 return;
2884 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2885 // triggering linked GO
2886 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2887 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2888 return;
2890 case GAMEOBJECT_TYPE_GOOBER:
2891 // goober_scripts can be triggered if the player don't have the quest
2892 if (gameObjTarget->GetGOInfo()->goober.eventId)
2894 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2895 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2898 // cast goober spell
2899 if (gameObjTarget->GetGOInfo()->goober.questId)
2900 ///Quest require to be active for GO using
2901 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2902 return;
2904 gameObjTarget->AddUniqueUse(player);
2905 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2907 //TODO? Objective counting called without spell check but with quest objective check
2908 // if send spell id then this line will duplicate to spell casting call (double counting)
2909 // So we or have this line and not required in quest_template have reqSpellIdN
2910 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2911 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2913 // triggering linked GO
2914 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2915 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2917 return;
2919 case GAMEOBJECT_TYPE_CHEST:
2920 // TODO: possible must be moved to loot release (in different from linked triggering)
2921 if (gameObjTarget->GetGOInfo()->chest.eventId)
2923 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2924 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2927 // triggering linked GO
2928 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2929 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2931 // Don't return, let loots been taken
2932 default:
2933 break;
2937 // Send loot
2938 player->SendLoot(guid, loottype);
2941 void Spell::EffectOpenLock(uint32 effIndex)
2943 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2945 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2946 return;
2949 Player* player = (Player*)m_caster;
2951 uint32 lockId = 0;
2952 uint64 guid = 0;
2954 // Get lockId
2955 if(gameObjTarget)
2957 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2958 // Arathi Basin banner opening !
2959 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2960 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2962 //CanUseBattleGroundObject() already called in CheckCast()
2963 // in battleground check
2964 if(BattleGround *bg = player->GetBattleGround())
2966 // check if it's correct bg
2967 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2968 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2969 return;
2972 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2974 //CanUseBattleGroundObject() already called in CheckCast()
2975 // in battleground check
2976 if(BattleGround *bg = player->GetBattleGround())
2978 if(bg->GetTypeID() == BATTLEGROUND_EY)
2979 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2980 return;
2983 lockId = gameObjTarget->GetLockId();
2984 guid = gameObjTarget->GetGUID();
2986 else if(itemTarget)
2988 lockId = itemTarget->GetProto()->LockID;
2989 guid = itemTarget->GetGUID();
2991 else
2993 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2994 return;
2997 SkillType skillId = SKILL_NONE;
2998 int32 reqSkillValue = 0;
2999 int32 skillValue;
3001 SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue);
3002 if(res != SPELL_CAST_OK)
3004 SendCastResult(res);
3005 return;
3008 SendLoot(guid, LOOT_SKINNING);
3010 // not allow use skill grow at item base open
3011 if(!m_CastItem && skillId != SKILL_NONE)
3013 // update skill if really known
3014 if(uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3016 if(gameObjTarget)
3018 // Allow one skill-up until respawned
3019 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3020 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue) )
3021 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3023 else if(itemTarget)
3025 // Do one skill-up
3026 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3032 void Spell::EffectSummonChangeItem(uint32 i)
3034 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3035 return;
3037 Player *player = (Player*)m_caster;
3039 // applied only to using item
3040 if(!m_CastItem)
3041 return;
3043 // ... only to item in own inventory/bank/equip_slot
3044 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3045 return;
3047 uint32 newitemid = m_spellInfo->EffectItemType[i];
3048 if(!newitemid)
3049 return;
3051 uint16 pos = m_CastItem->GetPos();
3053 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3054 if( !pNewItem )
3055 return;
3057 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3059 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3060 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3063 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3065 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3066 player->DurabilityLoss(pNewItem, loosePercent);
3069 if( player->IsInventoryPos( pos ) )
3071 ItemPosCountVec dest;
3072 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3073 if( msg == EQUIP_ERR_OK )
3075 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3077 // prevent crash at access and unexpected charges counting with item update queue corrupt
3078 if(m_CastItem==m_targets.getItemTarget())
3079 m_targets.setItemTarget(NULL);
3081 m_CastItem = NULL;
3083 player->StoreItem( dest, pNewItem, true);
3084 return;
3087 else if( player->IsBankPos ( pos ) )
3089 ItemPosCountVec dest;
3090 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3091 if( msg == EQUIP_ERR_OK )
3093 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3095 // prevent crash at access and unexpected charges counting with item update queue corrupt
3096 if(m_CastItem==m_targets.getItemTarget())
3097 m_targets.setItemTarget(NULL);
3099 m_CastItem = NULL;
3101 player->BankItem( dest, pNewItem, true);
3102 return;
3105 else if( player->IsEquipmentPos ( pos ) )
3107 uint16 dest;
3108 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3109 if( msg == EQUIP_ERR_OK )
3111 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
3113 // prevent crash at access and unexpected charges counting with item update queue corrupt
3114 if(m_CastItem==m_targets.getItemTarget())
3115 m_targets.setItemTarget(NULL);
3117 m_CastItem = NULL;
3119 player->EquipItem( dest, pNewItem, true);
3120 player->AutoUnequipOffhandIfNeed();
3121 return;
3125 // fail
3126 delete pNewItem;
3129 void Spell::EffectOpenSecretSafe(uint32 i)
3131 EffectOpenLock(i); //no difference for now
3134 void Spell::EffectProficiency(uint32 /*i*/)
3136 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3137 return;
3138 Player *p_target = (Player*)unitTarget;
3140 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3141 if(m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
3143 p_target->AddWeaponProficiency(subClassMask);
3144 p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
3146 if(m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
3148 p_target->AddArmorProficiency(subClassMask);
3149 p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
3153 void Spell::EffectApplyAreaAura(uint32 i)
3155 if(!unitTarget)
3156 return;
3157 if(!unitTarget->isAlive())
3158 return;
3160 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3161 unitTarget->AddAura(Aur);
3164 void Spell::EffectSummonType(uint32 i)
3166 switch(m_spellInfo->EffectMiscValueB[i])
3168 case SUMMON_TYPE_GUARDIAN:
3169 case SUMMON_TYPE_POSESSED:
3170 case SUMMON_TYPE_POSESSED2:
3171 case SUMMON_TYPE_FORCE_OF_NATURE:
3172 case SUMMON_TYPE_GUARDIAN2:
3173 EffectSummonGuardian(i);
3174 break;
3175 case SUMMON_TYPE_WILD:
3176 EffectSummonWild(i);
3177 break;
3178 case SUMMON_TYPE_DEMON:
3179 EffectSummonDemon(i);
3180 break;
3181 case SUMMON_TYPE_SUMMON:
3182 EffectSummon(i);
3183 break;
3184 case SUMMON_TYPE_CRITTER:
3185 case SUMMON_TYPE_CRITTER2:
3186 case SUMMON_TYPE_CRITTER3:
3187 EffectSummonCritter(i);
3188 break;
3189 case SUMMON_TYPE_TOTEM_SLOT1:
3190 case SUMMON_TYPE_TOTEM_SLOT2:
3191 case SUMMON_TYPE_TOTEM_SLOT3:
3192 case SUMMON_TYPE_TOTEM_SLOT4:
3193 case SUMMON_TYPE_TOTEM:
3194 EffectSummonTotem(i);
3195 break;
3196 case SUMMON_TYPE_UNKNOWN1:
3197 case SUMMON_TYPE_UNKNOWN2:
3198 case SUMMON_TYPE_UNKNOWN3:
3199 case SUMMON_TYPE_UNKNOWN4:
3200 case SUMMON_TYPE_UNKNOWN5:
3201 break;
3202 default:
3203 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3204 break;
3208 void Spell::EffectSummon(uint32 i)
3210 if(m_caster->GetPetGUID())
3211 return;
3213 if(!unitTarget)
3214 return;
3215 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3216 if(!pet_entry)
3217 return;
3218 uint32 level = m_caster->getLevel();
3219 Pet* spawnCreature = new Pet(SUMMON_PET);
3221 if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3223 // set timer for unsummon
3224 int32 duration = GetSpellDuration(m_spellInfo);
3225 if(duration > 0)
3226 spawnCreature->SetDuration(duration);
3228 return;
3231 Map *map = m_caster->GetMap();
3232 uint32 pet_number = objmgr.GeneratePetNumber();
3233 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
3234 m_spellInfo->EffectMiscValue[i], pet_number))
3236 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3237 delete spawnCreature;
3238 return;
3241 // Summon in dest location
3242 float x, y, z;
3243 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3245 x = m_targets.m_destX;
3246 y = m_targets.m_destY;
3247 z = m_targets.m_destZ;
3249 else
3250 m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectSize());
3252 spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation());
3254 if(!spawnCreature->IsPositionValid())
3256 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3257 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3258 delete spawnCreature;
3259 return;
3262 // set timer for unsummon
3263 int32 duration = GetSpellDuration(m_spellInfo);
3264 if(duration > 0)
3265 spawnCreature->SetDuration(duration);
3267 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3268 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3269 spawnCreature->setPowerType(POWER_MANA);
3270 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3271 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3272 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3273 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3274 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3275 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3276 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3277 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3278 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3280 spawnCreature->InitStatsForLevel(level);
3282 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3284 spawnCreature->AIM_Initialize();
3285 spawnCreature->InitPetCreateSpells();
3286 spawnCreature->InitLevelupSpellsForLevel();
3287 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3288 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3290 std::string name = m_caster->GetName();
3291 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3292 spawnCreature->SetName( name );
3294 map->Add((Creature*)spawnCreature);
3296 m_caster->SetPet(spawnCreature);
3298 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3300 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3301 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3302 ((Player*)m_caster)->PetSpellInitialize();
3306 void Spell::EffectLearnSpell(uint32 i)
3308 if(!unitTarget)
3309 return;
3311 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3313 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3314 EffectLearnPetSpell(i);
3316 return;
3319 Player *player = (Player*)unitTarget;
3321 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3322 player->learnSpell(spellToLearn,false);
3324 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3327 void Spell::EffectDispel(uint32 i)
3329 if(!unitTarget)
3330 return;
3332 // Fill possible dispell list
3333 std::vector <Aura *> dispel_list;
3335 // Create dispel mask by dispel type
3336 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3337 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3338 Unit::AuraMap const& auras = unitTarget->GetAuras();
3339 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3341 Aura *aur = (*itr).second;
3342 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3344 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3346 bool positive = true;
3347 if (!aur->IsPositive())
3348 positive = false;
3349 else
3350 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3352 // do not remove positive auras if friendly target
3353 // negative auras if non-friendly target
3354 if(positive == unitTarget->IsFriendlyTo(m_caster))
3355 continue;
3357 // Add aura to dispel list
3358 dispel_list.push_back(aur);
3361 // Ok if exist some buffs for dispel try dispel it
3362 if (!dispel_list.empty())
3364 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3365 std::list < uint32 > fail_list; // spell_id
3366 int32 list_size = dispel_list.size();
3367 // Dispell N = damage buffs (or while exist buffs for dispel)
3368 for (int32 count=0; count < damage && list_size > 0; ++count)
3370 // Random select buff for dispel
3371 Aura *aur = dispel_list[urand(0, list_size-1)];
3373 SpellEntry const* spellInfo = aur->GetSpellProto();
3374 // Base dispel chance
3375 // TODO: possible chance depend from spell level??
3376 int32 miss_chance = 0;
3377 // Apply dispel mod from aura caster
3378 if (Unit *caster = aur->GetCaster())
3380 if ( Player* modOwner = caster->GetSpellModOwner() )
3381 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3383 // Try dispel
3384 if (roll_chance_i(miss_chance))
3385 fail_list.push_back(aur->GetId());
3386 else
3387 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3388 // Remove buff from list for prevent doubles
3389 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3391 Aura *dispeled = *j;
3392 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3394 j = dispel_list.erase(j);
3395 --list_size;
3397 else
3398 ++j;
3401 // Send success log and really remove auras
3402 if (!success_list.empty())
3404 int32 count = success_list.size();
3405 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3406 data.append(unitTarget->GetPackGUID()); // Victim GUID
3407 data.append(m_caster->GetPackGUID()); // Caster GUID
3408 data << uint32(m_spellInfo->Id); // Dispell spell id
3409 data << uint8(0); // not used
3410 data << uint32(count); // count
3411 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3413 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3414 data << uint32(spellInfo->Id); // Spell Id
3415 data << uint8(0); // 0 - dispeled !=0 cleansed
3416 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3418 m_caster->SendMessageToSet(&data, true);
3420 // On succes dispel
3421 // Devour Magic
3422 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3424 uint32 heal_spell = 0;
3425 switch (m_spellInfo->Id)
3427 case 19505: heal_spell = 19658; break;
3428 case 19731: heal_spell = 19732; break;
3429 case 19734: heal_spell = 19733; break;
3430 case 19736: heal_spell = 19735; break;
3431 case 27276: heal_spell = 27278; break;
3432 case 27277: heal_spell = 27279; break;
3433 default:
3434 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3435 break;
3437 if (heal_spell)
3438 m_caster->CastSpell(m_caster, heal_spell, true);
3441 // Send fail log to client
3442 if (!fail_list.empty())
3444 // Failed to dispell
3445 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3446 data << uint64(m_caster->GetGUID()); // Caster GUID
3447 data << uint64(unitTarget->GetGUID()); // Victim GUID
3448 data << uint32(m_spellInfo->Id); // Dispell spell id
3449 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3450 data << uint32(*j); // Spell Id
3451 m_caster->SendMessageToSet(&data, true);
3456 void Spell::EffectDualWield(uint32 /*i*/)
3458 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3459 ((Player*)unitTarget)->SetCanDualWield(true);
3462 void Spell::EffectPull(uint32 /*i*/)
3464 // TODO: create a proper pull towards distract spell center for distract
3465 sLog.outDebug("WORLD: Spell Effect DUMMY");
3468 void Spell::EffectDistract(uint32 /*i*/)
3470 // Check for possible target
3471 if (!unitTarget || unitTarget->isInCombat())
3472 return;
3474 // target must be OK to do this
3475 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3476 return;
3478 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3480 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3482 // For players just turn them
3483 WorldPacket data;
3484 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3485 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3486 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3488 else
3490 // Set creature Distracted, Stop it, And turn it
3491 unitTarget->SetOrientation(angle);
3492 unitTarget->StopMoving();
3493 unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILISECONDS);
3497 void Spell::EffectPickPocket(uint32 /*i*/)
3499 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3500 return;
3502 // victim must be creature and attackable
3503 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3504 return;
3506 // victim have to be alive and humanoid or undead
3507 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3509 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3511 if (chance > irand(0, 19))
3513 // Stealing successful
3514 //sLog.outDebug("Sending loot from pickpocket");
3515 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3517 else
3519 // Reveal action + get attack
3520 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3521 if (((Creature*)unitTarget)->AI())
3522 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
3527 void Spell::EffectAddFarsight(uint32 i)
3529 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3530 int32 duration = GetSpellDuration(m_spellInfo);
3531 DynamicObject* dynObj = new DynamicObject;
3532 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))
3534 delete dynObj;
3535 return;
3537 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3538 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3539 m_caster->AddDynObject(dynObj);
3540 dynObj->GetMap()->Add(dynObj);
3541 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3542 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3545 void Spell::EffectSummonWild(uint32 i)
3547 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3548 if(!creature_entry)
3549 return;
3551 uint32 level = m_caster->getLevel();
3553 // level of creature summoned using engineering item based at engineering skill level
3554 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3556 ItemPrototype const *proto = m_CastItem->GetProto();
3557 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3559 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3560 if(skill202)
3562 level = skill202/5;
3567 // select center of summon position
3568 float center_x = m_targets.m_destX;
3569 float center_y = m_targets.m_destY;
3570 float center_z = m_targets.m_destZ;
3572 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3574 int32 amount = damage > 0 ? damage : 1;
3576 for(int32 count = 0; count < amount; ++count)
3578 float px, py, pz;
3579 // If dest location if present
3580 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3582 // Summon 1 unit in dest location
3583 if (count == 0)
3585 px = m_targets.m_destX;
3586 py = m_targets.m_destY;
3587 pz = m_targets.m_destZ;
3589 // Summon in random point all other units if location present
3590 else
3591 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3593 // Summon if dest location not present near caster
3594 else
3595 m_caster->GetClosePoint(px, py, pz, 3.0f);
3597 int32 duration = GetSpellDuration(m_spellInfo);
3599 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3601 m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration);
3605 void Spell::EffectSummonGuardian(uint32 i)
3607 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3608 if(!pet_entry)
3609 return;
3611 // Jewelery statue case (totem like)
3612 if(m_spellInfo->SpellIconID == 2056)
3614 EffectSummonTotem(i);
3615 return;
3618 // set timer for unsummon
3619 int32 duration = GetSpellDuration(m_spellInfo);
3621 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3622 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3623 // so this code hack in fact
3624 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo) == 0) )
3625 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3626 return; // find old guardian, ignore summon
3628 // in another case summon new
3629 uint32 level = m_caster->getLevel();
3631 // level of pet summoned using engineering item based at engineering skill level
3632 if(m_caster->GetTypeId() == TYPEID_PLAYER && m_CastItem)
3634 ItemPrototype const *proto = m_CastItem->GetProto();
3635 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3637 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3638 if(skill202)
3640 level = skill202 / 5;
3645 // select center of summon position
3646 float center_x = m_targets.m_destX;
3647 float center_y = m_targets.m_destY;
3648 float center_z = m_targets.m_destZ;
3650 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3652 int32 amount = damage > 0 ? damage : 1;
3654 for(int32 count = 0; count < amount; ++count)
3656 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3658 Map *map = m_caster->GetMap();
3659 uint32 pet_number = objmgr.GeneratePetNumber();
3660 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3661 m_spellInfo->EffectMiscValue[i], pet_number))
3663 sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[i]);
3664 delete spawnCreature;
3665 return;
3668 float px, py, pz;
3669 // If dest location if present
3670 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3672 // Summon 1 unit in dest location
3673 if (count == 0)
3675 px = m_targets.m_destX;
3676 py = m_targets.m_destY;
3677 pz = m_targets.m_destZ;
3679 // Summon in random point all other units if location present
3680 else
3681 m_caster->GetRandomPoint(center_x, center_y, center_z, radius, px, py, pz);
3683 // Summon if dest location not present near caster
3684 else
3685 m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectSize());
3687 spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation());
3689 if(!spawnCreature->IsPositionValid())
3691 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3692 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3693 delete spawnCreature;
3694 return;
3697 if(duration > 0)
3698 spawnCreature->SetDuration(duration);
3700 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3701 spawnCreature->setPowerType(POWER_MANA);
3702 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3703 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3704 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3705 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3706 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3707 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3708 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3710 spawnCreature->InitStatsForLevel(level);
3711 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3713 spawnCreature->AIM_Initialize();
3715 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3716 ((Player*)m_caster)->AddGuardian(spawnCreature);
3718 map->Add((Creature*)spawnCreature);
3722 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3724 if(!unitTarget)
3725 return;
3727 if(unitTarget->isInFlight())
3728 return;
3730 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3732 float fx, fy, fz;
3733 m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
3735 unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget==m_caster);
3738 void Spell::EffectLearnSkill(uint32 i)
3740 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3741 return;
3743 if(damage < 0)
3744 return;
3746 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3747 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3748 ((Player*)unitTarget)->SetSkill(skillid, skillval ? skillval : 1, damage * 75);
3751 void Spell::EffectAddHonor(uint32 /*i*/)
3753 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3754 return;
3756 // not scale value for item based reward (/10 value expected)
3757 if(m_CastItem)
3759 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage / 10);
3760 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());
3761 return;
3764 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3765 if( damage <= 50)
3767 uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
3768 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
3769 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
3771 else
3773 //maybe we have correct honor_gain in damage already
3774 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3775 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3779 void Spell::EffectTradeSkill(uint32 /*i*/)
3781 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3782 return;
3783 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3784 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3785 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3788 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
3790 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3791 return;
3792 if (!itemTarget)
3793 return;
3795 Player* p_caster = (Player*)m_caster;
3797 // not grow at item use at item case
3798 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3800 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3801 if (!enchant_id)
3802 return;
3804 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3805 if(!pEnchant)
3806 return;
3808 // item can be in trade slot and have owner diff. from caster
3809 Player* item_owner = itemTarget->GetOwner();
3810 if(!item_owner)
3811 return;
3813 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3815 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3816 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3817 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3818 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3821 // remove old enchanting before applying new if equipped
3822 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3824 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3826 // add new enchanting if equipped
3827 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3830 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
3832 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3833 return;
3834 if (!itemTarget)
3835 return;
3837 Player* p_caster = (Player*)m_caster;
3839 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3840 if (!enchant_id)
3841 return;
3843 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3844 if(!pEnchant)
3845 return;
3847 // support only enchantings with add socket in this slot
3849 bool add_socket = false;
3850 for(int i = 0; i < 3; ++i)
3852 if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
3854 add_socket = true;
3855 break;
3858 if(!add_socket)
3860 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.",
3861 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
3862 return;
3866 // item can be in trade slot and have owner diff. from caster
3867 Player* item_owner = itemTarget->GetOwner();
3868 if(!item_owner)
3869 return;
3871 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3873 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3874 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3875 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3876 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3879 // remove old enchanting before applying new if equipped
3880 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
3882 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3884 // add new enchanting if equipped
3885 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
3888 void Spell::EffectEnchantItemTmp(uint32 i)
3890 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3891 return;
3893 Player* p_caster = (Player*)m_caster;
3895 if(!itemTarget)
3896 return;
3898 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3900 // Shaman Rockbiter Weapon
3901 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3903 int32 enchnting_damage = m_currentBasePoints[1]+1;
3905 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3906 // with already applied percent bonus from Elemental Weapons talent
3907 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3908 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3909 switch(enchnting_damage)
3911 // Rank 1
3912 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3913 // Rank 2
3914 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3915 case 5: enchant_id = 3025; break; // 20%
3916 // Rank 3
3917 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3918 case 7: enchant_id = 3027; break; // 20%
3919 // Rank 4
3920 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3921 case 10: enchant_id = 503; break; // 14%
3922 case 11: enchant_id = 3031; break; // 20%
3923 // Rank 5
3924 case 15: enchant_id = 3035; break; // 0%
3925 case 16: enchant_id = 1663; break; // 7%
3926 case 17: enchant_id = 3033; break; // 14%
3927 case 18: enchant_id = 3034; break; // 20%
3928 // Rank 6
3929 case 28: enchant_id = 3038; break; // 0%
3930 case 29: enchant_id = 683; break; // 7%
3931 case 31: enchant_id = 3036; break; // 14%
3932 case 33: enchant_id = 3037; break; // 20%
3933 // Rank 7
3934 case 40: enchant_id = 3041; break; // 0%
3935 case 42: enchant_id = 1664; break; // 7%
3936 case 45: enchant_id = 3039; break; // 14%
3937 case 48: enchant_id = 3040; break; // 20%
3938 // Rank 8
3939 case 49: enchant_id = 3044; break; // 0%
3940 case 52: enchant_id = 2632; break; // 7%
3941 case 55: enchant_id = 3042; break; // 14%
3942 case 58: enchant_id = 3043; break; // 20%
3943 // Rank 9
3944 case 62: enchant_id = 2633; break; // 0%
3945 case 66: enchant_id = 3018; break; // 7%
3946 case 70: enchant_id = 3019; break; // 14%
3947 case 74: enchant_id = 3020; break; // 20%
3948 default:
3949 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3950 return;
3954 if (!enchant_id)
3956 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3957 return;
3960 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3961 if(!pEnchant)
3963 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3964 return;
3967 // select enchantment duration
3968 uint32 duration;
3970 // rogue family enchantments exception by duration
3971 if(m_spellInfo->Id == 38615)
3972 duration = 1800; // 30 mins
3973 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3974 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
3975 duration = 3600; // 1 hour
3976 // shaman family enchantments
3977 else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
3978 duration = 1800; // 30 mins
3979 // other cases with this SpellVisual already selected
3980 else if(m_spellInfo->SpellVisual[0] == 215)
3981 duration = 1800; // 30 mins
3982 // some fishing pole bonuses
3983 else if(m_spellInfo->SpellVisual[0] == 563)
3984 duration = 600; // 10 mins
3985 // shaman rockbiter enchantments
3986 else if(m_spellInfo->SpellVisual[0] == 0)
3987 duration = 1800; // 30 mins
3988 else if(m_spellInfo->Id == 29702)
3989 duration = 300; // 5 mins
3990 else if(m_spellInfo->Id == 37360)
3991 duration = 300; // 5 mins
3992 // default case
3993 else
3994 duration = 3600; // 1 hour
3996 // item can be in trade slot and have owner diff. from caster
3997 Player* item_owner = itemTarget->GetOwner();
3998 if(!item_owner)
3999 return;
4001 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4003 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4004 p_caster->GetName(), p_caster->GetSession()->GetAccountId(),
4005 itemTarget->GetProto()->Name1, itemTarget->GetEntry(),
4006 item_owner->GetName(), item_owner->GetSession()->GetAccountId());
4009 // remove old enchanting before applying new if equipped
4010 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false);
4012 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
4014 // add new enchanting if equipped
4015 item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
4018 void Spell::EffectTameCreature(uint32 /*i*/)
4020 if(m_caster->GetPetGUID())
4021 return;
4023 if(!unitTarget)
4024 return;
4026 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4027 return;
4029 Creature* creatureTarget = (Creature*)unitTarget;
4031 if(creatureTarget->isPet())
4032 return;
4034 if(m_caster->getClass() != CLASS_HUNTER)
4035 return;
4037 // cast finish successfully
4038 //SendChannelUpdate(0);
4039 finish();
4041 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
4043 // kill original creature
4044 creatureTarget->setDeathState(JUST_DIED);
4045 creatureTarget->RemoveCorpse();
4046 creatureTarget->SetHealth(0); // just for nice GM-mode view
4048 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4050 // prepare visual effect for levelup
4051 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4053 // add to world
4054 pet->GetMap()->Add((Creature*)pet);
4056 // visual effect for levelup
4057 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4059 // caster have pet now
4060 m_caster->SetPet(pet);
4062 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4064 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4065 ((Player*)m_caster)->PetSpellInitialize();
4069 void Spell::EffectSummonPet(uint32 i)
4071 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4073 Pet *OldSummon = m_caster->GetPet();
4075 // if pet requested type already exist
4076 if( OldSummon )
4078 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4080 // pet in corpse state can't be summoned
4081 if( OldSummon->isDead() )
4082 return;
4084 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4085 OldSummon->SetMapId(m_caster->GetMapId());
4087 float px, py, pz;
4088 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4090 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4091 m_caster->GetMap()->Add((Creature*)OldSummon);
4093 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4095 ((Player*)m_caster)->PetSpellInitialize();
4097 return;
4100 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4101 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4102 else
4103 return;
4106 Pet* NewSummon = new Pet;
4108 // petentry==0 for hunter "call pet" (current pet summoned if any)
4109 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4111 if(NewSummon->getPetType()==SUMMON_PET)
4113 // Remove Demonic Sacrifice auras (known pet)
4114 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4115 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4117 if((*itr)->GetModifier()->m_miscvalue == 2228)
4119 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4120 itr = auraClassScripts.begin();
4122 else
4123 ++itr;
4127 return;
4130 // not error in case fail hunter call pet
4131 if(!petentry)
4133 delete NewSummon;
4134 return;
4137 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4139 if(!cInfo)
4141 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4142 delete NewSummon;
4143 return;
4146 Map *map = m_caster->GetMap();
4147 uint32 pet_number = objmgr.GeneratePetNumber();
4148 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4149 petentry, pet_number))
4151 delete NewSummon;
4152 return;
4155 float px, py, pz;
4156 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4158 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4160 if(!NewSummon->IsPositionValid())
4162 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4163 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4164 delete NewSummon;
4165 return;
4168 uint32 petlevel = m_caster->getLevel();
4169 NewSummon->setPetType(SUMMON_PET);
4171 uint32 faction = m_caster->getFaction();
4172 if(m_caster->GetTypeId() == TYPEID_UNIT)
4174 if ( ((Creature*)m_caster)->isTotem() )
4175 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4176 else
4177 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4180 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4181 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4182 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4183 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4184 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4185 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4186 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4187 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4188 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4189 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4191 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4192 // this enables pet details window (Shift+P)
4194 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4195 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4196 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4198 if(m_caster->IsPvP())
4199 NewSummon->SetPvP(true);
4201 NewSummon->InitStatsForLevel(petlevel);
4202 NewSummon->InitPetCreateSpells();
4203 NewSummon->InitLevelupSpellsForLevel();
4204 NewSummon->InitTalentForLevel();
4206 if(NewSummon->getPetType()==SUMMON_PET)
4208 // Remove Demonic Sacrifice auras (new pet)
4209 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4210 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4212 if((*itr)->GetModifier()->m_miscvalue==2228)
4214 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4215 itr = auraClassScripts.begin();
4217 else
4218 ++itr;
4221 // generate new name for summon pet
4222 std::string new_name=objmgr.GeneratePetName(petentry);
4223 if(!new_name.empty())
4224 NewSummon->SetName(new_name);
4226 else if(NewSummon->getPetType()==HUNTER_PET)
4227 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4229 NewSummon->AIM_Initialize();
4230 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4231 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4233 map->Add((Creature*)NewSummon);
4235 m_caster->SetPet(NewSummon);
4236 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4238 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4240 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4241 ((Player*)m_caster)->PetSpellInitialize();
4245 void Spell::EffectLearnPetSpell(uint32 i)
4247 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4248 return;
4250 Player *_player = (Player*)m_caster;
4252 Pet *pet = _player->GetPet();
4253 if(!pet)
4254 return;
4255 if(!pet->isAlive())
4256 return;
4258 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4259 if(!learn_spellproto)
4260 return;
4262 pet->learnSpell(learn_spellproto->Id);
4264 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4265 _player->PetSpellInitialize();
4268 void Spell::EffectTaunt(uint32 /*i*/)
4270 if (!unitTarget)
4271 return;
4273 // this effect use before aura Taunt apply for prevent taunt already attacking target
4274 // for spell as marked "non effective at already attacking target"
4275 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4277 if (unitTarget->getVictim()==m_caster)
4279 SendCastResult(SPELL_FAILED_DONT_REPORT);
4280 return;
4284 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4285 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4286 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4289 void Spell::EffectWeaponDmg(uint32 i)
4291 if(!unitTarget)
4292 return;
4293 if(!unitTarget->isAlive())
4294 return;
4296 // multiple weapon dmg effect workaround
4297 // execute only the last weapon damage
4298 // and handle all effects at once
4299 for (int j = 0; j < 3; ++j)
4301 switch(m_spellInfo->Effect[j])
4303 case SPELL_EFFECT_WEAPON_DAMAGE:
4304 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4305 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4306 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4307 if (j < i) // we must calculate only at last weapon effect
4308 return;
4309 break;
4313 // some spell specific modifiers
4314 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4316 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4317 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4318 bool normalized = false;
4320 int32 spell_bonus = 0; // bonus specific for spell
4321 switch(m_spellInfo->SpellFamilyName)
4323 case SPELLFAMILY_WARRIOR:
4325 // Whirlwind, single only spell with 2 weapon white damage apply if have
4326 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000400000000)))
4328 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4329 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4331 // Devastate bonus and sunder armor refresh
4332 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4334 uint32 stack = 0;
4335 // Need refresh all Sunder Armor auras from this caster
4336 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4337 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4339 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4340 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4341 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
4342 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4344 (*itr).second->RefreshAura();
4345 stack = (*itr).second->GetStackAmount();
4348 if (stack)
4349 spell_bonus += stack * CalculateDamage(2, unitTarget);
4351 break;
4353 case SPELLFAMILY_ROGUE:
4355 // Mutilate (for each hand)
4356 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x600000000))
4358 bool found = false;
4359 // fast check
4360 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4361 found = true;
4362 // full aura scan
4363 else
4365 Unit::AuraMap const& auras = unitTarget->GetAuras();
4366 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4368 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4370 found = true;
4371 break;
4376 if(found)
4377 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4379 break;
4381 case SPELLFAMILY_PALADIN:
4383 // Seal of Command - receive benefit from Spell Damage and Healing
4384 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000002000000))
4386 spellBonusNeedWeaponDamagePercentMod = true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4387 spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4388 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4390 break;
4392 case SPELLFAMILY_SHAMAN:
4394 // Skyshatter Harness item set bonus
4395 // Stormstrike
4396 if(m_spellInfo->SpellFamilyFlags & UI64LIT(0x001000000000))
4398 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4399 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
4401 // Stormstrike AP Buff
4402 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
4404 m_caster->CastSpell(m_caster, 38430, true, NULL, *citr);
4405 break;
4412 int32 fixed_bonus = 0;
4413 for (int j = 0; j < 3; ++j)
4415 switch(m_spellInfo->Effect[j])
4417 case SPELL_EFFECT_WEAPON_DAMAGE:
4418 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4419 fixed_bonus += CalculateDamage(j, unitTarget);
4420 break;
4421 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4422 fixed_bonus += CalculateDamage(j, unitTarget);
4423 normalized = true;
4424 break;
4425 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4426 weaponDamagePercentMod *= float(CalculateDamage(j, unitTarget)) / 100.0f;
4428 // applied only to prev.effects fixed damage
4429 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4430 break;
4431 default:
4432 break; // not weapon damage effect, just skip
4436 // apply weaponDamagePercentMod to spell bonus also
4437 if(spellBonusNeedWeaponDamagePercentMod)
4438 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4440 // non-weapon damage
4441 int32 bonus = spell_bonus + fixed_bonus;
4443 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4444 if(bonus)
4446 UnitMods unitMod;
4447 switch(m_attackType)
4449 default:
4450 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4451 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4452 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4455 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4456 bonus = int32(bonus*weapon_total_pct);
4459 // + weapon damage with applied weapon% dmg to base weapon damage in call
4460 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4462 // total damage
4463 bonus = int32(bonus*totalDamagePercentMod);
4465 // prevent negative damage
4466 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4468 // Add melee damage bonuses (also check for negative)
4469 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4470 m_damage+= eff_damage;
4472 // Hemorrhage
4473 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
4475 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4476 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4479 // Mangle (Cat): CP
4480 if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
4482 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4483 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4486 // take ammo
4487 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4489 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4491 // wands don't have ammo
4492 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
4493 return;
4495 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4497 if(pItem->GetMaxStackCount()==1)
4499 // decrease durability for non-stackable throw weapon
4500 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4502 else
4504 // decrease items amount for stackable throw weapon
4505 uint32 count = 1;
4506 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4509 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4510 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4514 void Spell::EffectThreat(uint32 /*i*/)
4516 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4517 return;
4519 if(!unitTarget->CanHaveThreatList())
4520 return;
4522 unitTarget->AddThreat(m_caster, float(damage));
4525 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4527 if(!unitTarget)
4528 return;
4529 if(!unitTarget->isAlive())
4530 return;
4532 uint32 heal = m_caster->GetMaxHealth();
4534 m_healing += heal;
4537 void Spell::EffectInterruptCast(uint32 /*i*/)
4539 if(!unitTarget)
4540 return;
4541 if(!unitTarget->isAlive())
4542 return;
4544 // TODO: not all spells that used this effect apply cooldown at school spells
4545 // also exist case: apply cooldown to interrupted cast only and to all spells
4546 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4548 if (unitTarget->m_currentSpells[i])
4550 // check if we can interrupt spell
4551 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4553 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4554 unitTarget->InterruptSpell(i,false);
4560 void Spell::EffectSummonObjectWild(uint32 i)
4562 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4564 GameObject* pGameObj = new GameObject;
4566 WorldObject* target = focusObject;
4567 if( !target )
4568 target = m_caster;
4570 float x, y, z;
4571 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4573 x = m_targets.m_destX;
4574 y = m_targets.m_destY;
4575 z = m_targets.m_destZ;
4577 else
4578 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
4580 Map *map = target->GetMap();
4582 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4583 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4585 delete pGameObj;
4586 return;
4589 int32 duration = GetSpellDuration(m_spellInfo);
4590 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4591 pGameObj->SetSpellId(m_spellInfo->Id);
4593 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4594 m_caster->AddGameObject(pGameObj);
4595 map->Add(pGameObj);
4597 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4599 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4601 Player *pl = (Player*)m_caster;
4602 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4603 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4605 uint32 team = ALLIANCE;
4607 if(pl->GetTeam() == team)
4608 team = HORDE;
4610 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4615 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4617 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4619 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4620 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4622 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4627 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4629 GameObject* linkedGO = new GameObject;
4630 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4631 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4633 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4634 linkedGO->SetSpellId(m_spellInfo->Id);
4636 m_caster->AddGameObject(linkedGO);
4637 map->Add(linkedGO);
4639 else
4641 delete linkedGO;
4642 linkedGO = NULL;
4643 return;
4648 void Spell::EffectScriptEffect(uint32 effIndex)
4650 // TODO: we must implement hunter pet summon at login there (spell 6962)
4652 switch(m_spellInfo->SpellFamilyName)
4654 case SPELLFAMILY_GENERIC:
4656 switch(m_spellInfo->Id)
4658 // PX-238 Winter Wondervolt TRAP
4659 case 26275:
4661 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4663 // check presence
4664 for(int j = 0; j < 4; ++j)
4665 if(unitTarget->HasAura(spells[j],0))
4666 return;
4668 // select spell
4669 uint32 iTmpSpellId = spells[urand(0,3)];
4671 // cast
4672 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4673 return;
4675 // Bending Shinbone
4676 case 8856:
4678 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4679 return;
4681 uint32 spell_id = 0;
4682 switch(urand(1, 5))
4684 case 1: spell_id = 8854; break;
4685 default: spell_id = 8855; break;
4688 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4689 return;
4691 // Brittle Armor - need remove one 24575 Brittle Armor aura
4692 case 24590:
4693 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4694 return;
4695 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4696 case 26465:
4697 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4698 return;
4699 // Orb teleport spells
4700 case 25140:
4701 case 25143:
4702 case 25650:
4703 case 25652:
4704 case 29128:
4705 case 29129:
4706 case 35376:
4707 case 35727:
4709 if(!unitTarget)
4710 return;
4712 uint32 spellid;
4713 switch(m_spellInfo->Id)
4715 case 25140: spellid = 32571; break;
4716 case 25143: spellid = 32572; break;
4717 case 25650: spellid = 30140; break;
4718 case 25652: spellid = 30141; break;
4719 case 29128: spellid = 32568; break;
4720 case 29129: spellid = 32569; break;
4721 case 35376: spellid = 25649; break;
4722 case 35727: spellid = 35730; break;
4723 default:
4724 return;
4727 unitTarget->CastSpell(unitTarget,spellid,false);
4728 return;
4730 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4731 case 22539:
4732 case 22972:
4733 case 22975:
4734 case 22976:
4735 case 22977:
4736 case 22978:
4737 case 22979:
4738 case 22980:
4739 case 22981:
4740 case 22982:
4741 case 22983:
4742 case 22984:
4743 case 22985:
4745 if(!unitTarget || !unitTarget->isAlive())
4746 return;
4748 // Onyxia Scale Cloak
4749 if(unitTarget->GetDummyAura(22683))
4750 return;
4752 // Shadow Flame
4753 m_caster->CastSpell(unitTarget, 22682, true);
4754 return;
4756 // Summon Black Qiraji Battle Tank
4757 case 26656:
4759 if(!unitTarget)
4760 return;
4762 // Prevent stacking of mounts
4763 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4765 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4766 if (unitTarget->GetAreaId() == 3428)
4767 unitTarget->CastSpell(unitTarget, 25863, false);
4768 else
4769 unitTarget->CastSpell(unitTarget, 26655, false);
4770 return;
4772 // Piccolo of the Flaming Fire
4773 case 17512:
4775 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4776 return;
4777 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4778 return;
4780 // Escape artist
4781 case 20589:
4783 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4784 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
4785 return;
4787 // Mirren's Drinking Hat
4788 case 29830:
4790 uint32 item = 0;
4791 switch ( urand(1, 6) )
4793 case 1:
4794 case 2:
4795 case 3:
4796 item = 23584; break; // Loch Modan Lager
4797 case 4:
4798 case 5:
4799 item = 23585; break; // Stouthammer Lite
4800 case 6:
4801 item = 23586; break; // Aerie Peak Pale Ale
4803 if (item)
4804 DoCreateItem(effIndex,item);
4805 break;
4807 // Improved Sprint
4808 case 30918:
4810 // Removes snares and roots.
4811 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4812 Unit::AuraMap& Auras = unitTarget->GetAuras();
4813 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4815 next = iter;
4816 ++next;
4817 Aura *aur = iter->second;
4818 if (!aur->IsPositive()) //only remove negative spells
4820 // check for mechanic mask
4821 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4823 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4824 if(Auras.empty())
4825 break;
4826 else
4827 next = Auras.begin();
4831 break;
4833 // Flame Crash
4834 case 41126:
4836 if(!unitTarget)
4837 return;
4839 unitTarget->CastSpell(unitTarget, 41131, true);
4840 break;
4842 // Force Cast - Portal Effect: Sunwell Isle
4843 case 44876:
4845 if(!unitTarget)
4846 return;
4848 unitTarget->CastSpell(unitTarget, 44870, true);
4849 break;
4851 // Goblin Weather Machine
4852 case 46203:
4854 if(!unitTarget)
4855 return;
4857 uint32 spellId = 0;
4858 switch(rand() % 4)
4860 case 0: spellId = 46740; break;
4861 case 1: spellId = 46739; break;
4862 case 2: spellId = 46738; break;
4863 case 3: spellId = 46736; break;
4865 unitTarget->CastSpell(unitTarget, spellId, true);
4866 break;
4868 //5,000 Gold
4869 case 46642:
4871 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4872 return;
4874 ((Player*)unitTarget)->ModifyMoney(50000000);
4876 break;
4878 // Emblazon Runeblade
4879 case 51770:
4881 if(!unitTarget)
4882 return;
4884 unitTarget->CastSpell(unitTarget, 51771, false);
4885 break;
4887 // Death Gate
4888 case 52751:
4890 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
4891 return;
4892 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4893 unitTarget->CastSpell(unitTarget, damage, false);
4894 break;
4896 // Winged Steed of the Ebon Blade
4897 case 54729:
4899 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4900 return;
4902 // Prevent stacking of mounts
4903 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4905 // Triggered spell id dependent of riding skill
4906 if(uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
4908 if (skillval >= 300)
4909 unitTarget->CastSpell(unitTarget, 54727, true);
4910 else
4911 unitTarget->CastSpell(unitTarget, 54726, true);
4913 return;
4915 case 58418: // Portal to Orgrimmar
4916 case 58420: // Portal to Stormwind
4918 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0)
4919 return;
4921 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
4922 uint32 questID = m_spellInfo->CalculateSimpleValue(1);
4924 if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID))
4925 unitTarget->CastSpell(unitTarget, spellID, true);
4927 return;
4929 case 59317: // Teleporting
4930 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4931 return;
4933 // return from top
4934 if (((Player*)unitTarget)->GetAreaId() == 4637)
4935 unitTarget->CastSpell(unitTarget, 59316, true);
4936 // teleport atop
4937 else
4938 unitTarget->CastSpell(unitTarget, 59314, true);
4940 return;
4941 // random spell learn instead placeholder
4942 case 60893: // Northrend Alchemy Research
4943 case 61177: // Northrend Inscription Research
4944 case 61288: // Minor Inscription Research
4945 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4947 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4948 return;
4950 // learn random explicit discovery recipe (if any)
4951 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
4952 ((Player*)m_caster)->learnSpell(discoveredSpell, false);
4953 return;
4956 break;
4958 case SPELLFAMILY_WARLOCK:
4960 switch(m_spellInfo->Id)
4962 // Healthstone creating spells
4963 case 6201:
4964 case 6202:
4965 case 5699:
4966 case 11729:
4967 case 11730:
4968 case 27230:
4969 case 47871:
4970 case 47878:
4972 uint32 itemtype;
4973 uint32 rank = 0;
4974 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4975 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4977 if((*i)->GetId() == 18692)
4979 rank = 1;
4980 break;
4982 else if((*i)->GetId() == 18693)
4984 rank = 2;
4985 break;
4989 static uint32 const itypes[8][3] = {
4990 { 5512, 19004, 19005}, // Minor Healthstone
4991 { 5511, 19006, 19007}, // Lesser Healthstone
4992 { 5509, 19008, 19009}, // Healthstone
4993 { 5510, 19010, 19011}, // Greater Healthstone
4994 { 9421, 19012, 19013}, // Major Healthstone
4995 {22103, 22104, 22105}, // Master Healthstone
4996 {36889, 36890, 36891}, // Demonic Healthstone
4997 {36892, 36893, 36894} // Fel Healthstone
5000 switch(m_spellInfo->Id)
5002 case 6201:
5003 itemtype=itypes[0][rank];break; // Minor Healthstone
5004 case 6202:
5005 itemtype=itypes[1][rank];break; // Lesser Healthstone
5006 case 5699:
5007 itemtype=itypes[2][rank];break; // Healthstone
5008 case 11729:
5009 itemtype=itypes[3][rank];break; // Greater Healthstone
5010 case 11730:
5011 itemtype=itypes[4][rank];break; // Major Healthstone
5012 case 27230:
5013 itemtype=itypes[5][rank];break; // Master Healthstone
5014 case 47871:
5015 itemtype=itypes[6][rank];break; // Demonic Healthstone
5016 case 47878:
5017 itemtype=itypes[7][rank];break; // Fel Healthstone
5018 default:
5019 return;
5021 DoCreateItem( effIndex, itemtype );
5022 return;
5024 // Everlasting Affliction
5025 case 47422:
5027 // Need refresh caster corruption auras on target
5028 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5029 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5031 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5032 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5033 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
5034 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5035 (*itr).second->RefreshAura();
5037 return;
5040 break;
5042 case SPELLFAMILY_PRIEST:
5044 switch(m_spellInfo->Id)
5046 // Pain and Suffering
5047 case 47948:
5049 if (!unitTarget)
5050 return;
5051 // Refresh Shadow Word: Pain on target
5052 Unit::AuraMap& auras = unitTarget->GetAuras();
5053 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5055 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5056 if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5057 (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
5058 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5060 (*itr).second->RefreshAura();
5061 return;
5064 return;
5066 default:
5067 break;
5069 break;
5071 case SPELLFAMILY_HUNTER:
5073 switch(m_spellInfo->Id)
5075 // Chimera Shot
5076 case 53209:
5078 uint32 spellId = 0;
5079 int32 basePoint = 0;
5080 Unit::AuraMap& Auras = unitTarget->GetAuras();
5081 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5083 Aura *aura = (*i).second;
5084 if (aura->GetCasterGUID() != m_caster->GetGUID())
5085 continue;
5086 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5087 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5088 if (!(familyFlag & UI64LIT(0x000000800000C000)))
5089 continue;
5090 // Refresh aura duration
5091 aura->RefreshAura();
5093 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5094 if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == 0)
5096 spellId = 53353; // 53353 Chimera Shot - Serpent
5097 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5099 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5100 if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == 0)
5102 spellId = 53358; // 53358 Chimera Shot - Viper
5103 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
5105 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5106 if (familyFlag & UI64LIT(0x0000000000008000))
5107 spellId = 53359; // 53359 Chimera Shot - Scorpid
5108 // ?? nothing say in spell desc (possibly need addition check)
5109 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5110 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5112 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5115 if (spellId)
5116 m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
5117 return;
5119 default:
5120 break;
5122 break;
5124 case SPELLFAMILY_PALADIN:
5126 // Judgement
5127 if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000800000))
5129 if(!unitTarget || !unitTarget->isAlive())
5130 return;
5131 uint32 spellId1 = 0;
5132 uint32 spellId2 = 0;
5134 // Judgement self add switch
5135 switch (m_spellInfo->Id)
5137 case 41467: break; // Judgement
5138 case 53407: spellId1 = 20184; break; // Judgement of Justice
5139 case 20271: // Judgement of Light
5140 case 57774: spellId1 = 20185; break; // Judgement of Light
5141 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5142 default:
5143 return;
5145 // all seals have aura dummy in 2 effect
5146 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5147 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5149 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5150 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5151 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5152 continue;
5153 spellId2 = (*itr)->GetModifier()->m_amount;
5154 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5155 if (!judge)
5156 continue;
5157 break;
5159 if (spellId1)
5160 m_caster->CastSpell(unitTarget, spellId1, true);
5161 if (spellId2)
5162 m_caster->CastSpell(unitTarget, spellId2, true);
5163 return;
5166 case SPELLFAMILY_POTION:
5168 switch(m_spellInfo->Id)
5170 // Dreaming Glory
5171 case 28698:
5173 if(!unitTarget)
5174 return;
5175 unitTarget->CastSpell(unitTarget, 28694, true);
5176 break;
5178 // Netherbloom
5179 case 28702:
5181 if(!unitTarget)
5182 return;
5183 // 25% chance of casting a random buff
5184 if(roll_chance_i(75))
5185 return;
5187 // triggered spells are 28703 to 28707
5188 // Note: some sources say, that there was the possibility of
5189 // receiving a debuff. However, this seems to be removed by a patch.
5190 const uint32 spellid = 28703;
5192 // don't overwrite an existing aura
5193 for(uint8 i = 0; i < 5; ++i)
5194 if(unitTarget->HasAura(spellid + i, 0))
5195 return;
5196 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5197 break;
5200 // Nightmare Vine
5201 case 28720:
5203 if(!unitTarget)
5204 return;
5205 // 25% chance of casting Nightmare Pollen
5206 if(roll_chance_i(75))
5207 return;
5208 unitTarget->CastSpell(unitTarget, 28721, true);
5209 break;
5212 break;
5216 // normal DB scripted effect
5217 if(!unitTarget)
5218 return;
5220 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5221 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5224 void Spell::EffectSanctuary(uint32 /*i*/)
5226 if(!unitTarget)
5227 return;
5228 //unitTarget->CombatStop();
5230 unitTarget->CombatStop();
5231 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5232 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5233 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5235 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5239 void Spell::EffectAddComboPoints(uint32 /*i*/)
5241 if(!unitTarget)
5242 return;
5244 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5245 return;
5247 if(damage <= 0)
5248 return;
5250 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5253 void Spell::EffectDuel(uint32 i)
5255 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5256 return;
5258 Player *caster = (Player*)m_caster;
5259 Player *target = (Player*)unitTarget;
5261 // caster or target already have requested duel
5262 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5263 return;
5265 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5266 // Don't have to check the target's map since you cannot challenge someone across maps
5267 uint32 mapid = caster->GetMapId();
5268 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5270 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5271 return;
5274 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5275 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5277 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5278 return;
5281 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5282 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5284 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5285 return;
5288 //CREATE DUEL FLAG OBJECT
5289 GameObject* pGameObj = new GameObject;
5291 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5293 Map *map = m_caster->GetMap();
5294 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5295 map, m_caster->GetPhaseMask(),
5296 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5297 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5298 m_caster->GetPositionZ(),
5299 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5301 delete pGameObj;
5302 return;
5305 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5306 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5307 int32 duration = GetSpellDuration(m_spellInfo);
5308 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5309 pGameObj->SetSpellId(m_spellInfo->Id);
5311 m_caster->AddGameObject(pGameObj);
5312 map->Add(pGameObj);
5313 //END
5315 // Send request
5316 WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
5317 data << uint64(pGameObj->GetGUID());
5318 data << uint64(caster->GetGUID());
5319 caster->GetSession()->SendPacket(&data);
5320 target->GetSession()->SendPacket(&data);
5322 // create duel-info
5323 DuelInfo *duel = new DuelInfo;
5324 duel->initiator = caster;
5325 duel->opponent = target;
5326 duel->startTime = 0;
5327 duel->startTimer = 0;
5328 caster->duel = duel;
5330 DuelInfo *duel2 = new DuelInfo;
5331 duel2->initiator = caster;
5332 duel2->opponent = caster;
5333 duel2->startTime = 0;
5334 duel2->startTimer = 0;
5335 target->duel = duel2;
5337 caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5338 target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
5341 void Spell::EffectStuck(uint32 /*i*/)
5343 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5344 return;
5346 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5347 return;
5349 Player* pTarget = (Player*)unitTarget;
5351 sLog.outDebug("Spell Effect: Stuck");
5352 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());
5354 if(pTarget->isInFlight())
5355 return;
5357 // homebind location is loaded always
5358 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5360 // Stuck spell trigger Hearthstone cooldown
5361 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5362 if(!spellInfo)
5363 return;
5364 Spell spell(pTarget, spellInfo, true, 0);
5365 spell.SendSpellCooldown();
5368 void Spell::EffectSummonPlayer(uint32 /*i*/)
5370 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5371 return;
5373 // Evil Twin (ignore player summon, but hide this for summoner)
5374 if(unitTarget->GetDummyAura(23445))
5375 return;
5377 float x, y, z;
5378 m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize());
5380 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5382 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5383 data << uint64(m_caster->GetGUID()); // summoner guid
5384 data << uint32(m_caster->GetZoneId()); // summoner zone
5385 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5386 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5389 static ScriptInfo generateActivateCommand()
5391 ScriptInfo si;
5392 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5393 return si;
5396 void Spell::EffectActivateObject(uint32 effect_idx)
5398 if(!gameObjTarget)
5399 return;
5401 static ScriptInfo activateCommand = generateActivateCommand();
5403 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5405 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5408 void Spell::EffectApplyGlyph(uint32 i)
5410 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5411 return;
5413 Player *player = (Player*)m_caster;
5415 // apply new one
5416 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5418 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5420 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5422 if(gp->TypeFlags != gs->TypeFlags)
5424 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5425 return; // glyph slot mismatch
5429 // remove old glyph
5430 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5432 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5434 player->RemoveAurasDueToSpell(old_gp->SpellId);
5435 player->SetGlyph(m_glyphIndex, 0);
5439 player->CastSpell(m_caster, gp->SpellId, true);
5440 player->SetGlyph(m_glyphIndex, glyph);
5445 void Spell::EffectSummonTotem(uint32 i)
5447 uint8 slot = 0;
5448 switch(m_spellInfo->EffectMiscValueB[i])
5450 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5451 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5452 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5453 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5454 // Battle standard case
5455 case SUMMON_TYPE_TOTEM: slot = 254; break;
5456 // jewelery statue case, like totem without slot
5457 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5458 default: return;
5461 if(slot < MAX_TOTEM)
5463 uint64 guid = m_caster->m_TotemSlot[slot];
5464 if(guid != 0)
5466 Creature *OldTotem = m_caster->GetMap()->GetCreature(guid);
5467 if(OldTotem && OldTotem->isTotem())
5468 ((Totem*)OldTotem)->UnSummon();
5472 uint32 team = 0;
5473 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5474 team = ((Player*)m_caster)->GetTeam();
5476 Totem* pTotem = new Totem;
5478 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5479 m_spellInfo->EffectMiscValue[i], team ))
5481 delete pTotem;
5482 return;
5485 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5487 float x, y, z;
5488 m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle);
5490 // totem must be at same Z in case swimming caster and etc.
5491 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5492 z = m_caster->GetPositionZ();
5494 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5496 if(slot < MAX_TOTEM)
5497 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5499 pTotem->SetOwner(m_caster->GetGUID());
5500 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5502 int32 duration=GetSpellDuration(m_spellInfo);
5503 if(Player* modOwner = m_caster->GetSpellModOwner())
5504 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
5505 pTotem->SetDuration(duration);
5507 if (damage) // if not spell info, DB values used
5509 pTotem->SetMaxHealth(damage);
5510 pTotem->SetHealth(damage);
5513 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5515 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5516 pTotem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
5518 if(m_caster->IsPvP())
5519 pTotem->SetPvP(true);
5521 pTotem->Summon(m_caster);
5523 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5525 WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
5526 data << uint8(slot);
5527 data << uint64(pTotem->GetGUID());
5528 data << uint32(duration);
5529 data << uint32(m_spellInfo->Id);
5530 ((Player*)m_caster)->SendDirectMessage(&data);
5534 void Spell::EffectEnchantHeldItem(uint32 i)
5536 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5537 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5538 return;
5540 Player* item_owner = (Player*)unitTarget;
5541 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5543 if(!item )
5544 return;
5546 // must be equipped
5547 if(!item ->IsEquipped())
5548 return;
5550 if (m_spellInfo->EffectMiscValue[i])
5552 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5553 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5554 if(!duration)
5555 duration = m_currentBasePoints[i]+1; //Base points after ..
5556 if(!duration)
5557 duration = 10; //10 seconds for enchants which don't have listed duration
5559 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5560 if(!pEnchant)
5561 return;
5563 // Always go to temp enchantment slot
5564 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5566 // Enchantment will not be applied if a different one already exists
5567 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5568 return;
5570 // Apply the temporary enchantment
5571 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
5572 item_owner->ApplyEnchantment(item, slot, true);
5576 void Spell::EffectDisEnchant(uint32 /*i*/)
5578 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5579 return;
5581 Player* p_caster = (Player*)m_caster;
5582 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5583 return;
5585 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5587 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5589 // item will be removed at disenchanting end
5592 void Spell::EffectInebriate(uint32 /*i*/)
5594 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5595 return;
5597 Player *player = (Player*)unitTarget;
5598 uint16 currentDrunk = player->GetDrunkValue();
5599 uint16 drunkMod = damage * 256;
5600 if (currentDrunk + drunkMod > 0xFFFF)
5601 currentDrunk = 0xFFFF;
5602 else
5603 currentDrunk += drunkMod;
5604 player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
5607 void Spell::EffectFeedPet(uint32 i)
5609 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5610 return;
5612 Player *_player = (Player*)m_caster;
5614 Item* foodItem = m_targets.getItemTarget();
5615 if(!foodItem)
5616 return;
5618 Pet *pet = _player->GetPet();
5619 if(!pet)
5620 return;
5622 if(!pet->isAlive())
5623 return;
5625 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5626 if(benefit <= 0)
5627 return;
5629 uint32 count = 1;
5630 _player->DestroyItemCount(foodItem,count,true);
5631 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5633 m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[i], &benefit, NULL, NULL, true);
5636 void Spell::EffectDismissPet(uint32 /*i*/)
5638 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5639 return;
5641 Pet* pet = m_caster->GetPet();
5643 // not let dismiss dead pet
5644 if(!pet||!pet->isAlive())
5645 return;
5647 ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
5650 void Spell::EffectSummonObject(uint32 i)
5652 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5654 uint8 slot = 0;
5655 switch(m_spellInfo->Effect[i])
5657 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5658 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5659 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5660 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5661 default: return;
5664 uint64 guid = m_caster->m_ObjectSlot[slot];
5665 if(guid != 0)
5667 GameObject* obj = NULL;
5668 if( m_caster )
5669 obj = m_caster->GetMap()->GetGameObject(guid);
5671 if(obj) obj->Delete();
5672 m_caster->m_ObjectSlot[slot] = 0;
5675 GameObject* pGameObj = new GameObject;
5677 float x, y, z;
5678 // If dest location if present
5679 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5681 x = m_targets.m_destX;
5682 y = m_targets.m_destY;
5683 z = m_targets.m_destZ;
5685 // Summon in random point all other units if location present
5686 else
5687 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
5689 Map *map = m_caster->GetMap();
5690 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
5691 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5693 delete pGameObj;
5694 return;
5697 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5698 int32 duration = GetSpellDuration(m_spellInfo);
5699 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5700 pGameObj->SetSpellId(m_spellInfo->Id);
5701 m_caster->AddGameObject(pGameObj);
5703 map->Add(pGameObj);
5704 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5705 data << uint64(pGameObj->GetGUID());
5706 m_caster->SendMessageToSet(&data, true);
5708 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5711 void Spell::EffectResurrect(uint32 /*effIndex*/)
5713 if(!unitTarget)
5714 return;
5715 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5716 return;
5718 if(unitTarget->isAlive())
5719 return;
5720 if(!unitTarget->IsInWorld())
5721 return;
5723 switch (m_spellInfo->Id)
5725 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5726 case 8342:
5727 if (roll_chance_i(67))
5729 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5730 return;
5732 break;
5733 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5734 case 22999:
5735 if (roll_chance_i(50))
5737 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5738 return;
5740 break;
5741 default:
5742 break;
5745 Player* pTarget = ((Player*)unitTarget);
5747 if(pTarget->isRessurectRequested()) // already have one active request
5748 return;
5750 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5751 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5753 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5754 SendResurrectRequest(pTarget);
5757 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5759 if(!unitTarget || !unitTarget->isAlive())
5760 return;
5762 if( unitTarget->m_extraAttacks )
5763 return;
5765 unitTarget->m_extraAttacks = damage;
5768 void Spell::EffectParry(uint32 /*i*/)
5770 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5771 ((Player*)unitTarget)->SetCanParry(true);
5774 void Spell::EffectBlock(uint32 /*i*/)
5776 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5777 ((Player*)unitTarget)->SetCanBlock(true);
5780 void Spell::EffectMomentMove(uint32 i)
5782 if(unitTarget->isInFlight())
5783 return;
5785 if( m_spellInfo->rangeIndex == 1) //self range
5787 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5789 // before caster
5790 float fx, fy, fz;
5791 unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
5792 float ox, oy, oz;
5793 unitTarget->GetPosition(ox, oy, oz);
5795 float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
5796 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5798 fx = fx2;
5799 fy = fy2;
5800 fz = fz2;
5801 unitTarget->UpdateGroundPositionZ(fx, fy, fz);
5804 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
5808 void Spell::EffectReputation(uint32 i)
5810 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5811 return;
5813 Player *_player = (Player*)unitTarget;
5815 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5817 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5819 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5821 if(!factionEntry)
5822 return;
5824 _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
5827 void Spell::EffectQuestComplete(uint32 i)
5829 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5830 return;
5832 Player *_player = (Player*)m_caster;
5834 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5835 _player->AreaExploredOrEventHappens(quest_id);
5838 void Spell::EffectSelfResurrect(uint32 i)
5840 if(!unitTarget || unitTarget->isAlive())
5841 return;
5842 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5843 return;
5844 if(!unitTarget->IsInWorld())
5845 return;
5847 uint32 health = 0;
5848 uint32 mana = 0;
5850 // flat case
5851 if(damage < 0)
5853 health = uint32(-damage);
5854 mana = m_spellInfo->EffectMiscValue[i];
5856 // percent case
5857 else
5859 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5860 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5861 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5864 Player *plr = ((Player*)unitTarget);
5865 plr->ResurrectPlayer(0.0f);
5867 plr->SetHealth( health );
5868 plr->SetPower(POWER_MANA, mana );
5869 plr->SetPower(POWER_RAGE, 0 );
5870 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5872 plr->SpawnCorpseBones();
5874 plr->SaveToDB();
5877 void Spell::EffectSkinning(uint32 /*i*/)
5879 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5880 return;
5881 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5882 return;
5884 Creature* creature = (Creature*) unitTarget;
5885 int32 targetLevel = creature->getLevel();
5887 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5889 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5890 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5892 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5894 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5896 // Double chances for elites
5897 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5900 void Spell::EffectCharge(uint32 /*i*/)
5902 if(!unitTarget || !m_caster)
5903 return;
5905 float x, y, z;
5906 unitTarget->GetContactPoint(m_caster, x, y, z);
5907 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5908 ((Creature *)unitTarget)->StopMoving();
5910 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5911 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5913 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5914 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5916 // not all charge effects used in negative spells
5917 if ( !IsPositiveSpell(m_spellInfo->Id))
5918 m_caster->Attack(unitTarget,true);
5921 void Spell::EffectSummonCritter(uint32 i)
5923 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5924 return;
5925 Player* player = (Player*)m_caster;
5927 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5928 if(!pet_entry)
5929 return;
5931 Pet* old_critter = player->GetMiniPet();
5933 // for same pet just despawn
5934 if(old_critter && old_critter->GetEntry() == pet_entry)
5936 player->RemoveMiniPet();
5937 return;
5940 // despawn old pet before summon new
5941 if(old_critter)
5942 player->RemoveMiniPet();
5944 // summon new pet
5945 Pet* critter = new Pet(MINI_PET);
5947 Map *map = m_caster->GetMap();
5948 uint32 pet_number = objmgr.GeneratePetNumber();
5949 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
5950 pet_entry, pet_number))
5952 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5953 delete critter;
5954 return;
5957 float x, y, z;
5958 // If dest location if present
5959 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5961 x = m_targets.m_destX;
5962 y = m_targets.m_destY;
5963 z = m_targets.m_destZ;
5965 // Summon if dest location not present near caster
5966 else
5967 m_caster->GetClosePoint(x, y, z, critter->GetObjectSize());
5969 critter->Relocate(x, y, z, m_caster->GetOrientation());
5971 if(!critter->IsPositionValid())
5973 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5974 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5975 delete critter;
5976 return;
5979 critter->SetOwnerGUID(m_caster->GetGUID());
5980 critter->SetCreatorGUID(m_caster->GetGUID());
5981 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5982 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5984 critter->AIM_Initialize();
5985 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5986 //critter->InitLevelupSpellsForLevel(); // none?
5987 critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
5988 critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
5989 // some mini-pets have quests
5991 // set timer for unsummon
5992 int32 duration = GetSpellDuration(m_spellInfo);
5993 if(duration > 0)
5994 critter->SetDuration(duration);
5996 std::string name = player->GetName();
5997 name.append(petTypeSuffix[critter->getPetType()]);
5998 critter->SetName( name );
5999 player->SetMiniPet(critter);
6001 map->Add((Creature*)critter);
6004 void Spell::EffectKnockBack(uint32 i)
6006 if(!unitTarget || !m_caster)
6007 return;
6009 // Effect only works on players
6010 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
6011 return;
6013 float vsin = sin(m_caster->GetAngle(unitTarget));
6014 float vcos = cos(m_caster->GetAngle(unitTarget));
6016 WorldPacket data(SMSG_MOVE_KNOCK_BACK, 8+4+4+4+4+4);
6017 data.append(unitTarget->GetPackGUID());
6018 data << uint32(0); // Sequence
6019 data << float(vcos); // x direction
6020 data << float(vsin); // y direction
6021 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
6022 data << float(damage/-10); // Z Movement speed (vertical)
6024 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6027 void Spell::EffectSendTaxi(uint32 i)
6029 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6030 return;
6032 ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[i],m_spellInfo->Id);
6035 void Spell::EffectPlayerPull(uint32 i)
6037 if(!unitTarget || !m_caster)
6038 return;
6040 // Effect only works on players
6041 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
6042 return;
6044 float vsin = sin(unitTarget->GetAngle(m_caster));
6045 float vcos = cos(unitTarget->GetAngle(m_caster));
6047 WorldPacket data(SMSG_MOVE_KNOCK_BACK, 8+4+4+4+4+4);
6048 data.append(unitTarget->GetPackGUID());
6049 data << uint32(0); // Sequence
6050 data << float(vcos); // x direction
6051 data << float(vsin); // y direction
6052 // Horizontal speed
6053 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
6054 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
6056 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6059 void Spell::EffectDispelMechanic(uint32 i)
6061 if(!unitTarget)
6062 return;
6064 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6066 Unit::AuraMap& Auras = unitTarget->GetAuras();
6067 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6069 next = iter;
6070 ++next;
6071 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6072 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6074 unitTarget->RemoveAurasDueToSpell(spell->Id);
6075 if(Auras.empty())
6076 break;
6077 else
6078 next = Auras.begin();
6081 return;
6084 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6086 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6087 return;
6088 Player *_player = (Player*)m_caster;
6089 Pet *pet = _player->GetPet();
6090 if(!pet)
6091 return;
6092 if(pet->isAlive())
6093 return;
6094 if(damage < 0)
6095 return;
6096 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6097 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6098 pet->setDeathState( ALIVE );
6099 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6100 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6102 pet->AIM_Initialize();
6104 _player->PetSpellInitialize();
6105 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6108 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6110 int32 mana = 0;
6111 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6113 if(!m_caster->m_TotemSlot[slot])
6114 continue;
6116 Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]);
6117 if(totem && totem->isTotem())
6119 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6120 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6121 if(spellInfo)
6123 uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100;
6124 mana += manacost * damage / 100;
6126 ((Totem*)totem)->UnSummon();
6130 if (mana)
6131 m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
6134 void Spell::EffectDurabilityDamage(uint32 i)
6136 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6137 return;
6139 int32 slot = m_spellInfo->EffectMiscValue[i];
6141 // FIXME: some spells effects have value -1/-2
6142 // Possibly its mean -1 all player equipped items and -2 all items
6143 if(slot < 0)
6145 ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1));
6146 return;
6149 // invalid slot value
6150 if(slot >= INVENTORY_SLOT_BAG_END)
6151 return;
6153 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6154 ((Player*)unitTarget)->DurabilityPointsLoss(item, damage);
6157 void Spell::EffectDurabilityDamagePCT(uint32 i)
6159 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6160 return;
6162 int32 slot = m_spellInfo->EffectMiscValue[i];
6164 // FIXME: some spells effects have value -1/-2
6165 // Possibly its mean -1 all player equipped items and -2 all items
6166 if(slot < 0)
6168 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1));
6169 return;
6172 // invalid slot value
6173 if(slot >= INVENTORY_SLOT_BAG_END)
6174 return;
6176 if(damage <= 0)
6177 return;
6179 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
6180 ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f);
6183 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6185 if(!unitTarget)
6186 return;
6188 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6191 void Spell::EffectTransmitted(uint32 effIndex)
6193 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6195 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6197 if (!goinfo)
6199 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6200 return;
6203 float fx, fy, fz;
6205 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6207 fx = m_targets.m_destX;
6208 fy = m_targets.m_destY;
6209 fz = m_targets.m_destZ;
6211 //FIXME: this can be better check for most objects but still hack
6212 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6214 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6215 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6217 else
6219 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6220 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6221 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6223 m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
6226 Map *cMap = m_caster->GetMap();
6228 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6230 if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6231 { // but this is not proper, we really need to ignore not materialized objects
6232 SendCastResult(SPELL_FAILED_NOT_HERE);
6233 SendChannelUpdate(0);
6234 return;
6237 // replace by water level in this case
6238 fz = cMap->GetWaterLevel(fx, fy);
6240 // if gameobject is summoning object, it should be spawned right on caster's position
6241 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6243 m_caster->GetPosition(fx, fy, fz);
6246 GameObject* pGameObj = new GameObject;
6248 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6249 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6251 delete pGameObj;
6252 return;
6255 int32 duration = GetSpellDuration(m_spellInfo);
6257 switch(goinfo->type)
6259 case GAMEOBJECT_TYPE_FISHINGNODE:
6261 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6262 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6264 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6265 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6266 int32 lastSec = 0;
6267 switch(urand(0, 3))
6269 case 0: lastSec = 3; break;
6270 case 1: lastSec = 7; break;
6271 case 2: lastSec = 13; break;
6272 case 3: lastSec = 17; break;
6275 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6276 break;
6278 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6280 if(m_caster->GetTypeId() == TYPEID_PLAYER)
6282 pGameObj->AddUniqueUse((Player*)m_caster);
6283 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6285 break;
6287 case GAMEOBJECT_TYPE_FISHINGHOLE:
6288 case GAMEOBJECT_TYPE_CHEST:
6289 default:
6291 break;
6295 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6297 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6299 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6300 pGameObj->SetSpellId(m_spellInfo->Id);
6302 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6303 //m_caster->AddGameObject(pGameObj);
6304 //m_ObjToDel.push_back(pGameObj);
6306 cMap->Add(pGameObj);
6308 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6309 data << uint64(pGameObj->GetGUID());
6310 m_caster->SendMessageToSet(&data,true);
6312 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6314 GameObject* linkedGO = new GameObject;
6315 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6316 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6318 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6319 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6320 linkedGO->SetSpellId(m_spellInfo->Id);
6321 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6323 linkedGO->GetMap()->Add(linkedGO);
6325 else
6327 delete linkedGO;
6328 linkedGO = NULL;
6329 return;
6334 void Spell::EffectProspecting(uint32 /*i*/)
6336 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6337 return;
6339 Player* p_caster = (Player*)m_caster;
6340 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6341 return;
6343 if(itemTarget->GetCount() < 5)
6344 return;
6346 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6348 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6349 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6350 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6353 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6356 void Spell::EffectMilling(uint32 /*i*/)
6358 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6359 return;
6361 Player* p_caster = (Player*)m_caster;
6362 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6363 return;
6365 if(itemTarget->GetCount() < 5)
6366 return;
6368 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6370 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6371 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6372 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6375 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6378 void Spell::EffectSkill(uint32 /*i*/)
6380 sLog.outDebug("WORLD: SkillEFFECT");
6383 void Spell::EffectSummonDemon(uint32 i)
6385 // select center of summon position
6386 float center_x = m_targets.m_destX;
6387 float center_y = m_targets.m_destY;
6388 float center_z = m_targets.m_destZ;
6390 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6392 int32 amount = damage > 0 ? damage : 1;
6394 for(int32 count = 0; count < amount; ++count)
6396 float px, py, pz;
6397 // If dest location if present
6398 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6400 // Summon 1 unit in dest location
6401 if (count == 0)
6403 px = m_targets.m_destX;
6404 py = m_targets.m_destY;
6405 pz = m_targets.m_destZ;
6407 // Summon in random point all other units if location present
6408 else
6409 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
6411 // Summon if dest location not present near caster
6412 else
6413 m_caster->GetClosePoint(px,py,pz,3.0f);
6415 int32 duration = GetSpellDuration(m_spellInfo);
6417 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration);
6418 if (!Charmed) // something fatal, not attempt more
6419 return;
6421 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6422 Charmed->SetLevel(m_caster->getLevel());
6424 // TODO: Add damage/mana/hp according to level
6426 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6428 // Enslave demon effect, without mana cost and cooldown
6429 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6431 // Inferno effect
6432 Charmed->CastSpell(Charmed, 22703, true, 0);
6437 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6438 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6439 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6440 This is why we use a half sec delay between the visual effect and the resurrection itself */
6441 void Spell::EffectSpiritHeal(uint32 /*i*/)
6444 if(!unitTarget || unitTarget->isAlive())
6445 return;
6446 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6447 return;
6448 if(!unitTarget->IsInWorld())
6449 return;
6451 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6452 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6453 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6454 ((Player*)unitTarget)->SpawnCorpseBones();
6458 // remove insignia spell effect
6459 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6461 sLog.outDebug("Effect: SkinPlayerCorpse");
6462 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6463 return;
6465 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6468 void Spell::EffectStealBeneficialBuff(uint32 i)
6470 sLog.outDebug("Effect: StealBeneficialBuff");
6472 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6473 return;
6475 std::vector <Aura *> steal_list;
6476 // Create dispel mask by dispel type
6477 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6478 Unit::AuraMap const& auras = unitTarget->GetAuras();
6479 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6481 Aura *aur = (*itr).second;
6482 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6484 // Need check for passive? this
6485 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6486 steal_list.push_back(aur);
6489 // Ok if exist some buffs for dispel try dispel it
6490 if (!steal_list.empty())
6492 std::list < std::pair<uint32,uint64> > success_list;
6493 int32 list_size = steal_list.size();
6494 // Dispell N = damage buffs (or while exist buffs for dispel)
6495 for (int32 count=0; count < damage && list_size > 0; ++count)
6497 // Random select buff for dispel
6498 Aura *aur = steal_list[urand(0, list_size-1)];
6499 // Not use chance for steal
6500 // TODO possible need do it
6501 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6503 // Remove buff from list for prevent doubles
6504 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6506 Aura *stealed = *j;
6507 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6509 j = steal_list.erase(j);
6510 --list_size;
6512 else
6513 ++j;
6516 // Really try steal and send log
6517 if (!success_list.empty())
6519 int32 count = success_list.size();
6520 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6521 data.append(unitTarget->GetPackGUID()); // Victim GUID
6522 data.append(m_caster->GetPackGUID()); // Caster GUID
6523 data << uint32(m_spellInfo->Id); // Dispell spell id
6524 data << uint8(0); // not used
6525 data << uint32(count); // count
6526 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6528 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6529 data << uint32(spellInfo->Id); // Spell Id
6530 data << uint8(0); // 0 - steals !=0 transfers
6531 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6533 m_caster->SendMessageToSet(&data, true);
6538 void Spell::EffectKillCredit(uint32 i)
6540 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6541 return;
6543 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[i], unitTarget);
6546 void Spell::EffectQuestFail(uint32 i)
6548 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6549 return;
6551 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6554 void Spell::EffectActivateRune(uint32 eff_idx)
6556 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6557 return;
6559 Player *plr = (Player*)m_caster;
6561 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6562 return;
6564 for(uint32 j = 0; j < MAX_RUNES; ++j)
6566 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6568 plr->SetRuneCooldown(j, 0);
6573 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6575 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6576 ((Player*)unitTarget)->SetCanTitanGrip(true);
6579 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6581 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6582 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6583 return;
6585 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);