removed duplicated includes
[getmangos.git] / src / game / SpellEffects.cpp
blobaba08adcef8da2b277541e8dff4a5e36e8d88d07
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 "WorldSession.h"
23 #include "Opcodes.h"
24 #include "Log.h"
25 #include "UpdateMask.h"
26 #include "World.h"
27 #include "ObjectMgr.h"
28 #include "SpellMgr.h"
29 #include "Player.h"
30 #include "SkillExtraItems.h"
31 #include "Unit.h"
32 #include "Spell.h"
33 #include "DynamicObject.h"
34 #include "SpellAuras.h"
35 #include "Group.h"
36 #include "UpdateData.h"
37 #include "MapManager.h"
38 #include "ObjectAccessor.h"
39 #include "SharedDefines.h"
40 #include "Pet.h"
41 #include "GameObject.h"
42 #include "GossipDef.h"
43 #include "Creature.h"
44 #include "Totem.h"
45 #include "CreatureAI.h"
46 #include "BattleGroundMgr.h"
47 #include "BattleGround.h"
48 #include "BattleGroundEY.h"
49 #include "BattleGroundWS.h"
50 #include "VMapFactory.h"
51 #include "Language.h"
52 #include "SocialMgr.h"
53 #include "Util.h"
54 #include "TemporarySummon.h"
55 #include "ScriptCalls.h"
56 #include "SkillDiscovery.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::EffectUnused, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL, //154 unused
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
222 void Spell::EffectNULL(uint32 /*i*/)
224 sLog.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32 /*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i)
234 if(!unitTarget || unitTarget->isAlive())
235 return;
237 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
238 return;
240 if(!unitTarget->IsInWorld())
241 return;
243 Player* pTarget = ((Player*)unitTarget);
245 if(pTarget->isRessurectRequested()) // already have one active request
246 return;
248 uint32 health = damage;
249 uint32 mana = m_spellInfo->EffectMiscValue[i];
250 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
251 SendResurrectRequest(pTarget);
254 void Spell::EffectInstaKill(uint32 /*i*/)
256 if( !unitTarget || !unitTarget->isAlive() )
257 return;
259 // Demonic Sacrifice
260 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
262 uint32 entry = unitTarget->GetEntry();
263 uint32 spellID;
264 switch(entry)
266 case 416: spellID=18789; break; //imp
267 case 417: spellID=18792; break; //fellhunter
268 case 1860: spellID=18790; break; //void
269 case 1863: spellID=18791; break; //succubus
270 case 17252: spellID=35701; break; //fellguard
271 default:
272 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
273 return;
276 m_caster->CastSpell(m_caster,spellID,true);
279 if(m_caster==unitTarget) // prevent interrupt message
280 finish();
282 uint32 health = unitTarget->GetHealth();
283 m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i)
288 uint32 absorb = 0;
289 uint32 resist = 0;
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i];
296 m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
298 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
299 if(m_caster->GetTypeId() == TYPEID_PLAYER)
300 ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage);
303 void Spell::EffectSchoolDMG(uint32 effect_idx)
305 if( unitTarget && unitTarget->isAlive())
307 switch(m_spellInfo->SpellFamilyName)
309 case SPELLFAMILY_GENERIC:
311 //Gore
312 if(m_spellInfo->SpellIconID == 2269 )
314 damage+= rand()%2 ? damage : 0;
317 switch(m_spellInfo->Id) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
329 uint32 count = 0;
330 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
331 if(ihit->effectMask & (1<<effect_idx))
332 ++count;
334 damage /= count; // divide to all targets
335 break;
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage = unitTarget->GetHealth() / 2;
341 if(damage < 200)
342 damage = 200;
343 break;
345 // Intercept (warrior spell trigger)
346 case 20253:
347 case 61491:
349 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
350 break;
353 break;
356 case SPELLFAMILY_MAGE:
358 // Arcane Blast
359 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
361 m_caster->CastSpell(m_caster,36032,true);
363 break;
365 case SPELLFAMILY_WARRIOR:
367 // Bloodthirst
368 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
370 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
372 // Shield Slam
373 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
374 damage += int32(m_caster->GetShieldBlockValue());
375 // Victory Rush
376 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
378 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
379 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
381 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
382 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL)
383 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
384 // Heroic Throw ${$m1+$AP*.50}
385 else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL)
386 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
387 // Shockwave ${$m3/100*$AP}
388 else if(m_spellInfo->SpellFamilyFlags & 0x0000800000000000LL)
390 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
391 if (pct > 0)
392 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
393 break;
395 break;
397 case SPELLFAMILY_WARLOCK:
399 // Incinerate Rank 1 & 2
400 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
402 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
403 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
404 damage += int32(damage*0.25f);
406 break;
408 case SPELLFAMILY_PRIEST:
410 // Shadow Word: Death - deals damage equal to damage done to caster
411 if (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
412 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
413 break;
415 case SPELLFAMILY_DRUID:
417 // Ferocious Bite
418 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
420 // converts each extra point of energy into ($f1+$AP/410) additional damage
421 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
422 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
423 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
424 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
425 m_caster->SetPower(POWER_ENERGY,0);
427 // Rake
428 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
430 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
432 // Swipe
433 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
435 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
437 //Mangle Bonus for the initial damage of Lacerate and Rake
438 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
439 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
441 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
442 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
443 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
445 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
446 break;
449 break;
451 case SPELLFAMILY_ROGUE:
453 // Envenom
454 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
456 // consume from stack dozes not more that have combo-points
457 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
459 Aura *poison = 0;
460 // Lookup for Deadly poison (only attacker applied)
461 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
462 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
463 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
464 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
465 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
467 poison = *itr;
468 break;
470 // count consumed deadly poison doses at target
471 if (poison)
473 uint32 spellId = poison->GetId();
474 uint32 doses = poison->GetStackAmount();
475 if (doses > combo)
476 doses = combo;
477 for (int i=0; i< doses; i++)
478 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
479 damage *= doses;
480 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
482 // Eviscerate and Envenom Bonus Damage (item set effect)
483 if(m_caster->GetDummyAura(37169))
484 damage += ((Player*)m_caster)->GetComboPoints()*40;
487 // Eviscerate
488 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
490 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
492 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
493 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
495 // Eviscerate and Envenom Bonus Damage (item set effect)
496 if(m_caster->GetDummyAura(37169))
497 damage += combo*40;
500 // Gouge
501 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL)
503 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
505 // Instant Poison
506 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
508 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
510 // Wound Poison
511 else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL)
513 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
515 break;
517 case SPELLFAMILY_HUNTER:
519 // Mongoose Bite
520 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
522 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
524 // Counterattack
525 else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL)
527 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
529 // Arcane Shot
530 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
532 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
534 // Steady Shot
535 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
537 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
538 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
540 // Explosive Trap Effect
541 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
543 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
545 break;
547 case SPELLFAMILY_PALADIN:
549 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
550 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
552 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
553 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
554 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
555 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
556 // Get stack of Holy Vengeance on the target added by caster
557 uint32 stacks = 0;
558 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
559 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
560 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
562 stacks = (*itr)->GetStackAmount();
563 break;
565 // + 10% for each application of Holy Vengeance on the target
566 if(stacks)
567 damage += damage * stacks * 10 /100;
569 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
570 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
572 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
573 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
574 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
575 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
577 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
578 else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL)
580 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
581 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
582 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
583 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
585 // Hammer of the Righteous
586 else if(m_spellInfo->SpellFamilyFlags&0x0004000000000000LL)
588 // Add main hand dps * effect[2] amount
589 float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
590 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
591 damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
593 break;
597 if(damage >= 0)
598 m_damage+= damage;
602 void Spell::EffectDummy(uint32 i)
604 if(!unitTarget && !gameObjTarget && !itemTarget)
605 return;
607 // selection by spell family
608 switch(m_spellInfo->SpellFamilyName)
610 case SPELLFAMILY_GENERIC:
612 switch(m_spellInfo->Id )
614 case 8063: // Deviate Fish
616 if(m_caster->GetTypeId() != TYPEID_PLAYER)
617 return;
619 uint32 spell_id = 0;
620 switch(urand(1,5))
622 case 1: spell_id = 8064; break; // Sleepy
623 case 2: spell_id = 8065; break; // Invigorate
624 case 3: spell_id = 8066; break; // Shrink
625 case 4: spell_id = 8067; break; // Party Time!
626 case 5: spell_id = 8068; break; // Healthy Spirit
628 m_caster->CastSpell(m_caster,spell_id,true,NULL);
629 return;
631 case 8213: // Savory Deviate Delight
633 if(m_caster->GetTypeId() != TYPEID_PLAYER)
634 return;
636 uint32 spell_id = 0;
637 switch(urand(1,2))
639 // Flip Out - ninja
640 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
641 // Yaaarrrr - pirate
642 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
644 m_caster->CastSpell(m_caster,spell_id,true,NULL);
645 return;
647 case 8593: // Symbol of life (restore creature to life)
648 case 31225: // Shimmering Vessel (restore creature to life)
650 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
651 return;
652 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
653 return;
655 case 12162: // Deep wounds
656 case 12850: // (now good common check for this spells)
657 case 12868:
659 if(!unitTarget)
660 return;
662 float damage;
663 // DW should benefit of attack power, damage percent mods etc.
664 // TODO: check if using offhand damage is correct and if it should be divided by 2
665 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
666 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
667 else
668 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
670 switch (m_spellInfo->Id)
672 case 12850: damage *= 0.2f; break;
673 case 12162: damage *= 0.4f; break;
674 case 12868: damage *= 0.6f; break;
675 default:
676 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
677 return;
680 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
681 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
682 return;
684 case 13120: // net-o-matic
686 if(!unitTarget)
687 return;
689 uint32 spell_id = 0;
691 uint32 roll = urand(0, 99);
693 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
694 spell_id = 16566;
695 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
696 spell_id = 13119;
697 else // normal root
698 spell_id = 13099;
700 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
701 return;
703 case 13567: // Dummy Trigger
705 // can be used for different aura triggering, so select by aura
706 if(!m_triggeredByAuraSpell || !unitTarget)
707 return;
709 switch(m_triggeredByAuraSpell->Id)
711 case 26467: // Persistent Shield
712 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
713 break;
714 default:
715 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
716 break;
718 return;
720 case 15998: // Capture Worg Pup
721 case 29435: // Capture Female Kaliri Hatchling
723 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
724 return;
726 Creature* creatureTarget = (Creature*)unitTarget;
727 creatureTarget->setDeathState(JUST_DIED);
728 creatureTarget->RemoveCorpse();
729 creatureTarget->SetHealth(0); // just for nice GM-mode view
730 return;
732 case 16589: // Noggenfogger Elixir
734 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
735 return;
737 uint32 spell_id = 0;
738 switch(urand(1,3))
740 case 1: spell_id = 16595; break;
741 case 2: spell_id = 16593; break;
742 default:spell_id = 16591; break;
745 m_caster->CastSpell(m_caster,spell_id,true,NULL);
746 return;
748 case 17251: // Spirit Healer Res
750 if(!unitTarget || !m_originalCaster)
751 return;
753 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
755 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
756 data << unitTarget->GetGUID();
757 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
759 return;
761 case 17271: // Test Fetid Skull
763 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
764 return;
766 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
768 m_caster->CastSpell(m_caster,spell_id,true,NULL);
769 return;
771 case 20577: // Cannibalize
772 if (unitTarget)
773 m_caster->CastSpell(m_caster,20578,false,NULL);
774 return;
775 case 23019: // Crystal Prison Dummy DND
777 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
778 return;
780 Creature* creatureTarget = (Creature*)unitTarget;
781 if(creatureTarget->isPet())
782 return;
784 GameObject* pGameObj = new GameObject;
786 Map *map = creatureTarget->GetMap();
788 // create before death for get proper coordinates
789 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
790 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
791 creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) )
793 delete pGameObj;
794 return;
797 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
798 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
799 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
800 pGameObj->SetSpellId(m_spellInfo->Id);
802 creatureTarget->setDeathState(JUST_DIED);
803 creatureTarget->RemoveCorpse();
804 creatureTarget->SetHealth(0); // just for nice GM-mode view
806 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
807 map->Add(pGameObj);
809 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
810 data << uint64(pGameObj->GetGUID());
811 m_caster->SendMessageToSet(&data,true);
813 return;
815 case 23074: // Arcanite Dragonling
816 if (!m_CastItem) return;
817 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
818 return;
819 case 23075: // Mithril Mechanical Dragonling
820 if (!m_CastItem) return;
821 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
822 return;
823 case 23076: // Mechanical Dragonling
824 if (!m_CastItem) return;
825 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
826 return;
827 case 23133: // Gnomish Battle Chicken
828 if (!m_CastItem) return;
829 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
830 return;
831 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
833 int32 r = irand(0, 119);
834 if ( r < 20 ) // 1/6 polymorph
835 m_caster->CastSpell(m_caster,23444,true);
836 else if ( r < 100 ) // 4/6 evil twin
837 m_caster->CastSpell(m_caster,23445,true);
838 else // 1/6 miss the target
839 m_caster->CastSpell(m_caster,36902,true);
840 return;
842 case 23453: // Ultrasafe Transporter: Gadgetzan
843 if ( roll_chance_i(50) ) // success
844 m_caster->CastSpell(m_caster,23441,true);
845 else // failure
846 m_caster->CastSpell(m_caster,23446,true);
847 return;
848 case 23645: // Hourglass Sand
849 m_caster->RemoveAurasDueToSpell(23170);
850 return;
851 case 23725: // Gift of Life (warrior bwl trinket)
852 m_caster->CastSpell(m_caster,23782,true);
853 m_caster->CastSpell(m_caster,23783,true);
854 return;
855 case 25860: // Reindeer Transformation
857 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
858 return;
860 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
861 float speed = m_caster->GetSpeedRate(MOVE_RUN);
863 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
865 //5 different spells used depending on mounted speed and if mount can fly or not
866 if (flyspeed >= 4.1f)
867 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
868 else if (flyspeed >= 3.8f)
869 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
870 else if (flyspeed >= 1.6f)
871 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
872 else if (speed >= 2.0f)
873 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
874 else
875 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
877 return;
879 //case 26074: // Holiday Cheer
880 // return; -- implemented at client side
881 case 28006: // Arcane Cloaking
883 if( unitTarget->GetTypeId() == TYPEID_PLAYER )
884 m_caster->CastSpell(unitTarget,29294,true);
885 return;
887 case 28730: // Arcane Torrent (Mana)
889 Aura * dummy = m_caster->GetDummyAura(28734);
890 if (dummy)
892 int32 bp = damage * dummy->GetStackAmount();
893 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
894 m_caster->RemoveAurasDueToSpell(28734);
896 return;
898 case 29200: // Purify Helboar Meat
900 if( m_caster->GetTypeId() != TYPEID_PLAYER )
901 return;
903 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
905 m_caster->CastSpell(m_caster,spell_id,true,NULL);
906 return;
908 case 29858: // Soulshatter
909 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
910 m_caster->CastSpell(unitTarget,32835,true);
911 return;
912 case 30458: // Nigh Invulnerability
913 if (!m_CastItem) return;
914 if(roll_chance_i(86)) // success
915 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
916 else // backfire in 14% casts
917 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
918 return;
919 case 30507: // Poultryizer
920 if (!m_CastItem) return;
921 if(roll_chance_i(80)) // success
922 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
923 else // backfire 20%
924 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
925 return;
926 case 33060: // Make a Wish
928 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
929 return;
931 uint32 spell_id = 0;
933 switch(urand(1,5))
935 case 1: spell_id = 33053; break;
936 case 2: spell_id = 33057; break;
937 case 3: spell_id = 33059; break;
938 case 4: spell_id = 33062; break;
939 case 5: spell_id = 33064; break;
942 m_caster->CastSpell(m_caster,spell_id,true,NULL);
943 return;
945 case 35745:
947 uint32 spell_id;
948 switch(m_caster->GetAreaId())
950 case 3900: spell_id = 35743; break;
951 case 3742: spell_id = 35744; break;
952 default: return;
955 m_caster->CastSpell(m_caster,spell_id,true);
956 return;
958 case 37674: // Chaos Blast
960 if(!unitTarget)
961 return;
963 int32 basepoints0 = 100;
964 m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true);
965 return;
967 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
969 // selecting one from Bloodstained Fortune item
970 uint32 newitemid;
971 switch(urand(1,20))
973 case 1: newitemid = 32688; break;
974 case 2: newitemid = 32689; break;
975 case 3: newitemid = 32690; break;
976 case 4: newitemid = 32691; break;
977 case 5: newitemid = 32692; break;
978 case 6: newitemid = 32693; break;
979 case 7: newitemid = 32700; break;
980 case 8: newitemid = 32701; break;
981 case 9: newitemid = 32702; break;
982 case 10: newitemid = 32703; break;
983 case 11: newitemid = 32704; break;
984 case 12: newitemid = 32705; break;
985 case 13: newitemid = 32706; break;
986 case 14: newitemid = 32707; break;
987 case 15: newitemid = 32708; break;
988 case 16: newitemid = 32709; break;
989 case 17: newitemid = 32710; break;
990 case 18: newitemid = 32711; break;
991 case 19: newitemid = 32712; break;
992 case 20: newitemid = 32713; break;
993 default:
994 return;
997 DoCreateItem(i,newitemid);
998 return;
1000 // Demon Broiled Surprise
1001 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1002 case 43723:
1004 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1005 return;
1007 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1008 return;
1011 case 44875: // Complete Raptor Capture
1013 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1014 return;
1016 Creature* creatureTarget = (Creature*)unitTarget;
1018 creatureTarget->setDeathState(JUST_DIED);
1019 creatureTarget->RemoveCorpse();
1020 creatureTarget->SetHealth(0); // just for nice GM-mode view
1022 //cast spell Raptor Capture Credit
1023 m_caster->CastSpell(m_caster,42337,true,NULL);
1024 return;
1026 case 34665: //Administer Antidote
1028 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1029 return;
1031 if(!unitTarget)
1032 return;
1034 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1035 if(!tempSummon)
1036 return;
1038 uint32 health = tempSummon->GetHealth();
1040 float x = tempSummon->GetPositionX();
1041 float y = tempSummon->GetPositionY();
1042 float z = tempSummon->GetPositionZ();
1043 float o = tempSummon->GetOrientation();
1044 tempSummon->UnSummon();
1046 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1047 if (!pCreature)
1048 return;
1050 pCreature->SetHealth(health);
1051 ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
1053 if (pCreature->AI())
1054 pCreature->AI()->AttackStart(m_caster);
1056 return;
1058 case 44997: // Converting Sentry
1060 //Converted Sentry Credit
1061 m_caster->CastSpell(m_caster, 45009, true);
1062 return;
1064 case 45030: // Impale Emissary
1066 // Emissary of Hate Credit
1067 m_caster->CastSpell(m_caster, 45088, true);
1068 return;
1070 case 50243: // Teach Language
1072 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1073 return;
1075 // spell has a 1/3 chance to trigger one of the below
1076 if(roll_chance_i(66))
1077 return;
1078 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1080 // 1000001 - gnomish binary
1081 m_caster->CastSpell(m_caster, 50242, true);
1083 else
1085 // 01001000 - goblin binary
1086 m_caster->CastSpell(m_caster, 50246, true);
1089 return;
1091 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1093 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1094 return;
1096 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1097 bg->EventPlayerDroppedFlag((Player*)m_caster);
1099 m_caster->CastSpell(m_caster, 30452, true, NULL);
1100 return;
1102 case 53341:
1103 case 53343:
1105 m_caster->CastSpell(m_caster,54586,true);
1106 return;
1108 case 58418: // Portal to Orgrimmar
1110 if(!unitTarget)
1111 return;
1113 unitTarget->CastSpell(unitTarget, 58419, true);
1114 break;
1116 case 58420: // Portal to Stormwind
1118 if(!unitTarget)
1119 return;
1121 unitTarget->CastSpell(unitTarget, 58421, true);
1122 break;
1126 //All IconID Check in there
1127 switch(m_spellInfo->SpellIconID)
1129 // Berserking (troll racial traits)
1130 case 1661:
1132 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1133 int32 melee_mod = 10;
1134 if (healthPerc <= 40)
1135 melee_mod = 30;
1136 if (healthPerc < 100 && healthPerc > 40)
1137 melee_mod = 10+(100-healthPerc)/3;
1139 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1140 int32 hasteModBasePoints1 = (5-melee_mod);
1141 int32 hasteModBasePoints2 = 5;
1143 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1144 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1145 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1146 return;
1149 break;
1151 case SPELLFAMILY_MAGE:
1152 switch(m_spellInfo->Id )
1154 case 11958: // Cold Snap
1156 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1157 return;
1159 // immediately finishes the cooldown on Frost spells
1160 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1161 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1163 if (itr->second->state == PLAYERSPELL_REMOVED)
1164 continue;
1166 uint32 classspell = itr->first;
1167 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1169 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1170 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1171 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1173 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1175 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1176 data << uint32(classspell);
1177 data << uint64(m_caster->GetGUID());
1178 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1181 return;
1183 case 32826:
1185 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1187 //Polymorph Cast Visual Rank 1
1188 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1189 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1191 return;
1194 break;
1195 case SPELLFAMILY_WARRIOR:
1196 // Charge
1197 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1199 int32 chargeBasePoints0 = damage;
1200 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1201 return;
1203 // Execute
1204 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1206 if(!unitTarget)
1207 return;
1209 uint32 rage = m_caster->GetPower(POWER_RAGE);
1210 // Glyph of Execution bonus
1211 if (Aura *aura = m_caster->GetDummyAura(58367))
1212 rage+=aura->GetModifier()->m_amount;
1214 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1215 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1216 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1217 m_caster->SetPower(POWER_RAGE,0);
1218 return;
1220 // Slam
1221 if(m_spellInfo->SpellFamilyFlags & 0x0000000000200000LL)
1223 if(!unitTarget)
1224 return;
1225 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1226 m_damage+=damage;
1227 return;
1229 switch(m_spellInfo->Id)
1231 // Warrior's Wrath
1232 case 21977:
1234 if(!unitTarget)
1235 return;
1236 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1237 return;
1239 // Last Stand
1240 case 12975:
1242 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1243 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1244 return;
1246 // Bloodthirst
1247 case 23881:
1249 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1250 return;
1253 break;
1254 case SPELLFAMILY_WARLOCK:
1255 // Life Tap
1256 if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL)
1258 // In 303 exist spirit depend
1259 uint32 spirit = m_caster->GetStat(STAT_SPIRIT);
1260 switch (m_spellInfo->Id)
1262 case 1454: damage+=spirit; break;
1263 case 1455: damage+=spirit*15/10; break;
1264 case 1456: damage+=spirit*2; break;
1265 case 11687: damage+=spirit*25/10; break;
1266 case 11688:
1267 case 11689:
1268 case 27222:
1269 case 57946: damage+=spirit*3; break;
1270 default:
1271 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1272 return;
1274 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1275 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1276 if(int32(unitTarget->GetHealth()) > damage)
1278 // Shouldn't Appear in Combat Log
1279 unitTarget->ModifyHealth(-damage);
1281 int32 mana = damage;
1282 // Improved Life Tap mod
1283 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1284 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1286 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1287 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1289 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1291 // Mana Feed
1292 int32 manaFeedVal = 0;
1293 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1294 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1296 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1297 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1299 if(manaFeedVal > 0)
1301 manaFeedVal = manaFeedVal * mana / 100;
1302 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1305 else
1306 SendCastResult(SPELL_FAILED_FIZZLE);
1307 return;
1309 break;
1310 case SPELLFAMILY_PRIEST:
1311 // Penance
1312 if (m_spellInfo->SpellFamilyFlags & 0x0080000000000000LL)
1314 if (!unitTarget)
1315 return;
1317 int hurt = 0;
1318 int heal = 0;
1319 switch(m_spellInfo->Id)
1321 case 47540: hurt = 47758; heal = 47757; break;
1322 case 53005: hurt = 53001; heal = 52986; break;
1323 case 53006: hurt = 53002; heal = 52987; break;
1324 case 53007: hurt = 53003; heal = 52988; break;
1325 default:
1326 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1327 return;
1329 if (m_caster->IsFriendlyTo(unitTarget))
1330 m_caster->CastSpell(unitTarget, heal, true, 0);
1331 else
1332 m_caster->CastSpell(unitTarget, hurt, true, 0);
1333 return;
1335 switch(m_spellInfo->Id )
1337 case 28598: // Touch of Weakness triggered spell
1339 if(!unitTarget || !m_triggeredByAuraSpell)
1340 return;
1342 uint32 spellid = 0;
1343 switch(m_triggeredByAuraSpell->Id)
1345 case 2652: spellid = 2943; break; // Rank 1
1346 case 19261: spellid = 19249; break; // Rank 2
1347 case 19262: spellid = 19251; break; // Rank 3
1348 case 19264: spellid = 19252; break; // Rank 4
1349 case 19265: spellid = 19253; break; // Rank 5
1350 case 19266: spellid = 19254; break; // Rank 6
1351 case 25461: spellid = 25460; break; // Rank 7
1352 default:
1353 sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id);
1354 return;
1356 m_caster->CastSpell(unitTarget, spellid, true, NULL);
1357 return;
1360 break;
1361 case SPELLFAMILY_DRUID:
1362 break;
1363 case SPELLFAMILY_ROGUE:
1364 switch(m_spellInfo->Id )
1366 case 5938: // Shiv
1368 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1369 return;
1371 Player *pCaster = ((Player*)m_caster);
1373 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1374 if(!item)
1375 return;
1377 // all poison enchantments is temporary
1378 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1379 if(!enchant_id)
1380 return;
1382 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1383 if(!pEnchant)
1384 return;
1386 for (int s=0;s<3;s++)
1388 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1389 continue;
1391 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1392 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1393 continue;
1395 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1398 m_caster->CastSpell(unitTarget, 5940, true);
1399 return;
1401 case 14185: // Preparation Rogue
1403 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1404 return;
1406 //immediately finishes the cooldown on certain Rogue abilities
1407 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1408 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1410 uint32 classspell = itr->first;
1411 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1413 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL))
1415 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1417 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1418 data << uint32(classspell);
1419 data << uint64(m_caster->GetGUID());
1420 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1423 return;
1425 case 31231: // Cheat Death
1427 m_caster->CastSpell(m_caster,45182,true);
1428 return;
1431 break;
1432 case SPELLFAMILY_HUNTER:
1433 // Steady Shot
1434 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1436 if( !unitTarget || !unitTarget->isAlive())
1437 return;
1439 bool found = false;
1441 // check dazed affect
1442 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1443 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1445 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1447 found = true;
1448 break;
1452 if(found)
1453 m_damage+= damage;
1454 return;
1457 switch(m_spellInfo->Id)
1459 case 23989: //Readiness talent
1461 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1462 return;
1464 //immediately finishes the cooldown for hunter abilities
1465 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1466 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1468 uint32 classspell = itr->first;
1469 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1471 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1473 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1475 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1476 data << uint32(classspell);
1477 data << uint64(m_caster->GetGUID());
1478 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1481 return;
1483 case 37506: // Scatter Shot
1485 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1486 return;
1488 // break Auto Shot and autohit
1489 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1490 m_caster->AttackStop();
1491 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1492 return;
1495 break;
1496 case SPELLFAMILY_PALADIN:
1497 switch(m_spellInfo->SpellIconID)
1499 case 156: // Holy Shock
1501 if(!unitTarget)
1502 return;
1504 int hurt = 0;
1505 int heal = 0;
1507 switch(m_spellInfo->Id)
1509 case 20473: hurt = 25912; heal = 25914; break;
1510 case 20929: hurt = 25911; heal = 25913; break;
1511 case 20930: hurt = 25902; heal = 25903; break;
1512 case 27174: hurt = 27176; heal = 27175; break;
1513 case 33072: hurt = 33073; heal = 33074; break;
1514 case 48824: hurt = 48822; heal = 48820; break;
1515 case 48825: hurt = 48823; heal = 48821; break;
1516 default:
1517 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1518 return;
1521 if(m_caster->IsFriendlyTo(unitTarget))
1522 m_caster->CastSpell(unitTarget, heal, true, 0);
1523 else
1524 m_caster->CastSpell(unitTarget, hurt, true, 0);
1526 return;
1528 case 561: // Judgement of command
1530 if(!unitTarget)
1531 return;
1533 uint32 spell_id = m_currentBasePoints[i]+1;
1534 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1535 if(!spell_proto)
1536 return;
1538 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1540 // decreased damage (/2) for non-stunned target.
1541 SpellModifier *mod = new SpellModifier;
1542 mod->op = SPELLMOD_DAMAGE;
1543 mod->value = -50;
1544 mod->type = SPELLMOD_PCT;
1545 mod->spellId = m_spellInfo->Id;
1546 mod->mask = 0x0000020000000000LL;
1547 mod->mask2= 0LL;
1549 ((Player*)m_caster)->AddSpellMod(mod, true);
1550 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1551 // mod deleted
1552 ((Player*)m_caster)->AddSpellMod(mod, false);
1554 else
1555 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1557 return;
1561 switch(m_spellInfo->Id)
1563 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1564 case 20187:
1566 if (!unitTarget)
1567 return;
1568 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1569 return;
1571 case 31789: // Righteous Defense (step 1)
1573 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1575 // non-standard cast requirement check
1576 if (!unitTarget || unitTarget->getAttackers().empty())
1578 // clear cooldown at fail
1579 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1581 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1583 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1584 data << uint32(m_spellInfo->Id);
1585 data << uint64(m_caster->GetGUID());
1586 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1589 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1590 return;
1593 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1594 // Clear targets for eff 1
1595 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1596 ihit->effectMask &= ~(1<<1);
1598 // not empty (checked)
1599 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1601 // chance to be selected from list
1602 float chance = 100.0f/attackers.size();
1603 uint32 count=0;
1604 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1606 if(!roll_chance_f(chance))
1607 continue;
1608 ++count;
1609 AddUnitTarget((*aItr), 1);
1612 // now let next effect cast spell at each target.
1613 return;
1615 case 37877: // Blessing of Faith
1617 if(!unitTarget)
1618 return;
1620 uint32 spell_id = 0;
1621 switch(unitTarget->getClass())
1623 case CLASS_DRUID: spell_id = 37878; break;
1624 case CLASS_PALADIN: spell_id = 37879; break;
1625 case CLASS_PRIEST: spell_id = 37880; break;
1626 case CLASS_SHAMAN: spell_id = 37881; break;
1627 default: return; // ignore for not healing classes
1630 m_caster->CastSpell(m_caster,spell_id,true);
1631 return;
1634 break;
1635 case SPELLFAMILY_SHAMAN:
1636 //Shaman Rockbiter Weapon
1637 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1639 // TODO: use expect spell for enchant (if exist talent)
1640 // In 3.0.3 no mods present for rockbiter
1641 uint32 spell_id = 0;
1642 switch(m_spellInfo->Id)
1644 case 8017: spell_id = 36494; break; // Rank 1
1645 case 8018: spell_id = 36750; break; // Rank 2
1646 case 8019: spell_id = 36755; break; // Rank 3
1647 case 10399: spell_id = 36759; break; // Rank 4
1648 default:
1649 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1650 return;
1653 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1655 if(!spellInfo)
1657 sLog.outError("WORLD: unknown spell id %i\n", spell_id);
1658 return;
1661 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1662 return;
1664 for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1666 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1668 if(item->IsFitToSpellRequirements(m_spellInfo))
1670 Spell *spell = new Spell(m_caster, spellInfo, true);
1672 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1673 // at calculation applied affect from Elemental Weapons talent
1674 // real enchantment damage-1
1675 spell->m_currentBasePoints[1] = damage-1;
1677 SpellCastTargets targets;
1678 targets.setItemTarget( item );
1679 spell->prepare(&targets);
1683 return;
1685 // Healing Stream Totem
1686 if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
1688 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1689 return;
1691 // Mana Spring Totem
1692 if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
1694 if(unitTarget->getPowerType()!=POWER_MANA)
1695 return;
1696 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1697 return;
1699 if(m_spellInfo->Id == 39610) // Mana Tide Totem effect
1701 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1702 return;
1703 // Glyph of Mana Tide
1704 Unit *owner = m_caster->GetOwner();
1705 if (owner)
1706 if (Aura *dummy = owner->GetDummyAura(55441))
1707 damage+=dummy->GetModifier()->m_amount;
1708 // Regenerate 6% of Total Mana Every 3 secs
1709 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1710 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1711 return;
1713 // Lava Lash
1714 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1716 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1717 return;
1718 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1719 if (item)
1721 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1722 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1723 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1725 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1726 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000200000LL &&
1727 (*itr)->GetCastItemGUID() == item->GetGUID())
1729 m_damage += m_damage * damage / 100;
1730 return;
1734 return;
1736 break;
1739 // pet auras
1740 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1742 m_caster->AddPetAura(petSpell);
1743 return;
1747 void Spell::EffectTriggerSpellWithValue(uint32 i)
1749 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1751 // normal case
1752 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1754 if(!spellInfo)
1756 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id);
1757 return;
1760 int32 bp = damage;
1761 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1764 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1766 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1767 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1769 if(!spellInfo)
1771 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1772 return;
1775 finish();
1776 Spell *spell = new Spell(m_caster, spellInfo, true);
1778 SpellCastTargets targets;
1779 targets.setUnitTarget( unitTarget);
1780 spell->prepare(&targets);
1782 m_caster->SetCurrentCastedSpell(spell);
1783 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1787 void Spell::EffectForceCast(uint32 i)
1789 if( !unitTarget )
1790 return;
1792 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1794 // normal case
1795 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1797 if(!spellInfo)
1799 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1800 return;
1803 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1806 void Spell::EffectTriggerSpell(uint32 i)
1808 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1810 // special cases
1811 switch(triggered_spell_id)
1813 // Vanish
1814 case 18461:
1816 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1817 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1818 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1820 // if this spell is given to NPC it must handle rest by it's own AI
1821 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1822 return;
1824 // get highest rank of the Stealth spell
1825 uint32 spellId = 0;
1826 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1827 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1829 // only highest rank is shown in spell book, so simply check if shown in spell book
1830 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1831 continue;
1833 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1834 if (!spellInfo)
1835 continue;
1837 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1839 spellId = spellInfo->Id;
1840 break;
1844 // no Stealth spell found
1845 if (!spellId)
1846 return;
1848 // reset cooldown on it if needed
1849 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1850 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1852 m_caster->CastSpell(m_caster, spellId, true);
1853 return;
1855 // just skip
1856 case 23770: // Sayge's Dark Fortune of *
1857 // not exist, common cooldown can be implemented in scripts if need.
1858 return;
1859 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1860 case 29284:
1862 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1863 if (!spell)
1864 return;
1866 for (int i=0; i < spell->StackAmount; ++i)
1867 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1868 return;
1870 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1871 case 29286:
1873 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1874 if (!spell)
1875 return;
1877 for (int i=0; i < spell->StackAmount; ++i)
1878 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1879 return;
1881 // Righteous Defense
1882 case 31980:
1884 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1885 return;
1887 // Cloak of Shadows
1888 case 35729 :
1890 Unit::AuraMap& Auras = m_caster->GetAuras();
1891 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1893 // remove all harmful spells on you...
1894 if( // ignore positive and passive auras
1895 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1896 // ignore physical auras
1897 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
1899 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1900 iter = Auras.begin();
1903 return;
1905 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1906 case 41967:
1908 if (Unit *pet = m_caster->GetPet())
1909 pet->CastSpell(pet, 28305, true);
1910 return;
1914 // normal case
1915 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1917 if(!spellInfo)
1919 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1920 return;
1923 // some triggered spells require specific equipment
1924 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1926 // main hand weapon required
1927 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1929 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1931 // skip spell if no weapon in slot or broken
1932 if(!item || item->IsBroken() )
1933 return;
1935 // skip spell if weapon not fit to triggered spell
1936 if(!item->IsFitToSpellRequirements(spellInfo))
1937 return;
1940 // offhand hand weapon required
1941 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1943 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1945 // skip spell if no weapon in slot or broken
1946 if(!item || item->IsBroken() )
1947 return;
1949 // skip spell if weapon not fit to triggered spell
1950 if(!item->IsFitToSpellRequirements(spellInfo))
1951 return;
1955 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1956 bool instant = false;
1957 for(uint32 j = i+1; j < 3; ++j)
1959 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
1961 instant = true;
1962 break;
1966 if(instant)
1968 if (unitTarget)
1969 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
1971 else
1972 m_TriggerSpells.push_back(spellInfo);
1975 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
1977 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
1979 // normal case
1980 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1982 if(!spellInfo)
1984 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
1985 m_spellInfo->Id,effect_idx,triggered_spell_id);
1986 return;
1989 if (m_CastItem)
1990 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1992 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
1995 void Spell::EffectTeleportUnits(uint32 i)
1997 if(!unitTarget || unitTarget->isInFlight())
1998 return;
2000 switch (m_spellInfo->EffectImplicitTargetB[i])
2002 case TARGET_INNKEEPER_COORDINATES:
2004 // Only players can teleport to innkeeper
2005 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2006 return;
2008 ((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);
2009 return;
2011 case TARGET_TABLE_X_Y_Z_COORDINATES:
2013 // TODO: Only players can teleport?
2014 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2015 return;
2016 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2017 if(!st)
2019 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id );
2020 return;
2022 ((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);
2023 break;
2025 case TARGET_BEHIND_VICTIM:
2027 // Get selected target for player (or victim for units)
2028 Unit *pTarget = NULL;
2029 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2030 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2031 else
2032 pTarget = m_caster->getVictim();
2033 // No target present - return
2034 if (!pTarget)
2035 return;
2036 // Init dest coordinates
2037 uint32 mapid = m_caster->GetMapId();
2038 float x = m_targets.m_destX;
2039 float y = m_targets.m_destY;
2040 float z = m_targets.m_destZ;
2041 float orientation = pTarget->GetOrientation();
2042 // Teleport
2043 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2044 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2045 else
2047 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2048 WorldPacket data;
2049 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2050 unitTarget->SendMessageToSet(&data, false);
2052 return;
2054 default:
2056 // If not exist data for dest location - return
2057 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2059 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2060 return;
2062 // Init dest coordinates
2063 uint32 mapid = m_caster->GetMapId();
2064 float x = m_targets.m_destX;
2065 float y = m_targets.m_destY;
2066 float z = m_targets.m_destZ;
2067 float orientation = unitTarget->GetOrientation();
2068 // Teleport
2069 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2070 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2071 else
2073 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2074 WorldPacket data;
2075 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2076 unitTarget->SendMessageToSet(&data, false);
2078 return;
2082 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2083 switch ( m_spellInfo->Id )
2085 // Dimensional Ripper - Everlook
2086 case 23442:
2088 int32 r = irand(0, 119);
2089 if ( r >= 70 ) // 7/12 success
2091 if ( r < 100 ) // 4/12 evil twin
2092 m_caster->CastSpell(m_caster,23445,true);
2093 else // 1/12 fire
2094 m_caster->CastSpell(m_caster,23449,true);
2096 return;
2098 // Ultrasafe Transporter: Toshley's Station
2099 case 36941:
2101 if ( roll_chance_i(50) ) // 50% success
2103 int32 rand_eff = urand(1,7);
2104 switch ( rand_eff )
2106 case 1:
2107 // soul split - evil
2108 m_caster->CastSpell(m_caster,36900,true);
2109 break;
2110 case 2:
2111 // soul split - good
2112 m_caster->CastSpell(m_caster,36901,true);
2113 break;
2114 case 3:
2115 // Increase the size
2116 m_caster->CastSpell(m_caster,36895,true);
2117 break;
2118 case 4:
2119 // Decrease the size
2120 m_caster->CastSpell(m_caster,36893,true);
2121 break;
2122 case 5:
2123 // Transform
2125 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2126 m_caster->CastSpell(m_caster,36897,true);
2127 else
2128 m_caster->CastSpell(m_caster,36899,true);
2129 break;
2131 case 6:
2132 // chicken
2133 m_caster->CastSpell(m_caster,36940,true);
2134 break;
2135 case 7:
2136 // evil twin
2137 m_caster->CastSpell(m_caster,23445,true);
2138 break;
2141 return;
2143 // Dimensional Ripper - Area 52
2144 case 36890:
2146 if ( roll_chance_i(50) ) // 50% success
2148 int32 rand_eff = urand(1,4);
2149 switch ( rand_eff )
2151 case 1:
2152 // soul split - evil
2153 m_caster->CastSpell(m_caster,36900,true);
2154 break;
2155 case 2:
2156 // soul split - good
2157 m_caster->CastSpell(m_caster,36901,true);
2158 break;
2159 case 3:
2160 // Increase the size
2161 m_caster->CastSpell(m_caster,36895,true);
2162 break;
2163 case 4:
2164 // Transform
2166 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2167 m_caster->CastSpell(m_caster,36897,true);
2168 else
2169 m_caster->CastSpell(m_caster,36899,true);
2170 break;
2174 return;
2179 void Spell::EffectApplyAura(uint32 i)
2181 if(!unitTarget)
2182 return;
2184 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2185 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2186 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2187 return;
2189 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2190 if(!caster)
2191 return;
2193 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2195 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2197 // Now Reduce spell duration using data received at spell hit
2198 int32 duration = Aur->GetAuraMaxDuration();
2199 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2200 Aur->setDiminishGroup(m_diminishGroup);
2202 // if Aura removed and deleted, do not continue.
2203 if(duration== 0 && !(Aur->IsPermanent()))
2205 delete Aur;
2206 return;
2209 if(duration != Aur->GetAuraMaxDuration())
2211 Aur->SetAuraMaxDuration(duration);
2212 Aur->SetAuraDuration(duration);
2215 bool added = unitTarget->AddAura(Aur);
2217 // Aura not added and deleted in AddAura call;
2218 if (!added)
2219 return;
2221 // found crash at character loading, broken pointer to Aur...
2222 // Aur was deleted in AddAura()...
2223 if(!Aur)
2224 return;
2226 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2227 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2228 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2231 void Spell::EffectUnlearnSpecialization( uint32 i )
2233 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2234 return;
2236 Player *_player = (Player*)unitTarget;
2237 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2239 _player->removeSpell(spellToUnlearn);
2241 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2244 void Spell::EffectPowerDrain(uint32 i)
2246 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2247 return;
2249 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2251 if(!unitTarget)
2252 return;
2253 if(!unitTarget->isAlive())
2254 return;
2255 if(unitTarget->getPowerType() != drain_power)
2256 return;
2257 if(damage < 0)
2258 return;
2260 uint32 curPower = unitTarget->GetPower(drain_power);
2262 //add spell damage bonus
2263 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2265 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2266 uint32 power = damage;
2267 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2268 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2270 int32 new_damage;
2271 if(curPower < power)
2272 new_damage = curPower;
2273 else
2274 new_damage = power;
2276 unitTarget->ModifyPower(drain_power,-new_damage);
2278 // Don`t restore from self drain
2279 if(drain_power == POWER_MANA && m_caster != unitTarget)
2281 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2282 if(manaMultiplier==0)
2283 manaMultiplier = 1;
2285 if(Player *modOwner = m_caster->GetSpellModOwner())
2286 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2288 int32 gain = int32(new_damage*manaMultiplier);
2290 m_caster->ModifyPower(POWER_MANA,gain);
2291 //send log
2292 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2296 void Spell::EffectSendEvent(uint32 EffectIndex)
2298 if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround())
2300 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
2301 if(bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2303 switch(m_spellInfo->Id)
2305 case 23333: // Pickup Horde Flag
2306 /*do not uncomment .
2307 if(bg->GetTypeID()==BATTLEGROUND_WS)
2308 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2309 sLog.outDebug("Send Event Horde Flag Picked Up");
2310 break;
2311 /* not used :
2312 case 23334: // Drop Horde Flag
2313 if(bg->GetTypeID()==BATTLEGROUND_WS)
2314 bg->EventPlayerDroppedFlag((Player*)m_caster);
2315 sLog.outDebug("Drop Horde Flag");
2316 break;
2318 case 23335: // Pickup Alliance Flag
2319 /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2320 if(bg->GetTypeID()==BATTLEGROUND_WS)
2321 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2322 sLog.outDebug("Send Event Alliance Flag Picked Up");
2323 break;
2324 /* not used :
2325 case 23336: // Drop Alliance Flag
2326 if(bg->GetTypeID()==BATTLEGROUND_WS)
2327 bg->EventPlayerDroppedFlag((Player*)m_caster);
2328 sLog.outDebug("Drop Alliance Flag");
2329 break;
2330 case 23385: // Alliance Flag Returns
2331 if(bg->GetTypeID()==BATTLEGROUND_WS)
2332 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2333 sLog.outDebug("Alliance Flag Returned");
2334 break;
2335 case 23386: // Horde Flag Returns
2336 if(bg->GetTypeID()==BATTLEGROUND_WS)
2337 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2338 sLog.outDebug("Horde Flag Returned");
2339 break;*/
2340 case 34976:
2342 if(bg->GetTypeID()==BATTLEGROUND_EY)
2343 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2345 break;
2346 default:
2347 sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2348 break;
2352 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2353 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2356 void Spell::EffectPowerBurn(uint32 i)
2358 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2359 return;
2361 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2363 if(!unitTarget)
2364 return;
2365 if(!unitTarget->isAlive())
2366 return;
2367 if(unitTarget->getPowerType()!=powertype)
2368 return;
2369 if(damage < 0)
2370 return;
2372 int32 curPower = int32(unitTarget->GetPower(powertype));
2374 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2375 uint32 power = damage;
2376 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2377 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2379 int32 new_damage = (curPower < power) ? curPower : power;
2381 unitTarget->ModifyPower(powertype,-new_damage);
2382 float multiplier = m_spellInfo->EffectMultipleValue[i];
2384 if(Player *modOwner = m_caster->GetSpellModOwner())
2385 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2387 new_damage = int32(new_damage*multiplier);
2388 m_damage+=new_damage;
2391 void Spell::EffectHeal( uint32 /*i*/ )
2393 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2395 // Try to get original caster
2396 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2398 // Skip if m_originalCaster not available
2399 if (!caster)
2400 return;
2402 int32 addhealth = damage;
2404 // Vessel of the Naaru (Vial of the Sunwell trinket)
2405 if (m_spellInfo->Id == 45064)
2407 // Amount of heal - depends from stacked Holy Energy
2408 int damageAmount = 0;
2409 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2410 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2411 if((*i)->GetId() == 45062)
2412 damageAmount+=(*i)->GetModifier()->m_amount;
2413 if (damageAmount)
2414 m_caster->RemoveAurasDueToSpell(45062);
2416 addhealth += damageAmount;
2418 // Swiftmend - consumes Regrowth or Rejuvenation
2419 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2421 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2422 // find most short by duration
2423 Aura *targetAura = NULL;
2424 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2426 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2427 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2429 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2430 targetAura = *i;
2434 if(!targetAura)
2436 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2437 return;
2439 int idx = 0;
2440 while(idx < 3)
2442 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2443 break;
2444 idx++;
2447 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2448 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2449 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2451 addhealth += tickheal * tickcount;
2453 else
2454 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2456 m_healing+=addhealth;
2460 void Spell::EffectHealPct( uint32 /*i*/ )
2462 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2464 // Try to get original caster
2465 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2467 // Skip if m_originalCaster not available
2468 if (!caster)
2469 return;
2471 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2472 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2474 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2475 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2477 if(caster->GetTypeId()==TYPEID_PLAYER)
2478 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2479 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2483 void Spell::EffectHealMechanical( uint32 /*i*/ )
2485 // Mechanic creature type should be correctly checked by targetCreatureType field
2486 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2488 // Try to get original caster
2489 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2491 // Skip if m_originalCaster not available
2492 if (!caster)
2493 return;
2495 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2496 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2497 unitTarget->ModifyHealth( int32(damage) );
2501 void Spell::EffectHealthLeech(uint32 i)
2503 if(!unitTarget)
2504 return;
2505 if(!unitTarget->isAlive())
2506 return;
2508 if(damage < 0)
2509 return;
2511 sLog.outDebug("HealthLeech :%i", damage);
2513 float multiplier = m_spellInfo->EffectMultipleValue[i];
2515 if(Player *modOwner = m_caster->GetSpellModOwner())
2516 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2518 int32 new_damage = int32(damage*multiplier);
2519 uint32 curHealth = unitTarget->GetHealth();
2520 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2521 if(curHealth < new_damage)
2522 new_damage = curHealth;
2524 if(m_caster->isAlive())
2526 new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
2528 m_caster->ModifyHealth(new_damage);
2530 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2531 m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2533 // m_healthLeech+=tmpvalue;
2534 // m_damage+=new_damage;
2537 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2539 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2540 return;
2542 Player* player = (Player*)unitTarget;
2544 uint32 newitemid = itemtype;
2545 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2546 if(!pProto)
2548 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2549 return;
2552 uint32 num_to_add;
2554 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2555 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2557 int32 basePoints = m_currentBasePoints[i];
2558 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2559 if (randomPoints)
2560 num_to_add = basePoints + irand(1, randomPoints);
2561 else
2562 num_to_add = basePoints + 1;
2564 else if (pProto->MaxCount == 1)
2565 num_to_add = 1;
2566 else if(player->getLevel() >= m_spellInfo->spellLevel)
2568 int32 basePoints = m_currentBasePoints[i];
2569 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2570 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2572 else
2573 num_to_add = 2;
2575 if (num_to_add < 1)
2576 num_to_add = 1;
2577 if (num_to_add > pProto->GetMaxStackSize())
2578 num_to_add = pProto->GetMaxStackSize();
2580 // init items_count to 1, since 1 item will be created regardless of specialization
2581 int items_count=1;
2582 // the chance to create additional items
2583 float additionalCreateChance=0.0f;
2584 // the maximum number of created additional items
2585 uint8 additionalMaxNum=0;
2586 // get the chance and maximum number for creating extra items
2587 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2589 // roll with this chance till we roll not to create or we create the max num
2590 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2591 ++items_count;
2594 // really will be created more items
2595 num_to_add *= items_count;
2597 // can the player store the new item?
2598 ItemPosCountVec dest;
2599 uint32 no_space = 0;
2600 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2601 if( msg != EQUIP_ERR_OK )
2603 // convert to possible store amount
2604 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2605 num_to_add -= no_space;
2606 else
2608 // if not created by another reason from full inventory or unique items amount limitation
2609 player->SendEquipError( msg, NULL, NULL );
2610 return;
2614 if(num_to_add)
2616 // create the new item and store it
2617 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2619 // was it successful? return error if not
2620 if(!pItem)
2622 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2623 return;
2626 // set the "Crafted by ..." property of the item
2627 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2628 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2630 // send info to the client
2631 if(pItem)
2632 player->SendNewItem(pItem, num_to_add, true, true);
2634 // we succeeded in creating at least one item, so a levelup is possible
2635 player->UpdateCraftSkill(m_spellInfo->Id);
2638 // for battleground marks send by mail if not add all expected
2639 if(no_space > 0 )
2641 BattleGroundTypeId bgType;
2642 switch(m_spellInfo->Id)
2644 case SPELL_AV_MARK_WINNER:
2645 case SPELL_AV_MARK_LOSER:
2646 bgType = BATTLEGROUND_AV;
2647 break;
2648 case SPELL_WS_MARK_WINNER:
2649 case SPELL_WS_MARK_LOSER:
2650 bgType = BATTLEGROUND_WS;
2651 break;
2652 case SPELL_AB_MARK_WINNER:
2653 case SPELL_AB_MARK_LOSER:
2654 bgType = BATTLEGROUND_AB;
2655 break;
2656 default:
2657 return;
2660 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2661 bg->SendRewardMarkByMail(player,newitemid,no_space);
2665 void Spell::EffectCreateItem(uint32 i)
2667 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2670 void Spell::EffectCreateItem2(uint32 i)
2672 // special case: generate using spell_loot_template
2673 if(!m_spellInfo->EffectItemType[i])
2675 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
2676 return;
2678 // create some random items
2679 ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
2680 return;
2682 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2685 void Spell::EffectPersistentAA(uint32 i)
2687 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2689 if(Player* modOwner = m_caster->GetSpellModOwner())
2690 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2692 int32 duration = GetSpellDuration(m_spellInfo);
2693 DynamicObject* dynObj = new DynamicObject;
2694 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))
2696 delete dynObj;
2697 return;
2699 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2700 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2701 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2702 m_caster->AddDynObject(dynObj);
2703 dynObj->GetMap()->Add(dynObj);
2706 void Spell::EffectEnergize(uint32 i)
2708 if(!unitTarget)
2709 return;
2710 if(!unitTarget->isAlive())
2711 return;
2713 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2714 return;
2716 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2718 // Some level depends spells
2719 int multiplier = 0;
2720 int level_diff = 0;
2721 switch (m_spellInfo->Id)
2723 // Restore Energy
2724 case 9512:
2725 level_diff = m_caster->getLevel() - 40;
2726 multiplier = 2;
2727 break;
2728 // Blood Fury
2729 case 24571:
2730 level_diff = m_caster->getLevel() - 60;
2731 multiplier = 10;
2732 break;
2733 // Burst of Energy
2734 case 24532:
2735 level_diff = m_caster->getLevel() - 60;
2736 multiplier = 4;
2737 break;
2738 default:
2739 break;
2742 if (level_diff > 0)
2743 damage -= multiplier * level_diff;
2745 if(damage < 0)
2746 return;
2748 if(unitTarget->GetMaxPower(power) == 0)
2749 return;
2751 unitTarget->ModifyPower(power,damage);
2752 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2754 // Mad Alchemist's Potion
2755 if (m_spellInfo->Id == 45051)
2757 // find elixirs on target
2758 uint32 elixir_mask = 0;
2759 Unit::AuraMap& Auras = unitTarget->GetAuras();
2760 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2762 uint32 spell_id = itr->second->GetId();
2763 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2764 elixir_mask |= mask;
2767 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2768 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2770 // get all available elixirs by mask and spell level
2771 std::vector<uint32> elixirs;
2772 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2773 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2775 if (itr->second & elixir_mask)
2777 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2778 continue;
2780 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2781 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2782 continue;
2784 elixirs.push_back(itr->first);
2788 if (!elixirs.empty())
2790 // cast random elixir on target
2791 uint32 rand_spell = urand(0,elixirs.size()-1);
2792 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2797 void Spell::EffectEnergisePct(uint32 i)
2799 if(!unitTarget)
2800 return;
2801 if(!unitTarget->isAlive())
2802 return;
2804 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2805 return;
2807 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2809 uint32 maxPower = unitTarget->GetMaxPower(power);
2810 if(maxPower == 0)
2811 return;
2813 uint32 gain = damage * maxPower / 100;
2814 unitTarget->ModifyPower(power, gain);
2815 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
2818 void Spell::SendLoot(uint64 guid, LootType loottype)
2820 Player* player = (Player*)m_caster;
2821 if (!player)
2822 return;
2824 if (gameObjTarget)
2826 if (Script->GOHello(player, gameObjTarget))
2827 return;
2829 switch (gameObjTarget->GetGoType())
2831 case GAMEOBJECT_TYPE_DOOR:
2832 case GAMEOBJECT_TYPE_BUTTON:
2833 gameObjTarget->UseDoorOrButton();
2834 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2835 return;
2837 case GAMEOBJECT_TYPE_QUESTGIVER:
2838 // start or end quest
2839 player->PrepareQuestMenu(guid);
2840 player->SendPreparedQuest(guid);
2841 return;
2843 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2844 // triggering linked GO
2845 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2846 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2847 return;
2849 case GAMEOBJECT_TYPE_GOOBER:
2850 // goober_scripts can be triggered if the player don't have the quest
2851 if (gameObjTarget->GetGOInfo()->goober.eventId)
2853 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2854 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2857 // cast goober spell
2858 if (gameObjTarget->GetGOInfo()->goober.questId)
2859 ///Quest require to be active for GO using
2860 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2861 return;
2863 gameObjTarget->AddUniqueUse(player);
2864 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2866 //TODO? Objective counting called without spell check but with quest objective check
2867 // if send spell id then this line will duplicate to spell casting call (double counting)
2868 // So we or have this line and not required in quest_template have reqSpellIdN
2869 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2870 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2872 // triggering linked GO
2873 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2874 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2876 return;
2878 case GAMEOBJECT_TYPE_CHEST:
2879 // TODO: possible must be moved to loot release (in different from linked triggering)
2880 if (gameObjTarget->GetGOInfo()->chest.eventId)
2882 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2883 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2886 // triggering linked GO
2887 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2888 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2890 // Don't return, let loots been taken
2894 // Send loot
2895 player->SendLoot(guid, loottype);
2898 void Spell::EffectOpenLock(uint32 /*i*/)
2900 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2902 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2903 return;
2906 Player* player = (Player*)m_caster;
2908 LootType loottype = LOOT_CORPSE;
2909 uint32 lockId = 0;
2910 uint64 guid = 0;
2912 // Get lockId
2913 if(gameObjTarget)
2915 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2916 // Arathi Basin banner opening !
2917 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2918 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2920 //isAllowUseBattleGroundObject() already called in CanCast()
2921 // in battleground check
2922 if(BattleGround *bg = player->GetBattleGround())
2924 // check if it's correct bg
2925 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2926 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2927 return;
2930 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2932 //isAllowUseBattleGroundObject() already called in CanCast()
2933 // in battleground check
2934 if(BattleGround *bg = player->GetBattleGround())
2936 if(bg->GetTypeID() == BATTLEGROUND_EY)
2937 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2938 return;
2941 lockId = gameObjTarget->GetLockId();
2942 guid = gameObjTarget->GetGUID();
2944 else if(itemTarget)
2946 lockId = itemTarget->GetProto()->LockID;
2947 guid = itemTarget->GetGUID();
2949 else
2951 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2952 return;
2955 if(!lockId) // possible case for GO and maybe for items.
2957 SendLoot(guid, loottype);
2958 return;
2961 // Get LockInfo
2962 LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
2964 if (!lockInfo)
2966 sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2967 (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
2968 SendCastResult(SPELL_FAILED_BAD_TARGETS);
2969 return;
2972 // check key
2973 for(int i = 0; i < 8; ++i)
2975 // Type==1 This means lockInfo->Index[i] is an item
2976 if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
2978 SendLoot(guid, loottype);
2979 return;
2983 uint32 SkillId = 0;
2984 // Check and skill-up skill
2985 if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
2986 SkillId = m_spellInfo->EffectMiscValue[1];
2987 // pickpocketing spells
2988 else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
2989 SkillId = SKILL_LOCKPICKING;
2991 // skill bonus provided by casting spell (mostly item spells)
2992 uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
2994 uint32 reqSkillValue = lockInfo->Skill[0];
2996 if(lockInfo->Skill[1]) // required pick lock skill applying
2998 if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
3000 SendCastResult(SPELL_FAILED_FIZZLE);
3001 return;
3004 reqSkillValue = lockInfo->Skill[1];
3006 else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
3008 SendCastResult(SPELL_FAILED_BAD_TARGETS);
3009 return;
3012 if ( SkillId )
3014 loottype = LOOT_SKINNING;
3015 if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
3017 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
3018 return;
3021 // update skill if really known
3022 if(uint32 SkillValue = player->GetPureSkillValue(SkillId))
3024 if(gameObjTarget)
3026 // Allow one skill-up until respawned
3027 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3028 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
3029 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3031 else if(itemTarget)
3033 // Do one skill-up
3034 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
3039 SendLoot(guid, loottype);
3042 void Spell::EffectSummonChangeItem(uint32 i)
3044 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3045 return;
3047 Player *player = (Player*)m_caster;
3049 // applied only to using item
3050 if(!m_CastItem)
3051 return;
3053 // ... only to item in own inventory/bank/equip_slot
3054 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3055 return;
3057 uint32 newitemid = m_spellInfo->EffectItemType[i];
3058 if(!newitemid)
3059 return;
3061 uint16 pos = m_CastItem->GetPos();
3063 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3064 if( !pNewItem )
3065 return;
3067 for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3069 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3070 pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3073 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3075 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3076 player->DurabilityLoss(pNewItem, loosePercent);
3079 if( player->IsInventoryPos( pos ) )
3081 ItemPosCountVec dest;
3082 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3083 if( msg == EQUIP_ERR_OK )
3085 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3087 // prevent crash at access and unexpected charges counting with item update queue corrupt
3088 if(m_CastItem==m_targets.getItemTarget())
3089 m_targets.setItemTarget(NULL);
3091 m_CastItem = NULL;
3093 player->StoreItem( dest, pNewItem, true);
3094 return;
3097 else if( player->IsBankPos ( pos ) )
3099 ItemPosCountVec dest;
3100 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3101 if( msg == EQUIP_ERR_OK )
3103 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3105 // prevent crash at access and unexpected charges counting with item update queue corrupt
3106 if(m_CastItem==m_targets.getItemTarget())
3107 m_targets.setItemTarget(NULL);
3109 m_CastItem = NULL;
3111 player->BankItem( dest, pNewItem, true);
3112 return;
3115 else if( player->IsEquipmentPos ( pos ) )
3117 uint16 dest;
3118 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3119 if( msg == EQUIP_ERR_OK )
3121 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3123 // prevent crash at access and unexpected charges counting with item update queue corrupt
3124 if(m_CastItem==m_targets.getItemTarget())
3125 m_targets.setItemTarget(NULL);
3127 m_CastItem = NULL;
3129 player->EquipItem( dest, pNewItem, true);
3130 player->AutoUnequipOffhandIfNeed();
3131 return;
3135 // fail
3136 delete pNewItem;
3139 void Spell::EffectOpenSecretSafe(uint32 i)
3141 EffectOpenLock(i); //no difference for now
3144 void Spell::EffectProficiency(uint32 /*i*/)
3146 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3147 return;
3148 Player *p_target = (Player*)unitTarget;
3150 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3151 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3153 p_target->AddWeaponProficiency(subClassMask);
3154 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3156 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3158 p_target->AddArmorProficiency(subClassMask);
3159 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3163 void Spell::EffectApplyAreaAura(uint32 i)
3165 if(!unitTarget)
3166 return;
3167 if(!unitTarget->isAlive())
3168 return;
3170 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3171 unitTarget->AddAura(Aur);
3174 void Spell::EffectSummonType(uint32 i)
3176 switch(m_spellInfo->EffectMiscValueB[i])
3178 case SUMMON_TYPE_GUARDIAN:
3179 case SUMMON_TYPE_POSESSED:
3180 case SUMMON_TYPE_POSESSED2:
3181 case SUMMON_TYPE_FORCE_OF_NATURE:
3182 case SUMMON_TYPE_GUARDIAN2:
3183 EffectSummonGuardian(i);
3184 break;
3185 case SUMMON_TYPE_WILD:
3186 EffectSummonWild(i);
3187 break;
3188 case SUMMON_TYPE_DEMON:
3189 EffectSummonDemon(i);
3190 break;
3191 case SUMMON_TYPE_SUMMON:
3192 EffectSummon(i);
3193 break;
3194 case SUMMON_TYPE_CRITTER:
3195 case SUMMON_TYPE_CRITTER2:
3196 case SUMMON_TYPE_CRITTER3:
3197 EffectSummonCritter(i);
3198 break;
3199 case SUMMON_TYPE_TOTEM_SLOT1:
3200 case SUMMON_TYPE_TOTEM_SLOT2:
3201 case SUMMON_TYPE_TOTEM_SLOT3:
3202 case SUMMON_TYPE_TOTEM_SLOT4:
3203 case SUMMON_TYPE_TOTEM:
3204 EffectSummonTotem(i);
3205 break;
3206 case SUMMON_TYPE_UNKNOWN1:
3207 case SUMMON_TYPE_UNKNOWN2:
3208 case SUMMON_TYPE_UNKNOWN3:
3209 case SUMMON_TYPE_UNKNOWN4:
3210 case SUMMON_TYPE_UNKNOWN5:
3211 break;
3212 default:
3213 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3214 break;
3218 void Spell::EffectSummon(uint32 i)
3220 if(m_caster->GetPetGUID())
3221 return;
3223 if(!unitTarget)
3224 return;
3225 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3226 if(!pet_entry)
3227 return;
3228 uint32 level = m_caster->getLevel();
3229 Pet* spawnCreature = new Pet(SUMMON_PET);
3231 if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3233 // set timer for unsummon
3234 int32 duration = GetSpellDuration(m_spellInfo);
3235 if(duration > 0)
3236 spawnCreature->SetDuration(duration);
3238 return;
3241 Map *map = m_caster->GetMap();
3242 uint32 pet_number = objmgr.GeneratePetNumber();
3243 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_caster->GetPhaseMask(),
3244 m_spellInfo->EffectMiscValue[i], pet_number))
3246 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3247 delete spawnCreature;
3248 return;
3251 // Summon in dest location
3252 float x,y,z;
3253 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3255 x = m_targets.m_destX;
3256 y = m_targets.m_destY;
3257 z = m_targets.m_destZ;
3259 else
3260 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3262 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3264 if(!spawnCreature->IsPositionValid())
3266 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3267 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3268 delete spawnCreature;
3269 return;
3272 // set timer for unsummon
3273 int32 duration = GetSpellDuration(m_spellInfo);
3274 if(duration > 0)
3275 spawnCreature->SetDuration(duration);
3277 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3278 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3279 spawnCreature->setPowerType(POWER_MANA);
3280 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3281 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3282 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3283 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3284 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3285 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3286 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3287 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3288 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3290 spawnCreature->InitStatsForLevel(level);
3292 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3294 spawnCreature->AIM_Initialize();
3295 spawnCreature->InitPetCreateSpells();
3296 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3297 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3299 std::string name = m_caster->GetName();
3300 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3301 spawnCreature->SetName( name );
3303 map->Add((Creature*)spawnCreature);
3305 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3307 m_caster->SetPet(spawnCreature);
3308 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3309 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3310 ((Player*)m_caster)->PetSpellInitialize();
3314 void Spell::EffectLearnSpell(uint32 i)
3316 if(!unitTarget)
3317 return;
3319 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3321 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3322 EffectLearnPetSpell(i);
3324 return;
3327 Player *player = (Player*)unitTarget;
3329 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3330 player->learnSpell(spellToLearn,false);
3332 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3335 void Spell::EffectDispel(uint32 i)
3337 if(!unitTarget)
3338 return;
3340 // Fill possible dispell list
3341 std::vector <Aura *> dispel_list;
3343 // Create dispel mask by dispel type
3344 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3345 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3346 Unit::AuraMap const& auras = unitTarget->GetAuras();
3347 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3349 Aura *aur = (*itr).second;
3350 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3352 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3354 bool positive = true;
3355 if (!aur->IsPositive())
3356 positive = false;
3357 else
3358 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3360 // do not remove positive auras if friendly target
3361 // negative auras if non-friendly target
3362 if(positive == unitTarget->IsFriendlyTo(m_caster))
3363 continue;
3365 // Add aura to dispel list
3366 dispel_list.push_back(aur);
3369 // Ok if exist some buffs for dispel try dispel it
3370 if (!dispel_list.empty())
3372 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3373 std::list < uint32 > fail_list; // spell_id
3374 int32 list_size = dispel_list.size();
3375 // Dispell N = damage buffs (or while exist buffs for dispel)
3376 for (int32 count=0; count < damage && list_size > 0; ++count)
3378 // Random select buff for dispel
3379 Aura *aur = dispel_list[urand(0, list_size-1)];
3381 SpellEntry const* spellInfo = aur->GetSpellProto();
3382 // Base dispel chance
3383 // TODO: possible chance depend from spell level??
3384 int32 miss_chance = 0;
3385 // Apply dispel mod from aura caster
3386 if (Unit *caster = aur->GetCaster())
3388 if ( Player* modOwner = caster->GetSpellModOwner() )
3389 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3391 // Try dispel
3392 if (roll_chance_i(miss_chance))
3393 fail_list.push_back(aur->GetId());
3394 else
3395 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3396 // Remove buff from list for prevent doubles
3397 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3399 Aura *dispeled = *j;
3400 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3402 j = dispel_list.erase(j);
3403 --list_size;
3405 else
3406 ++j;
3409 // Send success log and really remove auras
3410 if (!success_list.empty())
3412 int32 count = success_list.size();
3413 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3414 data.append(unitTarget->GetPackGUID()); // Victim GUID
3415 data.append(m_caster->GetPackGUID()); // Caster GUID
3416 data << uint32(m_spellInfo->Id); // Dispell spell id
3417 data << uint8(0); // not used
3418 data << uint32(count); // count
3419 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3421 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3422 data << uint32(spellInfo->Id); // Spell Id
3423 data << uint8(0); // 0 - dispeled !=0 cleansed
3424 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3426 m_caster->SendMessageToSet(&data, true);
3428 // On succes dispel
3429 // Devour Magic
3430 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3432 uint32 heal_spell = 0;
3433 switch (m_spellInfo->Id)
3435 case 19505: heal_spell = 19658; break;
3436 case 19731: heal_spell = 19732; break;
3437 case 19734: heal_spell = 19733; break;
3438 case 19736: heal_spell = 19735; break;
3439 case 27276: heal_spell = 27278; break;
3440 case 27277: heal_spell = 27279; break;
3441 default:
3442 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3443 break;
3445 if (heal_spell)
3446 m_caster->CastSpell(m_caster, heal_spell, true);
3449 // Send fail log to client
3450 if (!fail_list.empty())
3452 // Failed to dispell
3453 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3454 data << uint64(m_caster->GetGUID()); // Caster GUID
3455 data << uint64(unitTarget->GetGUID()); // Victim GUID
3456 data << uint32(m_spellInfo->Id); // Dispell spell id
3457 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3458 data << uint32(*j); // Spell Id
3459 m_caster->SendMessageToSet(&data, true);
3464 void Spell::EffectDualWield(uint32 /*i*/)
3466 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3467 ((Player*)unitTarget)->SetCanDualWield(true);
3470 void Spell::EffectPull(uint32 /*i*/)
3472 // TODO: create a proper pull towards distract spell center for distract
3473 sLog.outDebug("WORLD: Spell Effect DUMMY");
3476 void Spell::EffectDistract(uint32 /*i*/)
3478 // Check for possible target
3479 if (!unitTarget || unitTarget->isInCombat())
3480 return;
3482 // target must be OK to do this
3483 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3484 return;
3486 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3488 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3490 // For players just turn them
3491 WorldPacket data;
3492 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3493 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3494 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3496 else
3498 // Set creature Distracted, Stop it, And turn it
3499 unitTarget->SetOrientation(angle);
3500 unitTarget->StopMoving();
3501 unitTarget->GetMotionMaster()->MoveDistract(damage*IN_MILISECONDS);
3505 void Spell::EffectPickPocket(uint32 /*i*/)
3507 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3508 return;
3510 // victim must be creature and attackable
3511 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3512 return;
3514 // victim have to be alive and humanoid or undead
3515 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3517 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3519 if (chance > irand(0, 19))
3521 // Stealing successful
3522 //sLog.outDebug("Sending loot from pickpocket");
3523 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3525 else
3527 // Reveal action + get attack
3528 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3529 if (((Creature*)unitTarget)->AI())
3530 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3535 void Spell::EffectAddFarsight(uint32 i)
3537 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3538 int32 duration = GetSpellDuration(m_spellInfo);
3539 DynamicObject* dynObj = new DynamicObject;
3540 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))
3542 delete dynObj;
3543 return;
3545 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3546 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3547 m_caster->AddDynObject(dynObj);
3548 dynObj->GetMap()->Add(dynObj);
3549 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3550 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3553 void Spell::EffectSummonWild(uint32 i)
3555 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3556 if(!creature_entry)
3557 return;
3559 uint32 level = m_caster->getLevel();
3561 // level of creature summoned using engineering item based at engineering skill level
3562 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3564 ItemPrototype const *proto = m_CastItem->GetProto();
3565 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3567 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3568 if(skill202)
3570 level = skill202/5;
3575 // select center of summon position
3576 float center_x = m_targets.m_destX;
3577 float center_y = m_targets.m_destY;
3578 float center_z = m_targets.m_destZ;
3580 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3582 int32 amount = damage > 0 ? damage : 1;
3584 for(int32 count = 0; count < amount; ++count)
3586 float px, py, pz;
3587 // If dest location if present
3588 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3590 // Summon 1 unit in dest location
3591 if (count == 0)
3593 px = m_targets.m_destX;
3594 py = m_targets.m_destY;
3595 pz = m_targets.m_destZ;
3597 // Summon in random point all other units if location present
3598 else
3599 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3601 // Summon if dest location not present near caster
3602 else
3603 m_caster->GetClosePoint(px,py,pz,3.0f);
3605 int32 duration = GetSpellDuration(m_spellInfo);
3607 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3609 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3613 void Spell::EffectSummonGuardian(uint32 i)
3615 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3616 if(!pet_entry)
3617 return;
3619 // Jewelery statue case (totem like)
3620 if(m_spellInfo->SpellIconID==2056)
3622 EffectSummonTotem(i);
3623 return;
3626 // set timer for unsummon
3627 int32 duration = GetSpellDuration(m_spellInfo);
3629 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3630 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3631 // so this code hack in fact
3632 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3633 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3634 return; // find old guardian, ignore summon
3636 // in another case summon new
3637 uint32 level = m_caster->getLevel();
3639 // level of pet summoned using engineering item based at engineering skill level
3640 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3642 ItemPrototype const *proto = m_CastItem->GetProto();
3643 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3645 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3646 if(skill202)
3648 level = skill202/5;
3653 // select center of summon position
3654 float center_x = m_targets.m_destX;
3655 float center_y = m_targets.m_destY;
3656 float center_z = m_targets.m_destZ;
3658 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3660 int32 amount = damage > 0 ? damage : 1;
3662 for(int32 count = 0; count < amount; ++count)
3664 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3666 Map *map = m_caster->GetMap();
3667 uint32 pet_number = objmgr.GeneratePetNumber();
3668 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3669 m_spellInfo->EffectMiscValue[i], pet_number))
3671 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3672 delete spawnCreature;
3673 return;
3676 float px, py, pz;
3677 // If dest location if present
3678 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3680 // Summon 1 unit in dest location
3681 if (count == 0)
3683 px = m_targets.m_destX;
3684 py = m_targets.m_destY;
3685 pz = m_targets.m_destZ;
3687 // Summon in random point all other units if location present
3688 else
3689 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3691 // Summon if dest location not present near caster
3692 else
3693 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3695 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3697 if(!spawnCreature->IsPositionValid())
3699 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3700 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3701 delete spawnCreature;
3702 return;
3705 if(duration > 0)
3706 spawnCreature->SetDuration(duration);
3708 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3709 spawnCreature->setPowerType(POWER_MANA);
3710 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3711 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3712 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3713 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3714 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3715 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3716 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3718 spawnCreature->InitStatsForLevel(level);
3719 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3721 spawnCreature->AIM_Initialize();
3723 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3724 ((Player*)m_caster)->AddGuardian(spawnCreature);
3726 map->Add((Creature*)spawnCreature);
3730 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3732 if(!unitTarget)
3733 return;
3735 if(unitTarget->isInFlight())
3736 return;
3738 uint32 mapid = m_caster->GetMapId();
3739 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3741 float fx,fy,fz;
3742 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3744 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3745 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
3746 else
3747 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3750 void Spell::EffectLearnSkill(uint32 i)
3752 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3753 return;
3755 if(damage < 0)
3756 return;
3758 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3759 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3760 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3763 void Spell::EffectAddHonor(uint32 /*i*/)
3765 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3766 return;
3768 sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3770 // TODO: find formula for honor reward based on player's level!
3772 // now fixed only for level 70 players:
3773 if (((Player*)unitTarget)->getLevel() == 70)
3774 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3777 void Spell::EffectTradeSkill(uint32 /*i*/)
3779 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3780 return;
3781 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3782 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3783 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3786 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
3788 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3789 return;
3790 if (!itemTarget)
3791 return;
3793 Player* p_caster = (Player*)m_caster;
3795 // not grow at item use at item case
3796 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3798 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3799 if (!enchant_id)
3800 return;
3802 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3803 if(!pEnchant)
3804 return;
3806 // item can be in trade slot and have owner diff. from caster
3807 Player* item_owner = itemTarget->GetOwner();
3808 if(!item_owner)
3809 return;
3811 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3813 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3814 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3815 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3816 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3819 // remove old enchanting before applying new if equipped
3820 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3822 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3824 // add new enchanting if equipped
3825 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3828 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
3830 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3831 return;
3832 if (!itemTarget)
3833 return;
3835 Player* p_caster = (Player*)m_caster;
3837 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3838 if (!enchant_id)
3839 return;
3841 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3842 if(!pEnchant)
3843 return;
3845 // support only enchantings with add socket in this slot
3847 bool add_socket = false;
3848 for(int i = 0; i < 3; ++i)
3850 if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
3852 add_socket = true;
3853 break;
3856 if(!add_socket)
3858 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.",
3859 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
3860 return;
3864 // item can be in trade slot and have owner diff. from caster
3865 Player* item_owner = itemTarget->GetOwner();
3866 if(!item_owner)
3867 return;
3869 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3871 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3872 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3873 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3874 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3877 // remove old enchanting before applying new if equipped
3878 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
3880 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3882 // add new enchanting if equipped
3883 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
3886 void Spell::EffectEnchantItemTmp(uint32 i)
3888 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3889 return;
3891 Player* p_caster = (Player*)m_caster;
3893 if(!itemTarget)
3894 return;
3896 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3898 // Shaman Rockbiter Weapon
3899 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3901 int32 enchnting_damage = m_currentBasePoints[1]+1;
3903 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3904 // with already applied percent bonus from Elemental Weapons talent
3905 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3906 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3907 switch(enchnting_damage)
3909 // Rank 1
3910 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3911 // Rank 2
3912 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3913 case 5: enchant_id = 3025; break; // 20%
3914 // Rank 3
3915 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3916 case 7: enchant_id = 3027; break; // 20%
3917 // Rank 4
3918 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3919 case 10: enchant_id = 503; break; // 14%
3920 case 11: enchant_id = 3031; break; // 20%
3921 // Rank 5
3922 case 15: enchant_id = 3035; break; // 0%
3923 case 16: enchant_id = 1663; break; // 7%
3924 case 17: enchant_id = 3033; break; // 14%
3925 case 18: enchant_id = 3034; break; // 20%
3926 // Rank 6
3927 case 28: enchant_id = 3038; break; // 0%
3928 case 29: enchant_id = 683; break; // 7%
3929 case 31: enchant_id = 3036; break; // 14%
3930 case 33: enchant_id = 3037; break; // 20%
3931 // Rank 7
3932 case 40: enchant_id = 3041; break; // 0%
3933 case 42: enchant_id = 1664; break; // 7%
3934 case 45: enchant_id = 3039; break; // 14%
3935 case 48: enchant_id = 3040; break; // 20%
3936 // Rank 8
3937 case 49: enchant_id = 3044; break; // 0%
3938 case 52: enchant_id = 2632; break; // 7%
3939 case 55: enchant_id = 3042; break; // 14%
3940 case 58: enchant_id = 3043; break; // 20%
3941 // Rank 9
3942 case 62: enchant_id = 2633; break; // 0%
3943 case 66: enchant_id = 3018; break; // 7%
3944 case 70: enchant_id = 3019; break; // 14%
3945 case 74: enchant_id = 3020; break; // 20%
3946 default:
3947 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3948 return;
3952 if (!enchant_id)
3954 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3955 return;
3958 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3959 if(!pEnchant)
3961 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3962 return;
3965 // select enchantment duration
3966 uint32 duration;
3968 // rogue family enchantments exception by duration
3969 if(m_spellInfo->Id==38615)
3970 duration = 1800; // 30 mins
3971 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3972 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3973 duration = 3600; // 1 hour
3974 // shaman family enchantments
3975 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3976 duration = 1800; // 30 mins
3977 // other cases with this SpellVisual already selected
3978 else if(m_spellInfo->SpellVisual[0]==215)
3979 duration = 1800; // 30 mins
3980 // some fishing pole bonuses
3981 else if(m_spellInfo->SpellVisual[0]==563)
3982 duration = 600; // 10 mins
3983 // shaman rockbiter enchantments
3984 else if(m_spellInfo->SpellVisual[0]==0)
3985 duration = 1800; // 30 mins
3986 else if(m_spellInfo->Id==29702)
3987 duration = 300; // 5 mins
3988 else if(m_spellInfo->Id==37360)
3989 duration = 300; // 5 mins
3990 // default case
3991 else
3992 duration = 3600; // 1 hour
3994 // item can be in trade slot and have owner diff. from caster
3995 Player* item_owner = itemTarget->GetOwner();
3996 if(!item_owner)
3997 return;
3999 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
4001 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4002 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
4003 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
4004 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
4007 // remove old enchanting before applying new if equipped
4008 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
4010 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
4012 // add new enchanting if equipped
4013 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
4016 void Spell::EffectTameCreature(uint32 /*i*/)
4018 if(m_caster->GetPetGUID())
4019 return;
4021 if(!unitTarget)
4022 return;
4024 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4025 return;
4027 Creature* creatureTarget = (Creature*)unitTarget;
4029 if(creatureTarget->isPet())
4030 return;
4032 if(m_caster->getClass() != CLASS_HUNTER)
4033 return;
4035 // cast finish successfully
4036 //SendChannelUpdate(0);
4037 finish();
4039 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
4041 // kill original creature
4042 creatureTarget->setDeathState(JUST_DIED);
4043 creatureTarget->RemoveCorpse();
4044 creatureTarget->SetHealth(0); // just for nice GM-mode view
4046 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4048 // prepare visual effect for levelup
4049 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4051 // add to world
4052 pet->GetMap()->Add((Creature*)pet);
4054 // visual effect for levelup
4055 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4057 // caster have pet now
4058 m_caster->SetPet(pet);
4060 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4062 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4063 ((Player*)m_caster)->PetSpellInitialize();
4067 void Spell::EffectSummonPet(uint32 i)
4069 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4071 Pet *OldSummon = m_caster->GetPet();
4073 // if pet requested type already exist
4074 if( OldSummon )
4076 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4078 // pet in corpse state can't be summoned
4079 if( OldSummon->isDead() )
4080 return;
4082 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4083 OldSummon->SetMapId(m_caster->GetMapId());
4085 float px, py, pz;
4086 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4088 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4089 m_caster->GetMap()->Add((Creature*)OldSummon);
4091 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4093 ((Player*)m_caster)->PetSpellInitialize();
4095 return;
4098 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4099 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4100 else
4101 return;
4104 Pet* NewSummon = new Pet;
4106 // petentry==0 for hunter "call pet" (current pet summoned if any)
4107 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4109 if(NewSummon->getPetType()==SUMMON_PET)
4111 // Remove Demonic Sacrifice auras (known pet)
4112 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4113 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4115 if((*itr)->GetModifier()->m_miscvalue==2228)
4117 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4118 itr = auraClassScripts.begin();
4120 else
4121 ++itr;
4125 return;
4128 // not error in case fail hunter call pet
4129 if(!petentry)
4131 delete NewSummon;
4132 return;
4135 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4137 if(!cInfo)
4139 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4140 delete NewSummon;
4141 return;
4144 Map *map = m_caster->GetMap();
4145 uint32 pet_number = objmgr.GeneratePetNumber();
4146 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4147 petentry, pet_number))
4149 delete NewSummon;
4150 return;
4153 float px, py, pz;
4154 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4156 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4158 if(!NewSummon->IsPositionValid())
4160 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4161 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4162 delete NewSummon;
4163 return;
4166 uint32 petlevel = m_caster->getLevel();
4167 NewSummon->setPetType(SUMMON_PET);
4169 uint32 faction = m_caster->getFaction();
4170 if(m_caster->GetTypeId() == TYPEID_UNIT)
4172 if ( ((Creature*)m_caster)->isTotem() )
4173 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4174 else
4175 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4178 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4179 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4180 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4181 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4182 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4183 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4184 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4185 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4186 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4187 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4189 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4190 // this enables pet details window (Shift+P)
4192 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4193 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4194 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4196 NewSummon->InitStatsForLevel(petlevel);
4197 NewSummon->InitPetCreateSpells();
4198 NewSummon->InitTalentForLevel();
4200 if(NewSummon->getPetType()==SUMMON_PET)
4202 // Remove Demonic Sacrifice auras (new pet)
4203 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4204 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4206 if((*itr)->GetModifier()->m_miscvalue==2228)
4208 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4209 itr = auraClassScripts.begin();
4211 else
4212 ++itr;
4215 // generate new name for summon pet
4216 std::string new_name=objmgr.GeneratePetName(petentry);
4217 if(!new_name.empty())
4218 NewSummon->SetName(new_name);
4220 else if(NewSummon->getPetType()==HUNTER_PET)
4221 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4223 NewSummon->AIM_Initialize();
4224 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4225 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4227 map->Add((Creature*)NewSummon);
4229 m_caster->SetPet(NewSummon);
4230 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4232 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4234 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4235 ((Player*)m_caster)->PetSpellInitialize();
4239 void Spell::EffectLearnPetSpell(uint32 i)
4241 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4242 return;
4244 Player *_player = (Player*)m_caster;
4246 Pet *pet = _player->GetPet();
4247 if(!pet)
4248 return;
4249 if(!pet->isAlive())
4250 return;
4252 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4253 if(!learn_spellproto)
4254 return;
4256 pet->learnSpell(learn_spellproto->Id);
4258 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4259 _player->PetSpellInitialize();
4262 void Spell::EffectTaunt(uint32 /*i*/)
4264 // this effect use before aura Taunt apply for prevent taunt already attacking target
4265 // for spell as marked "non effective at already attacking target"
4266 if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4268 if(unitTarget->getVictim()==m_caster)
4270 SendCastResult(SPELL_FAILED_DONT_REPORT);
4271 return;
4275 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4276 if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4277 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4280 void Spell::EffectWeaponDmg(uint32 i)
4282 if(!unitTarget)
4283 return;
4284 if(!unitTarget->isAlive())
4285 return;
4287 // multiple weapon dmg effect workaround
4288 // execute only the last weapon damage
4289 // and handle all effects at once
4290 for (int j = 0; j < 3; j++)
4292 switch(m_spellInfo->Effect[j])
4294 case SPELL_EFFECT_WEAPON_DAMAGE:
4295 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4296 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4297 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4298 if (j < i) // we must calculate only at last weapon effect
4299 return;
4300 break;
4304 // some spell specific modifiers
4305 bool customBonusDamagePercentMod = false;
4306 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4308 float bonusDamagePercentMod = 1.0f; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4309 float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4310 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4311 bool normalized = false;
4313 int32 spell_bonus = 0; // bonus specific for spell
4314 switch(m_spellInfo->SpellFamilyName)
4316 case SPELLFAMILY_WARRIOR:
4318 // Whirlwind, single only spell with 2 weapon white damage apply if have
4319 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4321 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4322 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4324 // Devastate bonus and sunder armor refresh
4325 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4327 uint32 stack = 0;
4328 // Need refresh all Sunder Armor auras from this caster
4329 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4330 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4332 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4333 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4334 spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
4335 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4337 (*itr).second->RefreshAura();
4338 stack = (*itr).second->GetStackAmount();
4341 if (stack)
4342 spell_bonus += stack * CalculateDamage(2, unitTarget);
4344 break;
4346 case SPELLFAMILY_ROGUE:
4348 // Ambush
4349 if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4351 customBonusDamagePercentMod = true;
4352 bonusDamagePercentMod = 2.5f; // 250%
4354 // Mutilate (for each hand)
4355 else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4357 bool found = false;
4358 // fast check
4359 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4360 found = true;
4361 // full aura scan
4362 else
4364 Unit::AuraMap const& auras = unitTarget->GetAuras();
4365 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4367 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4369 found = true;
4370 break;
4375 if(found)
4376 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4378 break;
4380 case SPELLFAMILY_PALADIN:
4382 // Seal of Command - receive benefit from Spell Damage and Healing
4383 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4385 spellBonusNeedWeaponDamagePercentMod = true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4386 spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4387 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4389 break;
4391 case SPELLFAMILY_SHAMAN:
4393 // Skyshatter Harness item set bonus
4394 // Stormstrike
4395 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4397 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4398 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4400 // Stormstrike AP Buff
4401 if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4403 m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4404 break;
4411 int32 fixed_bonus = 0;
4412 for (int j = 0; j < 3; j++)
4414 switch(m_spellInfo->Effect[j])
4416 case SPELL_EFFECT_WEAPON_DAMAGE:
4417 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4418 fixed_bonus += CalculateDamage(j,unitTarget);
4419 break;
4420 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4421 fixed_bonus += CalculateDamage(j,unitTarget);
4422 normalized = true;
4423 break;
4424 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4425 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4427 // applied only to prev.effects fixed damage
4428 if(customBonusDamagePercentMod)
4429 fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4430 else
4431 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4432 break;
4433 default:
4434 break; // not weapon damage effect, just skip
4438 // apply weaponDamagePercentMod to spell bonus also
4439 if(spellBonusNeedWeaponDamagePercentMod)
4440 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4442 // non-weapon damage
4443 int32 bonus = spell_bonus + fixed_bonus;
4445 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4446 if(bonus)
4448 UnitMods unitMod;
4449 switch(m_attackType)
4451 default:
4452 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4453 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4454 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4457 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4458 bonus = int32(bonus*weapon_total_pct);
4461 // + weapon damage with applied weapon% dmg to base weapon damage in call
4462 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4464 // total damage
4465 bonus = int32(bonus*totalDamagePercentMod);
4467 // prevent negative damage
4468 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4470 // Add melee damage bonuses (also check for negative)
4471 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4472 m_damage+= eff_damage;
4474 // Hemorrhage
4475 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4477 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4478 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4481 // Mangle (Cat): CP
4482 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4484 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4485 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4488 // take ammo
4489 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4491 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4493 // wands don't have ammo
4494 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4495 return;
4497 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4499 if(pItem->GetMaxStackCount()==1)
4501 // decrease durability for non-stackable throw weapon
4502 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4504 else
4506 // decrease items amount for stackable throw weapon
4507 uint32 count = 1;
4508 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4511 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4512 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4516 void Spell::EffectThreat(uint32 /*i*/)
4518 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4519 return;
4521 if(!unitTarget->CanHaveThreatList())
4522 return;
4524 unitTarget->AddThreat(m_caster, float(damage));
4527 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4529 if(!unitTarget)
4530 return;
4531 if(!unitTarget->isAlive())
4532 return;
4534 uint32 heal = m_caster->GetMaxHealth();
4536 m_healing+=heal;
4539 void Spell::EffectInterruptCast(uint32 /*i*/)
4541 if(!unitTarget)
4542 return;
4543 if(!unitTarget->isAlive())
4544 return;
4546 // TODO: not all spells that used this effect apply cooldown at school spells
4547 // also exist case: apply cooldown to interrupted cast only and to all spells
4548 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4550 if (unitTarget->m_currentSpells[i])
4552 // check if we can interrupt spell
4553 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4555 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4556 unitTarget->InterruptSpell(i,false);
4562 void Spell::EffectSummonObjectWild(uint32 i)
4564 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4566 GameObject* pGameObj = new GameObject;
4568 WorldObject* target = focusObject;
4569 if( !target )
4570 target = m_caster;
4572 float x,y,z;
4573 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4575 x = m_targets.m_destX;
4576 y = m_targets.m_destY;
4577 z = m_targets.m_destZ;
4579 else
4580 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4582 Map *map = target->GetMap();
4584 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4585 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4587 delete pGameObj;
4588 return;
4591 int32 duration = GetSpellDuration(m_spellInfo);
4592 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4593 pGameObj->SetSpellId(m_spellInfo->Id);
4595 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4596 m_caster->AddGameObject(pGameObj);
4597 map->Add(pGameObj);
4599 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4601 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4603 Player *pl = (Player*)m_caster;
4604 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4605 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4607 uint32 team = ALLIANCE;
4609 if(pl->GetTeam() == team)
4610 team = HORDE;
4612 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4617 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4619 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4621 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4622 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4624 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4629 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4631 GameObject* linkedGO = new GameObject;
4632 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4633 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4635 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4636 linkedGO->SetSpellId(m_spellInfo->Id);
4638 m_caster->AddGameObject(linkedGO);
4639 map->Add(linkedGO);
4641 else
4643 delete linkedGO;
4644 linkedGO = NULL;
4645 return;
4650 void Spell::EffectScriptEffect(uint32 effIndex)
4652 // TODO: we must implement hunter pet summon at login there (spell 6962)
4654 switch(m_spellInfo->SpellFamilyName)
4656 case SPELLFAMILY_GENERIC:
4658 switch(m_spellInfo->Id)
4660 // PX-238 Winter Wondervolt TRAP
4661 case 26275:
4663 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4665 // check presence
4666 for(int j = 0; j < 4; ++j)
4667 if(unitTarget->HasAura(spells[j],0))
4668 return;
4670 // select spell
4671 uint32 iTmpSpellId = spells[urand(0,3)];
4673 // cast
4674 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4675 return;
4677 // Bending Shinbone
4678 case 8856:
4680 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4681 return;
4683 uint32 spell_id = 0;
4684 switch(urand(1,5))
4686 case 1: spell_id = 8854; break;
4687 default: spell_id = 8855; break;
4690 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4691 return;
4693 // Brittle Armor - need remove one 24575 Brittle Armor aura
4694 case 24590:
4695 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4696 return;
4697 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4698 case 26465:
4699 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4700 return;
4701 // Orb teleport spells
4702 case 25140:
4703 case 25143:
4704 case 25650:
4705 case 25652:
4706 case 29128:
4707 case 29129:
4708 case 35376:
4709 case 35727:
4711 if(!unitTarget)
4712 return;
4714 uint32 spellid;
4715 switch(m_spellInfo->Id)
4717 case 25140: spellid = 32571; break;
4718 case 25143: spellid = 32572; break;
4719 case 25650: spellid = 30140; break;
4720 case 25652: spellid = 30141; break;
4721 case 29128: spellid = 32568; break;
4722 case 29129: spellid = 32569; break;
4723 case 35376: spellid = 25649; break;
4724 case 35727: spellid = 35730; break;
4725 default:
4726 return;
4729 unitTarget->CastSpell(unitTarget,spellid,false);
4730 return;
4732 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4733 case 22539:
4734 case 22972:
4735 case 22975:
4736 case 22976:
4737 case 22977:
4738 case 22978:
4739 case 22979:
4740 case 22980:
4741 case 22981:
4742 case 22982:
4743 case 22983:
4744 case 22984:
4745 case 22985:
4747 if(!unitTarget || !unitTarget->isAlive())
4748 return;
4750 // Onyxia Scale Cloak
4751 if(unitTarget->GetDummyAura(22683))
4752 return;
4754 // Shadow Flame
4755 m_caster->CastSpell(unitTarget, 22682, true);
4756 return;
4758 // Summon Black Qiraji Battle Tank
4759 case 26656:
4761 if(!unitTarget)
4762 return;
4764 // Prevent stacking of mounts
4765 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4767 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4768 if (unitTarget->GetAreaId() == 3428)
4769 unitTarget->CastSpell(unitTarget, 25863, false);
4770 else
4771 unitTarget->CastSpell(unitTarget, 26655, false);
4772 break;
4774 // Piccolo of the Flaming Fire
4775 case 17512:
4777 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4778 return;
4779 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4780 break;
4782 // Mirren's Drinking Hat
4783 case 29830:
4785 uint32 item = 0;
4786 switch ( urand(1,6) )
4788 case 1:case 2:case 3:
4789 item = 23584;break; // Loch Modan Lager
4790 case 4:case 5:
4791 item = 23585;break; // Stouthammer Lite
4792 case 6:
4793 item = 23586;break; // Aerie Peak Pale Ale
4795 if (item)
4796 DoCreateItem(effIndex,item);
4797 break;
4799 // Improved Sprint
4800 case 30918:
4802 // Removes snares and roots.
4803 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4804 Unit::AuraMap& Auras = unitTarget->GetAuras();
4805 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4807 next = iter;
4808 ++next;
4809 Aura *aur = iter->second;
4810 if (!aur->IsPositive()) //only remove negative spells
4812 // check for mechanic mask
4813 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4815 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4816 if(Auras.empty())
4817 break;
4818 else
4819 next = Auras.begin();
4823 break;
4825 // Flame Crash
4826 case 41126:
4828 if(!unitTarget)
4829 return;
4831 unitTarget->CastSpell(unitTarget, 41131, true);
4832 break;
4834 // Force Cast - Portal Effect: Sunwell Isle
4835 case 44876:
4837 if(!unitTarget)
4838 return;
4840 unitTarget->CastSpell(unitTarget, 44870, true);
4841 break;
4843 // Goblin Weather Machine
4844 case 46203:
4846 if(!unitTarget)
4847 return;
4849 uint32 spellId;
4850 switch(rand()%4)
4852 case 0: spellId = 46740; break;
4853 case 1: spellId = 46739; break;
4854 case 2: spellId = 46738; break;
4855 case 3: spellId = 46736; break;
4857 unitTarget->CastSpell(unitTarget, spellId, true);
4858 break;
4860 //5,000 Gold
4861 case 46642:
4863 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4864 return;
4866 ((Player*)unitTarget)->ModifyMoney(50000000);
4868 break;
4870 // Emblazon Runeblade
4871 case 51770:
4873 if(!unitTarget)
4874 return;
4876 unitTarget->CastSpell(unitTarget,51771,false);
4877 break;
4879 // Death Gate
4880 case 52751:
4882 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
4883 return;
4884 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4885 unitTarget->CastSpell(unitTarget, damage, false);
4886 break;
4888 // random spell learn instead placeholder
4889 case 60893: // Northrend Alchemy Research
4890 case 61177: // Northrend Inscription Research
4891 case 61288: // Minor Inscription Research
4892 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4894 if(!IsExplicitDiscoverySpell(m_spellInfo))
4896 sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id);
4897 return;
4900 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
4901 return;
4902 Player* player = (Player*)m_caster;
4904 // need replace effect 0 item by loot
4905 uint32 reagent_id = m_spellInfo->EffectItemType[0];
4907 if(!player->HasItemCount(reagent_id,1))
4908 return;
4910 // remove reagent
4911 uint32 count = 1;
4912 player->DestroyItemCount (reagent_id,count,true);
4914 // create some random items
4915 player->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
4917 // learn random explicit discovery recipe (if any)
4918 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
4919 player->learnSpell(discoveredSpell,false);
4920 return;
4923 break;
4925 case SPELLFAMILY_WARLOCK:
4927 switch(m_spellInfo->Id)
4929 // Healthstone creating spells
4930 case 6201:
4931 case 6202:
4932 case 5699:
4933 case 11729:
4934 case 11730:
4935 case 27230:
4936 case 47871:
4937 case 47878:
4939 uint32 itemtype;
4940 uint32 rank = 0;
4941 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4942 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4944 if((*i)->GetId() == 18692)
4946 rank = 1;
4947 break;
4949 else if((*i)->GetId() == 18693)
4951 rank = 2;
4952 break;
4956 static uint32 const itypes[8][3] = {
4957 { 5512,19004,19005}, // Minor Healthstone
4958 { 5511,19006,19007}, // Lesser Healthstone
4959 { 5509,19008,19009}, // Healthstone
4960 { 5510,19010,19011}, // Greater Healthstone
4961 { 9421,19012,19013}, // Major Healthstone
4962 {22103,22104,22105}, // Master Healthstone
4963 {36889,36890,36891}, // Demonic Healthstone
4964 {36892,36893,36894} // Fel Healthstone
4967 switch(m_spellInfo->Id)
4969 case 6201:
4970 itemtype=itypes[0][rank];break; // Minor Healthstone
4971 case 6202:
4972 itemtype=itypes[1][rank];break; // Lesser Healthstone
4973 case 5699:
4974 itemtype=itypes[2][rank];break; // Healthstone
4975 case 11729:
4976 itemtype=itypes[3][rank];break; // Greater Healthstone
4977 case 11730:
4978 itemtype=itypes[4][rank];break; // Major Healthstone
4979 case 27230:
4980 itemtype=itypes[5][rank];break; // Master Healthstone
4981 case 47871:
4982 itemtype=itypes[6][rank];break; // Demonic Healthstone
4983 case 47878:
4984 itemtype=itypes[7][rank];break; // Fel Healthstone
4985 default:
4986 return;
4988 DoCreateItem( effIndex, itemtype );
4989 return;
4992 break;
4994 case SPELLFAMILY_PRIEST:
4996 switch(m_spellInfo->Id)
4998 // Pain and Suffering
4999 case 47948:
5001 if (!unitTarget)
5002 return;
5003 // Refresh Shadow Word: Pain on target
5004 Unit::AuraMap& auras = unitTarget->GetAuras();
5005 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5007 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5008 if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5009 spellInfo->SpellFamilyFlags & 0x0000000000008000LL &&
5010 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5012 (*itr).second->RefreshAura();
5013 return;
5016 return;
5018 default:
5019 break;
5021 break;
5023 case SPELLFAMILY_HUNTER:
5025 switch(m_spellInfo->Id)
5027 // Chimera Shot
5028 case 53209:
5030 uint32 spellId = 0;
5031 int32 basePoint = 0;
5032 Unit::AuraMap& Auras = unitTarget->GetAuras();
5033 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5035 Aura *aura = (*i).second;
5036 if (aura->GetCasterGUID() != m_caster->GetGUID())
5037 continue;
5038 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5039 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5040 if (!(familyFlag & 0x000000800000C000LL))
5041 continue;
5042 // Refresh aura duration
5043 aura->RefreshAura();
5045 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5046 if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
5048 spellId = 53353; // 53353 Chimera Shot - Serpent
5049 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5051 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5052 if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
5054 spellId = 53358; // 53358 Chimera Shot - Viper
5055 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
5057 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5058 if (familyFlag & 0x0000000000008000LL)
5059 spellId = 53359; // 53359 Chimera Shot - Scorpid
5060 // ?? nothing say in spell desc (possibly need addition check)
5061 //if (familyFlag & 0x0000010000000000LL || // dot
5062 // familyFlag & 0x0000100000000000LL) // stun
5064 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5067 if (spellId)
5068 m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
5069 return;
5071 default:
5072 break;
5074 break;
5076 case SPELLFAMILY_PALADIN:
5078 // Judgement
5079 if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
5081 if(!unitTarget || !unitTarget->isAlive())
5082 return;
5083 uint32 spellId1 = 0;
5084 uint32 spellId2 = 0;
5086 // Judgement self add switch
5087 switch (m_spellInfo->Id)
5089 case 41467: break; // Judgement
5090 case 53407: spellId1 = 20184; break; // Judgement of Justice
5091 case 20271: // Judgement of Light
5092 case 57774: spellId1 = 20185; break; // Judgement of Light
5093 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5094 default:
5095 return;
5097 // all seals have aura dummy in 2 effect
5098 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5099 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5101 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5102 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5103 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5104 continue;
5105 spellId2 = (*itr)->GetModifier()->m_amount;
5106 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5107 if (!judge)
5108 continue;
5109 break;
5111 if (spellId1)
5112 m_caster->CastSpell(unitTarget, spellId1, true);
5113 if (spellId2)
5114 m_caster->CastSpell(unitTarget, spellId2, true);
5115 return;
5118 case SPELLFAMILY_POTION:
5120 switch(m_spellInfo->Id)
5122 // Dreaming Glory
5123 case 28698:
5125 if(!unitTarget)
5126 return;
5127 unitTarget->CastSpell(unitTarget, 28694, true);
5128 break;
5130 // Netherbloom
5131 case 28702:
5133 if(!unitTarget)
5134 return;
5135 // 25% chance of casting a random buff
5136 if(roll_chance_i(75))
5137 return;
5139 // triggered spells are 28703 to 28707
5140 // Note: some sources say, that there was the possibility of
5141 // receiving a debuff. However, this seems to be removed by a patch.
5142 const uint32 spellid = 28703;
5144 // don't overwrite an existing aura
5145 for(uint8 i=0; i<5; i++)
5146 if(unitTarget->HasAura(spellid+i, 0))
5147 return;
5148 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5149 break;
5152 // Nightmare Vine
5153 case 28720:
5155 if(!unitTarget)
5156 return;
5157 // 25% chance of casting Nightmare Pollen
5158 if(roll_chance_i(75))
5159 return;
5160 unitTarget->CastSpell(unitTarget, 28721, true);
5161 break;
5164 break;
5168 // normal DB scripted effect
5169 if(!unitTarget)
5170 return;
5172 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5173 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5176 void Spell::EffectSanctuary(uint32 /*i*/)
5178 if(!unitTarget)
5179 return;
5180 //unitTarget->CombatStop();
5182 unitTarget->CombatStop();
5183 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5184 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5185 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5187 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5191 void Spell::EffectAddComboPoints(uint32 /*i*/)
5193 if(!unitTarget)
5194 return;
5196 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5197 return;
5199 if(damage <= 0)
5200 return;
5202 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5205 void Spell::EffectDuel(uint32 i)
5207 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5208 return;
5210 Player *caster = (Player*)m_caster;
5211 Player *target = (Player*)unitTarget;
5213 // caster or target already have requested duel
5214 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5215 return;
5217 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5218 // Don't have to check the target's map since you cannot challenge someone across maps
5219 uint32 mapid = caster->GetMapId();
5220 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5222 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5223 return;
5226 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5227 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5229 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5230 return;
5233 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5234 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5236 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5237 return;
5240 //CREATE DUEL FLAG OBJECT
5241 GameObject* pGameObj = new GameObject;
5243 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5245 Map *map = m_caster->GetMap();
5246 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5247 map, m_caster->GetPhaseMask(),
5248 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5249 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5250 m_caster->GetPositionZ(),
5251 m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5253 delete pGameObj;
5254 return;
5257 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5258 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5259 int32 duration = GetSpellDuration(m_spellInfo);
5260 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5261 pGameObj->SetSpellId(m_spellInfo->Id);
5263 m_caster->AddGameObject(pGameObj);
5264 map->Add(pGameObj);
5265 //END
5267 // Send request
5268 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5269 data << pGameObj->GetGUID();
5270 data << caster->GetGUID();
5271 caster->GetSession()->SendPacket(&data);
5272 target->GetSession()->SendPacket(&data);
5274 // create duel-info
5275 DuelInfo *duel = new DuelInfo;
5276 duel->initiator = caster;
5277 duel->opponent = target;
5278 duel->startTime = 0;
5279 duel->startTimer = 0;
5280 caster->duel = duel;
5282 DuelInfo *duel2 = new DuelInfo;
5283 duel2->initiator = caster;
5284 duel2->opponent = caster;
5285 duel2->startTime = 0;
5286 duel2->startTimer = 0;
5287 target->duel = duel2;
5289 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5290 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5293 void Spell::EffectStuck(uint32 /*i*/)
5295 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5296 return;
5298 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5299 return;
5301 Player* pTarget = (Player*)unitTarget;
5303 sLog.outDebug("Spell Effect: Stuck");
5304 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());
5306 if(pTarget->isInFlight())
5307 return;
5309 // homebind location is loaded always
5310 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5312 // Stuck spell trigger Hearthstone cooldown
5313 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5314 if(!spellInfo)
5315 return;
5316 Spell spell(pTarget,spellInfo,true,0);
5317 spell.SendSpellCooldown();
5320 void Spell::EffectSummonPlayer(uint32 /*i*/)
5322 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5323 return;
5325 // Evil Twin (ignore player summon, but hide this for summoner)
5326 if(unitTarget->GetDummyAura(23445))
5327 return;
5329 float x,y,z;
5330 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5332 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5334 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5335 data << uint64(m_caster->GetGUID()); // summoner guid
5336 data << uint32(m_caster->GetZoneId()); // summoner zone
5337 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5338 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5341 static ScriptInfo generateActivateCommand()
5343 ScriptInfo si;
5344 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5345 return si;
5348 void Spell::EffectActivateObject(uint32 effect_idx)
5350 if(!gameObjTarget)
5351 return;
5353 static ScriptInfo activateCommand = generateActivateCommand();
5355 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5357 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5360 void Spell::EffectApplyGlyph(uint32 i)
5362 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5363 return;
5365 Player *player = (Player*)m_caster;
5367 // remove old glyph
5368 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5370 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5372 player->RemoveAurasDueToSpell(old_gp->SpellId);
5373 player->SetGlyph(m_glyphIndex, 0);
5377 // apply new one
5378 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5380 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5382 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5384 if(gp->TypeFlags != gs->TypeFlags)
5386 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5387 return; // glyph slot missmatch
5391 player->CastSpell(m_caster, gp->SpellId, true);
5392 player->SetGlyph(m_glyphIndex, glyph);
5397 void Spell::EffectSummonTotem(uint32 i)
5399 uint8 slot = 0;
5400 switch(m_spellInfo->EffectMiscValueB[i])
5402 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5403 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5404 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5405 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5406 // Battle standard case
5407 case SUMMON_TYPE_TOTEM: slot = 254; break;
5408 // jewelery statue case, like totem without slot
5409 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5410 default: return;
5413 if(slot < MAX_TOTEM)
5415 uint64 guid = m_caster->m_TotemSlot[slot];
5416 if(guid != 0)
5418 Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5419 if(OldTotem && OldTotem->isTotem())
5420 ((Totem*)OldTotem)->UnSummon();
5424 uint32 team = 0;
5425 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5426 team = ((Player*)m_caster)->GetTeam();
5428 Totem* pTotem = new Totem;
5430 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5431 m_spellInfo->EffectMiscValue[i], team ))
5433 delete pTotem;
5434 return;
5437 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5439 float x,y,z;
5440 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5442 // totem must be at same Z in case swimming caster and etc.
5443 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5444 z = m_caster->GetPositionZ();
5446 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5448 if(slot < MAX_TOTEM)
5449 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5451 pTotem->SetOwner(m_caster->GetGUID());
5452 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5454 int32 duration=GetSpellDuration(m_spellInfo);
5455 if(Player* modOwner = m_caster->GetSpellModOwner())
5456 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5457 pTotem->SetDuration(duration);
5459 if (damage) // if not spell info, DB values used
5461 pTotem->SetMaxHealth(damage);
5462 pTotem->SetHealth(damage);
5465 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5467 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5468 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5470 pTotem->Summon(m_caster);
5472 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5474 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5475 data << uint8(slot);
5476 data << uint64(pTotem->GetGUID());
5477 data << uint32(duration);
5478 data << uint32(m_spellInfo->Id);
5479 ((Player*)m_caster)->SendDirectMessage(&data);
5483 void Spell::EffectEnchantHeldItem(uint32 i)
5485 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5486 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5487 return;
5489 Player* item_owner = (Player*)unitTarget;
5490 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5492 if(!item )
5493 return;
5495 // must be equipped
5496 if(!item ->IsEquipped())
5497 return;
5499 if (m_spellInfo->EffectMiscValue[i])
5501 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5502 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5503 if(!duration)
5504 duration = m_currentBasePoints[i]+1; //Base points after ..
5505 if(!duration)
5506 duration = 10; //10 seconds for enchants which don't have listed duration
5508 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5509 if(!pEnchant)
5510 return;
5512 // Always go to temp enchantment slot
5513 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5515 // Enchantment will not be applied if a different one already exists
5516 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5517 return;
5519 // Apply the temporary enchantment
5520 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
5521 item_owner->ApplyEnchantment(item,slot,true);
5525 void Spell::EffectDisEnchant(uint32 /*i*/)
5527 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5528 return;
5530 Player* p_caster = (Player*)m_caster;
5531 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5532 return;
5534 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5536 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5538 // item will be removed at disenchanting end
5541 void Spell::EffectInebriate(uint32 /*i*/)
5543 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5544 return;
5546 Player *player = (Player*)unitTarget;
5547 uint16 currentDrunk = player->GetDrunkValue();
5548 uint16 drunkMod = damage * 256;
5549 if (currentDrunk + drunkMod > 0xFFFF)
5550 currentDrunk = 0xFFFF;
5551 else
5552 currentDrunk += drunkMod;
5553 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5556 void Spell::EffectFeedPet(uint32 i)
5558 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5559 return;
5561 Player *_player = (Player*)m_caster;
5563 Item* foodItem = m_targets.getItemTarget();
5564 if(!foodItem)
5565 return;
5567 Pet *pet = _player->GetPet();
5568 if(!pet)
5569 return;
5571 if(!pet->isAlive())
5572 return;
5574 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5575 if(benefit <= 0)
5576 return;
5578 uint32 count = 1;
5579 _player->DestroyItemCount(foodItem,count,true);
5580 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5582 m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5585 void Spell::EffectDismissPet(uint32 /*i*/)
5587 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5588 return;
5590 Pet* pet = m_caster->GetPet();
5592 // not let dismiss dead pet
5593 if(!pet||!pet->isAlive())
5594 return;
5596 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5599 void Spell::EffectSummonObject(uint32 i)
5601 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5603 uint8 slot = 0;
5604 switch(m_spellInfo->Effect[i])
5606 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5607 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5608 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5609 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5610 default: return;
5613 uint64 guid = m_caster->m_ObjectSlot[slot];
5614 if(guid != 0)
5616 GameObject* obj = NULL;
5617 if( m_caster )
5618 obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5620 if(obj) obj->Delete();
5621 m_caster->m_ObjectSlot[slot] = 0;
5624 GameObject* pGameObj = new GameObject;
5626 float rot2 = sin(m_caster->GetOrientation()/2);
5627 float rot3 = cos(m_caster->GetOrientation()/2);
5629 float x,y,z;
5630 // If dest location if present
5631 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5633 x = m_targets.m_destX;
5634 y = m_targets.m_destY;
5635 z = m_targets.m_destZ;
5637 // Summon in random point all other units if location present
5638 else
5639 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5641 Map *map = m_caster->GetMap();
5642 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
5643 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5645 delete pGameObj;
5646 return;
5649 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5650 int32 duration = GetSpellDuration(m_spellInfo);
5651 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5652 pGameObj->SetSpellId(m_spellInfo->Id);
5653 m_caster->AddGameObject(pGameObj);
5655 map->Add(pGameObj);
5656 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5657 data << pGameObj->GetGUID();
5658 m_caster->SendMessageToSet(&data,true);
5660 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5663 void Spell::EffectResurrect(uint32 /*effIndex*/)
5665 if(!unitTarget)
5666 return;
5667 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5668 return;
5670 if(unitTarget->isAlive())
5671 return;
5672 if(!unitTarget->IsInWorld())
5673 return;
5675 switch (m_spellInfo->Id)
5677 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5678 case 8342:
5679 if (roll_chance_i(67))
5681 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5682 return;
5684 break;
5685 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5686 case 22999:
5687 if (roll_chance_i(50))
5689 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5690 return;
5692 break;
5693 default:
5694 break;
5697 Player* pTarget = ((Player*)unitTarget);
5699 if(pTarget->isRessurectRequested()) // already have one active request
5700 return;
5702 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5703 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5705 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5706 SendResurrectRequest(pTarget);
5709 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5711 if(!unitTarget || !unitTarget->isAlive())
5712 return;
5714 if( unitTarget->m_extraAttacks )
5715 return;
5717 unitTarget->m_extraAttacks = damage;
5720 void Spell::EffectParry(uint32 /*i*/)
5722 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5723 ((Player*)unitTarget)->SetCanParry(true);
5726 void Spell::EffectBlock(uint32 /*i*/)
5728 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5729 ((Player*)unitTarget)->SetCanBlock(true);
5732 void Spell::EffectMomentMove(uint32 i)
5734 if(unitTarget->isInFlight())
5735 return;
5737 if( m_spellInfo->rangeIndex== 1) //self range
5739 uint32 mapid = m_caster->GetMapId();
5740 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5742 // before caster
5743 float fx,fy,fz;
5744 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5745 float ox,oy,oz;
5746 unitTarget->GetPosition(ox,oy,oz);
5748 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5749 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5751 fx = fx2;
5752 fy = fy2;
5753 fz = fz2;
5754 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5757 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5758 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5759 else
5760 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5764 void Spell::EffectReputation(uint32 i)
5766 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5767 return;
5769 Player *_player = (Player*)unitTarget;
5771 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5773 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5775 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5777 if(!factionEntry)
5778 return;
5780 _player->ModifyFactionReputation(factionEntry,rep_change);
5783 void Spell::EffectQuestComplete(uint32 i)
5785 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5786 return;
5788 Player *_player = (Player*)m_caster;
5790 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5791 _player->AreaExploredOrEventHappens(quest_id);
5794 void Spell::EffectSelfResurrect(uint32 i)
5796 if(!unitTarget || unitTarget->isAlive())
5797 return;
5798 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5799 return;
5800 if(!unitTarget->IsInWorld())
5801 return;
5803 uint32 health = 0;
5804 uint32 mana = 0;
5806 // flat case
5807 if(damage < 0)
5809 health = uint32(-damage);
5810 mana = m_spellInfo->EffectMiscValue[i];
5812 // percent case
5813 else
5815 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5816 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5817 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5820 Player *plr = ((Player*)unitTarget);
5821 plr->ResurrectPlayer(0.0f);
5823 plr->SetHealth( health );
5824 plr->SetPower(POWER_MANA, mana );
5825 plr->SetPower(POWER_RAGE, 0 );
5826 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5828 plr->SpawnCorpseBones();
5830 plr->SaveToDB();
5833 void Spell::EffectSkinning(uint32 /*i*/)
5835 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5836 return;
5837 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5838 return;
5840 Creature* creature = (Creature*) unitTarget;
5841 int32 targetLevel = creature->getLevel();
5843 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5845 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5846 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5848 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5850 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5852 // Double chances for elites
5853 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5856 void Spell::EffectCharge(uint32 /*i*/)
5858 if(!unitTarget || !m_caster)
5859 return;
5861 float x, y, z;
5862 unitTarget->GetContactPoint(m_caster, x, y, z);
5863 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5864 ((Creature *)unitTarget)->StopMoving();
5866 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5867 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5869 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5870 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5872 // not all charge effects used in negative spells
5873 if ( !IsPositiveSpell(m_spellInfo->Id))
5874 m_caster->Attack(unitTarget,true);
5877 void Spell::EffectSummonCritter(uint32 i)
5879 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5880 return;
5881 Player* player = (Player*)m_caster;
5883 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5884 if(!pet_entry)
5885 return;
5887 Pet* old_critter = player->GetMiniPet();
5889 // for same pet just despawn
5890 if(old_critter && old_critter->GetEntry() == pet_entry)
5892 player->RemoveMiniPet();
5893 return;
5896 // despawn old pet before summon new
5897 if(old_critter)
5898 player->RemoveMiniPet();
5900 // summon new pet
5901 Pet* critter = new Pet(MINI_PET);
5903 Map *map = m_caster->GetMap();
5904 uint32 pet_number = objmgr.GeneratePetNumber();
5905 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
5906 pet_entry, pet_number))
5908 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5909 delete critter;
5910 return;
5913 float x,y,z;
5914 // If dest location if present
5915 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5917 x = m_targets.m_destX;
5918 y = m_targets.m_destY;
5919 z = m_targets.m_destZ;
5921 // Summon if dest location not present near caster
5922 else
5923 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5925 critter->Relocate(x,y,z,m_caster->GetOrientation());
5927 if(!critter->IsPositionValid())
5929 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5930 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5931 delete critter;
5932 return;
5935 critter->SetOwnerGUID(m_caster->GetGUID());
5936 critter->SetCreatorGUID(m_caster->GetGUID());
5937 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5938 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5940 critter->AIM_Initialize();
5941 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5942 critter->SetMaxHealth(1);
5943 critter->SetHealth(1);
5944 critter->SetLevel(1);
5946 // set timer for unsummon
5947 int32 duration = GetSpellDuration(m_spellInfo);
5948 if(duration > 0)
5949 critter->SetDuration(duration);
5951 std::string name = player->GetName();
5952 name.append(petTypeSuffix[critter->getPetType()]);
5953 critter->SetName( name );
5954 player->SetMiniPet(critter);
5956 map->Add((Creature*)critter);
5959 void Spell::EffectKnockBack(uint32 i)
5961 if(!unitTarget || !m_caster)
5962 return;
5964 // Effect only works on players
5965 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5966 return;
5968 float vsin = sin(m_caster->GetAngle(unitTarget));
5969 float vcos = cos(m_caster->GetAngle(unitTarget));
5971 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5972 data.append(unitTarget->GetPackGUID());
5973 data << uint32(0); // Sequence
5974 data << float(vcos); // x direction
5975 data << float(vsin); // y direction
5976 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
5977 data << float(damage/-10); // Z Movement speed (vertical)
5979 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5982 void Spell::EffectSendTaxi(uint32 i)
5984 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5985 return;
5987 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5988 if(!entry)
5989 return;
5991 std::vector<uint32> nodes;
5993 nodes.resize(2);
5994 nodes[0] = entry->from;
5995 nodes[1] = entry->to;
5997 uint32 mountid = 0;
5998 switch(m_spellInfo->Id)
6000 case 31606: //Stormcrow Amulet
6001 mountid = 17447;
6002 break;
6003 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
6004 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
6005 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
6006 mountid = 22840;
6007 break;
6008 case 34905: //Stealth Flight
6009 mountid = 6851;
6010 break;
6011 case 45883: //Amber Ledge to Beryl Point
6012 mountid = 23524;
6013 break;
6014 case 46064: //Amber Ledge to Coldarra
6015 mountid = 6371;
6016 break;
6017 case 53335: //Stormwind Harbor Flight - Peaceful
6018 mountid = 6852;
6019 break;
6022 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
6026 void Spell::EffectPlayerPull(uint32 i)
6028 if(!unitTarget || !m_caster)
6029 return;
6031 // Effect only works on players
6032 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
6033 return;
6035 float vsin = sin(unitTarget->GetAngle(m_caster));
6036 float vcos = cos(unitTarget->GetAngle(m_caster));
6038 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
6039 data.append(unitTarget->GetPackGUID());
6040 data << uint32(0); // Sequence
6041 data << float(vcos); // x direction
6042 data << float(vsin); // y direction
6043 // Horizontal speed
6044 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
6045 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
6047 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6050 void Spell::EffectDispelMechanic(uint32 i)
6052 if(!unitTarget)
6053 return;
6055 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6057 Unit::AuraMap& Auras = unitTarget->GetAuras();
6058 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6060 next = iter;
6061 ++next;
6062 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6063 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6065 unitTarget->RemoveAurasDueToSpell(spell->Id);
6066 if(Auras.empty())
6067 break;
6068 else
6069 next = Auras.begin();
6072 return;
6075 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6077 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6078 return;
6079 Player *_player = (Player*)m_caster;
6080 Pet *pet = _player->GetPet();
6081 if(!pet)
6082 return;
6083 if(pet->isAlive())
6084 return;
6085 if(damage < 0)
6086 return;
6087 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6088 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6089 pet->setDeathState( ALIVE );
6090 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6091 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6093 pet->AIM_Initialize();
6095 _player->PetSpellInitialize();
6096 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6099 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6101 float mana = 0;
6102 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6104 if(!m_caster->m_TotemSlot[slot])
6105 continue;
6107 Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
6108 if(totem && totem->isTotem())
6110 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6111 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6112 if(spellInfo)
6113 mana += spellInfo->manaCost * damage / 100;
6114 ((Totem*)totem)->UnSummon();
6118 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
6119 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
6122 void Spell::EffectDurabilityDamage(uint32 i)
6124 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6125 return;
6127 int32 slot = m_spellInfo->EffectMiscValue[i];
6129 // FIXME: some spells effects have value -1/-2
6130 // Possibly its mean -1 all player equipped items and -2 all items
6131 if(slot < 0)
6133 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
6134 return;
6137 // invalid slot value
6138 if(slot >= INVENTORY_SLOT_BAG_END)
6139 return;
6141 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6142 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
6145 void Spell::EffectDurabilityDamagePCT(uint32 i)
6147 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6148 return;
6150 int32 slot = m_spellInfo->EffectMiscValue[i];
6152 // FIXME: some spells effects have value -1/-2
6153 // Possibly its mean -1 all player equipped items and -2 all items
6154 if(slot < 0)
6156 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
6157 return;
6160 // invalid slot value
6161 if(slot >= INVENTORY_SLOT_BAG_END)
6162 return;
6164 if(damage <= 0)
6165 return;
6167 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6168 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
6171 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6173 if(!unitTarget)
6174 return;
6176 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6179 void Spell::EffectTransmitted(uint32 effIndex)
6181 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6183 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6185 if (!goinfo)
6187 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6188 return;
6191 float fx,fy,fz;
6193 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6195 fx = m_targets.m_destX;
6196 fy = m_targets.m_destY;
6197 fz = m_targets.m_destZ;
6199 //FIXME: this can be better check for most objects but still hack
6200 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6202 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6203 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6205 else
6207 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6208 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6209 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6211 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6214 Map *cMap = m_caster->GetMap();
6216 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6218 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6219 { // but this is not proper, we really need to ignore not materialized objects
6220 SendCastResult(SPELL_FAILED_NOT_HERE);
6221 SendChannelUpdate(0);
6222 return;
6225 // replace by water level in this case
6226 fz = cMap->GetWaterLevel(fx,fy);
6228 // if gameobject is summoning object, it should be spawned right on caster's position
6229 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6231 m_caster->GetPosition(fx,fy,fz);
6234 GameObject* pGameObj = new GameObject;
6236 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6237 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6239 delete pGameObj;
6240 return;
6243 int32 duration = GetSpellDuration(m_spellInfo);
6245 switch(goinfo->type)
6247 case GAMEOBJECT_TYPE_FISHINGNODE:
6249 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6250 // Orientation3
6251 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 );
6252 // Orientation4
6253 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 );
6254 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6256 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6257 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6258 int32 lastSec;
6259 switch(urand(0, 3))
6261 case 0: lastSec = 3; break;
6262 case 1: lastSec = 7; break;
6263 case 2: lastSec = 13; break;
6264 case 3: lastSec = 17; break;
6267 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6268 break;
6270 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6272 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6274 pGameObj->AddUniqueUse((Player*)m_caster);
6275 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6277 break;
6279 case GAMEOBJECT_TYPE_FISHINGHOLE:
6280 case GAMEOBJECT_TYPE_CHEST:
6281 default:
6283 break;
6287 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6289 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6291 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6292 pGameObj->SetSpellId(m_spellInfo->Id);
6294 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6295 //m_caster->AddGameObject(pGameObj);
6296 //m_ObjToDel.push_back(pGameObj);
6298 cMap->Add(pGameObj);
6300 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6301 data << uint64(pGameObj->GetGUID());
6302 m_caster->SendMessageToSet(&data,true);
6304 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6306 GameObject* linkedGO = new GameObject;
6307 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6308 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6310 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6311 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6312 linkedGO->SetSpellId(m_spellInfo->Id);
6313 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6315 linkedGO->GetMap()->Add(linkedGO);
6317 else
6319 delete linkedGO;
6320 linkedGO = NULL;
6321 return;
6326 void Spell::EffectProspecting(uint32 /*i*/)
6328 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6329 return;
6331 Player* p_caster = (Player*)m_caster;
6332 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6333 return;
6335 if(itemTarget->GetCount() < 5)
6336 return;
6338 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6340 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6341 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6342 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6345 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6348 void Spell::EffectMilling(uint32 /*i*/)
6350 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6351 return;
6353 Player* p_caster = (Player*)m_caster;
6354 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6355 return;
6357 if(itemTarget->GetCount() < 5)
6358 return;
6360 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6362 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6363 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6364 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6367 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6370 void Spell::EffectSkill(uint32 /*i*/)
6372 sLog.outDebug("WORLD: SkillEFFECT");
6375 void Spell::EffectSummonDemon(uint32 i)
6377 float px = m_targets.m_destX;
6378 float py = m_targets.m_destY;
6379 float pz = m_targets.m_destZ;
6381 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6382 if (!Charmed)
6383 return;
6385 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6386 Charmed->SetLevel(m_caster->getLevel());
6388 // TODO: Add damage/mana/hp according to level
6390 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6392 // Enslave demon effect, without mana cost and cooldown
6393 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6395 // Inferno effect
6396 Charmed->CastSpell(Charmed, 22703, true, 0);
6400 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6401 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6402 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6403 This is why we use a half sec delay between the visual effect and the resurrection itself */
6404 void Spell::EffectSpiritHeal(uint32 /*i*/)
6407 if(!unitTarget || unitTarget->isAlive())
6408 return;
6409 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6410 return;
6411 if(!unitTarget->IsInWorld())
6412 return;
6414 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6415 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6416 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6417 ((Player*)unitTarget)->SpawnCorpseBones();
6421 // remove insignia spell effect
6422 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6424 sLog.outDebug("Effect: SkinPlayerCorpse");
6425 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6426 return;
6428 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6431 void Spell::EffectStealBeneficialBuff(uint32 i)
6433 sLog.outDebug("Effect: StealBeneficialBuff");
6435 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6436 return;
6438 std::vector <Aura *> steal_list;
6439 // Create dispel mask by dispel type
6440 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6441 Unit::AuraMap const& auras = unitTarget->GetAuras();
6442 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6444 Aura *aur = (*itr).second;
6445 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6447 // Need check for passive? this
6448 if (aur->IsPositive() && !aur->IsPassive())
6449 steal_list.push_back(aur);
6452 // Ok if exist some buffs for dispel try dispel it
6453 if (!steal_list.empty())
6455 std::list < std::pair<uint32,uint64> > success_list;
6456 int32 list_size = steal_list.size();
6457 // Dispell N = damage buffs (or while exist buffs for dispel)
6458 for (int32 count=0; count < damage && list_size > 0; ++count)
6460 // Random select buff for dispel
6461 Aura *aur = steal_list[urand(0, list_size-1)];
6462 // Not use chance for steal
6463 // TODO possible need do it
6464 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6466 // Remove buff from list for prevent doubles
6467 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6469 Aura *stealed = *j;
6470 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6472 j = steal_list.erase(j);
6473 --list_size;
6475 else
6476 ++j;
6479 // Really try steal and send log
6480 if (!success_list.empty())
6482 int32 count = success_list.size();
6483 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6484 data.append(unitTarget->GetPackGUID()); // Victim GUID
6485 data.append(m_caster->GetPackGUID()); // Caster GUID
6486 data << uint32(m_spellInfo->Id); // Dispell spell id
6487 data << uint8(0); // not used
6488 data << uint32(count); // count
6489 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6491 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6492 data << uint32(spellInfo->Id); // Spell Id
6493 data << uint8(0); // 0 - steals !=0 transfers
6494 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6496 m_caster->SendMessageToSet(&data, true);
6501 void Spell::EffectKillCredit(uint32 i)
6503 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6504 return;
6506 ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6509 void Spell::EffectQuestFail(uint32 i)
6511 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6512 return;
6514 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6517 void Spell::EffectActivateRune(uint32 eff_idx)
6519 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6520 return;
6522 Player *plr = (Player*)m_caster;
6524 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6525 return;
6527 for(uint32 j = 0; j < MAX_RUNES; ++j)
6529 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6531 plr->SetRuneCooldown(j, 0);
6536 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6538 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6539 ((Player*)unitTarget)->SetCanTitanGrip(true);
6542 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6544 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6545 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6546 return;
6548 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);