[7732] Fixed compile warnings.
[getmangos.git] / src / game / SpellEffects.cpp
blob216b018d39e320d7ab5983620df72516f8348256
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "UpdateMask.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "SpellMgr.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
39 #include "Pet.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
42 #include "Creature.h"
43 #include "Totem.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
50 #include "Language.h"
51 #include "SocialMgr.h"
52 #include "Util.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
56 #include "Formulas.h"
58 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
60 &Spell::EffectNULL, // 0
61 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
120 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
151 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
199 &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
210 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL, //154 unused
215 &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
218 &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
222 void Spell::EffectNULL(uint32 /*i*/)
224 sLog.outDebug("WORLD: Spell Effect DUMMY");
227 void Spell::EffectUnused(uint32 /*i*/)
229 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
232 void Spell::EffectResurrectNew(uint32 i)
234 if(!unitTarget || unitTarget->isAlive())
235 return;
237 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
238 return;
240 if(!unitTarget->IsInWorld())
241 return;
243 Player* pTarget = ((Player*)unitTarget);
245 if(pTarget->isRessurectRequested()) // already have one active request
246 return;
248 uint32 health = damage;
249 uint32 mana = m_spellInfo->EffectMiscValue[i];
250 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
251 SendResurrectRequest(pTarget);
254 void Spell::EffectInstaKill(uint32 /*i*/)
256 if( !unitTarget || !unitTarget->isAlive() )
257 return;
259 // Demonic Sacrifice
260 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
262 uint32 entry = unitTarget->GetEntry();
263 uint32 spellID;
264 switch(entry)
266 case 416: spellID=18789; break; //imp
267 case 417: spellID=18792; break; //fellhunter
268 case 1860: spellID=18790; break; //void
269 case 1863: spellID=18791; break; //succubus
270 case 17252: spellID=35701; break; //fellguard
271 default:
272 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
273 return;
276 m_caster->CastSpell(m_caster,spellID,true);
279 if(m_caster==unitTarget) // prevent interrupt message
280 finish();
282 uint32 health = unitTarget->GetHealth();
283 m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
286 void Spell::EffectEnvirinmentalDMG(uint32 i)
288 uint32 absorb = 0;
289 uint32 resist = 0;
291 // Note: this hack with damage replace required until GO casting not implemented
292 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
293 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
294 damage = m_spellInfo->CalculateSimpleValue(i);
296 m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
298 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
299 if(m_caster->GetTypeId() == TYPEID_PLAYER)
300 ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE,damage);
303 void Spell::EffectSchoolDMG(uint32 effect_idx)
305 if( unitTarget && unitTarget->isAlive())
307 switch(m_spellInfo->SpellFamilyName)
309 case SPELLFAMILY_GENERIC:
311 //Gore
312 if(m_spellInfo->SpellIconID == 2269 )
314 damage+= rand()%2 ? damage : 0;
317 switch(m_spellInfo->Id) // better way to check unknown
319 // Meteor like spells (divided damage to targets)
320 case 24340: case 26558: case 28884: // Meteor
321 case 36837: case 38903: case 41276: // Meteor
322 case 26789: // Shard of the Fallen Star
323 case 31436: // Malevolent Cleave
324 case 35181: // Dive Bomb
325 case 40810: case 43267: case 43268: // Saber Lash
326 case 42384: // Brutal Swipe
327 case 45150: // Meteor Slash
329 uint32 count = 0;
330 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
331 if(ihit->effectMask & (1<<effect_idx))
332 ++count;
334 damage /= count; // divide to all targets
335 break;
337 // percent from health with min
338 case 25599: // Thundercrash
340 damage = unitTarget->GetHealth() / 2;
341 if(damage < 200)
342 damage = 200;
343 break;
345 // Intercept (warrior spell trigger)
346 case 20253:
347 case 61491:
349 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
350 break;
353 break;
356 case SPELLFAMILY_MAGE:
358 // Arcane Blast
359 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
361 m_caster->CastSpell(m_caster,36032,true);
363 break;
365 case SPELLFAMILY_WARRIOR:
367 // Bloodthirst
368 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
370 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
372 // Shield Slam
373 else if(m_spellInfo->SpellFamilyFlags & 0x0000020000000000LL && m_spellInfo->Category==1209)
374 damage += int32(m_caster->GetShieldBlockValue());
375 // Victory Rush
376 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
378 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
379 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
381 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
382 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL)
383 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
384 // Heroic Throw ${$m1+$AP*.50}
385 else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL)
386 damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
387 // Shockwave ${$m3/100*$AP}
388 else if(m_spellInfo->SpellFamilyFlags & 0x0000800000000000LL)
390 int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
391 if (pct > 0)
392 damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
393 break;
395 break;
397 case SPELLFAMILY_WARLOCK:
399 // Incinerate Rank 1 & 2
400 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
402 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
403 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
404 damage += int32(damage*0.25f);
406 break;
408 case SPELLFAMILY_PRIEST:
410 // Shadow Word: Death - deals damage equal to damage done to caster
411 if (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
412 m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true);
413 break;
415 case SPELLFAMILY_DRUID:
417 // Ferocious Bite
418 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
420 // converts each extra point of energy into ($f1+$AP/410) additional damage
421 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
422 float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
423 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
424 damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
425 m_caster->SetPower(POWER_ENERGY,0);
427 // Rake
428 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
430 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
432 // Swipe
433 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
435 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
437 //Mangle Bonus for the initial damage of Lacerate and Rake
438 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
439 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
441 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
442 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
443 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
445 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
446 break;
449 break;
451 case SPELLFAMILY_ROGUE:
453 // Envenom
454 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
456 // consume from stack dozes not more that have combo-points
457 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
459 Aura *poison = 0;
460 // Lookup for Deadly poison (only attacker applied)
461 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
462 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
463 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
464 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
465 (*itr)->GetCasterGUID()==m_caster->GetGUID() )
467 poison = *itr;
468 break;
470 // count consumed deadly poison doses at target
471 if (poison)
473 uint32 spellId = poison->GetId();
474 uint32 doses = poison->GetStackAmount();
475 if (doses > combo)
476 doses = combo;
477 for (int i=0; i< doses; i++)
478 unitTarget->RemoveSingleSpellAurasFromStack(spellId);
479 damage *= doses;
480 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
482 // Eviscerate and Envenom Bonus Damage (item set effect)
483 if(m_caster->GetDummyAura(37169))
484 damage += ((Player*)m_caster)->GetComboPoints()*40;
487 // Eviscerate
488 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
490 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
492 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
493 damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
495 // Eviscerate and Envenom Bonus Damage (item set effect)
496 if(m_caster->GetDummyAura(37169))
497 damage += combo*40;
500 // Gouge
501 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL)
503 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
505 // Instant Poison
506 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
508 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
510 // Wound Poison
511 else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL)
513 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
515 break;
517 case SPELLFAMILY_HUNTER:
519 // Mongoose Bite
520 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
522 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
524 // Counterattack
525 else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL)
527 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
529 // Arcane Shot
530 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
532 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
534 // Steady Shot
535 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
537 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
538 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
540 // Explosive Trap Effect
541 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
543 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
545 break;
547 case SPELLFAMILY_PALADIN:
549 // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target
550 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
552 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
553 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
554 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
555 damage+=int32(ap * 0.14f) + int32(holy * 22 / 100);
556 // Get stack of Holy Vengeance on the target added by caster
557 uint32 stacks = 0;
558 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
559 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
560 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
562 stacks = (*itr)->GetStackAmount();
563 break;
565 // + 10% for each application of Holy Vengeance on the target
566 if(stacks)
567 damage += damage * stacks * 10 /100;
569 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
570 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
572 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
573 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
574 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
575 damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
577 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
578 else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL)
580 float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
581 int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
582 m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
583 damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
585 // Hammer of the Righteous
586 else if(m_spellInfo->SpellFamilyFlags&0x0004000000000000LL)
588 // Add main hand dps * effect[2] amount
589 float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
590 int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
591 damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
593 // Shield of Righteousness
594 else if(m_spellInfo->SpellFamilyFlags&0x0010000000000000LL)
596 damage+=int32(m_caster->GetShieldBlockValue());
598 break;
602 if(damage >= 0)
603 m_damage+= damage;
607 void Spell::EffectDummy(uint32 i)
609 if(!unitTarget && !gameObjTarget && !itemTarget)
610 return;
612 // selection by spell family
613 switch(m_spellInfo->SpellFamilyName)
615 case SPELLFAMILY_GENERIC:
617 switch(m_spellInfo->Id )
619 case 8063: // Deviate Fish
621 if(m_caster->GetTypeId() != TYPEID_PLAYER)
622 return;
624 uint32 spell_id = 0;
625 switch(urand(1,5))
627 case 1: spell_id = 8064; break; // Sleepy
628 case 2: spell_id = 8065; break; // Invigorate
629 case 3: spell_id = 8066; break; // Shrink
630 case 4: spell_id = 8067; break; // Party Time!
631 case 5: spell_id = 8068; break; // Healthy Spirit
633 m_caster->CastSpell(m_caster,spell_id,true,NULL);
634 return;
636 case 8213: // Savory Deviate Delight
638 if(m_caster->GetTypeId() != TYPEID_PLAYER)
639 return;
641 uint32 spell_id = 0;
642 switch(urand(1,2))
644 // Flip Out - ninja
645 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
646 // Yaaarrrr - pirate
647 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
649 m_caster->CastSpell(m_caster,spell_id,true,NULL);
650 return;
652 case 8593: // Symbol of life (restore creature to life)
653 case 31225: // Shimmering Vessel (restore creature to life)
655 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
656 return;
657 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
658 return;
660 case 12162: // Deep wounds
661 case 12850: // (now good common check for this spells)
662 case 12868:
664 if(!unitTarget)
665 return;
667 float damage;
668 // DW should benefit of attack power, damage percent mods etc.
669 // TODO: check if using offhand damage is correct and if it should be divided by 2
670 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
671 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
672 else
673 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
675 switch (m_spellInfo->Id)
677 case 12850: damage *= 0.2f; break;
678 case 12162: damage *= 0.4f; break;
679 case 12868: damage *= 0.6f; break;
680 default:
681 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
682 return;
685 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
686 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
687 return;
689 case 13120: // net-o-matic
691 if(!unitTarget)
692 return;
694 uint32 spell_id = 0;
696 uint32 roll = urand(0, 99);
698 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
699 spell_id = 16566;
700 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
701 spell_id = 13119;
702 else // normal root
703 spell_id = 13099;
705 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
706 return;
708 case 13567: // Dummy Trigger
710 // can be used for different aura triggering, so select by aura
711 if(!m_triggeredByAuraSpell || !unitTarget)
712 return;
714 switch(m_triggeredByAuraSpell->Id)
716 case 26467: // Persistent Shield
717 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
718 break;
719 default:
720 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
721 break;
723 return;
725 case 15998: // Capture Worg Pup
726 case 29435: // Capture Female Kaliri Hatchling
728 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
729 return;
731 Creature* creatureTarget = (Creature*)unitTarget;
732 creatureTarget->setDeathState(JUST_DIED);
733 creatureTarget->RemoveCorpse();
734 creatureTarget->SetHealth(0); // just for nice GM-mode view
735 return;
737 case 16589: // Noggenfogger Elixir
739 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
740 return;
742 uint32 spell_id = 0;
743 switch(urand(1,3))
745 case 1: spell_id = 16595; break;
746 case 2: spell_id = 16593; break;
747 default:spell_id = 16591; break;
750 m_caster->CastSpell(m_caster,spell_id,true,NULL);
751 return;
753 case 17251: // Spirit Healer Res
755 if(!unitTarget || !m_originalCaster)
756 return;
758 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
760 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
761 data << unitTarget->GetGUID();
762 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
764 return;
766 case 17271: // Test Fetid Skull
768 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
769 return;
771 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
773 m_caster->CastSpell(m_caster,spell_id,true,NULL);
774 return;
776 case 20577: // Cannibalize
777 if (unitTarget)
778 m_caster->CastSpell(m_caster,20578,false,NULL);
779 return;
780 case 23019: // Crystal Prison Dummy DND
782 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
783 return;
785 Creature* creatureTarget = (Creature*)unitTarget;
786 if(creatureTarget->isPet())
787 return;
789 GameObject* pGameObj = new GameObject;
791 Map *map = creatureTarget->GetMap();
793 // create before death for get proper coordinates
794 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(),
795 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
796 creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) )
798 delete pGameObj;
799 return;
802 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
803 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
804 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
805 pGameObj->SetSpellId(m_spellInfo->Id);
807 creatureTarget->setDeathState(JUST_DIED);
808 creatureTarget->RemoveCorpse();
809 creatureTarget->SetHealth(0); // just for nice GM-mode view
811 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
812 map->Add(pGameObj);
814 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
815 data << uint64(pGameObj->GetGUID());
816 m_caster->SendMessageToSet(&data,true);
818 return;
820 case 23074: // Arcanite Dragonling
821 if (!m_CastItem) return;
822 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
823 return;
824 case 23075: // Mithril Mechanical Dragonling
825 if (!m_CastItem) return;
826 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
827 return;
828 case 23076: // Mechanical Dragonling
829 if (!m_CastItem) return;
830 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
831 return;
832 case 23133: // Gnomish Battle Chicken
833 if (!m_CastItem) return;
834 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
835 return;
836 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
838 int32 r = irand(0, 119);
839 if ( r < 20 ) // 1/6 polymorph
840 m_caster->CastSpell(m_caster,23444,true);
841 else if ( r < 100 ) // 4/6 evil twin
842 m_caster->CastSpell(m_caster,23445,true);
843 else // 1/6 miss the target
844 m_caster->CastSpell(m_caster,36902,true);
845 return;
847 case 23453: // Ultrasafe Transporter: Gadgetzan
848 if ( roll_chance_i(50) ) // success
849 m_caster->CastSpell(m_caster,23441,true);
850 else // failure
851 m_caster->CastSpell(m_caster,23446,true);
852 return;
853 case 23645: // Hourglass Sand
854 m_caster->RemoveAurasDueToSpell(23170);
855 return;
856 case 23725: // Gift of Life (warrior bwl trinket)
857 m_caster->CastSpell(m_caster,23782,true);
858 m_caster->CastSpell(m_caster,23783,true);
859 return;
860 case 25860: // Reindeer Transformation
862 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
863 return;
865 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
866 float speed = m_caster->GetSpeedRate(MOVE_RUN);
868 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
870 //5 different spells used depending on mounted speed and if mount can fly or not
871 if (flyspeed >= 4.1f)
872 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
873 else if (flyspeed >= 3.8f)
874 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
875 else if (flyspeed >= 1.6f)
876 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
877 else if (speed >= 2.0f)
878 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
879 else
880 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
882 return;
884 //case 26074: // Holiday Cheer
885 // return; -- implemented at client side
886 case 28006: // Arcane Cloaking
888 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER )
889 m_caster->CastSpell(unitTarget,29294,true);
890 return;
892 case 28730: // Arcane Torrent (Mana)
894 Aura * dummy = m_caster->GetDummyAura(28734);
895 if (dummy)
897 int32 bp = damage * dummy->GetStackAmount();
898 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
899 m_caster->RemoveAurasDueToSpell(28734);
901 return;
903 case 29200: // Purify Helboar Meat
905 if( m_caster->GetTypeId() != TYPEID_PLAYER )
906 return;
908 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
910 m_caster->CastSpell(m_caster,spell_id,true,NULL);
911 return;
913 case 29858: // Soulshatter
914 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
915 m_caster->CastSpell(unitTarget,32835,true);
916 return;
917 case 30458: // Nigh Invulnerability
918 if (!m_CastItem) return;
919 if(roll_chance_i(86)) // success
920 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
921 else // backfire in 14% casts
922 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
923 return;
924 case 30507: // Poultryizer
925 if (!m_CastItem) return;
926 if(roll_chance_i(80)) // success
927 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
928 else // backfire 20%
929 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
930 return;
931 case 33060: // Make a Wish
933 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
934 return;
936 uint32 spell_id = 0;
938 switch(urand(1,5))
940 case 1: spell_id = 33053; break;
941 case 2: spell_id = 33057; break;
942 case 3: spell_id = 33059; break;
943 case 4: spell_id = 33062; break;
944 case 5: spell_id = 33064; break;
947 m_caster->CastSpell(m_caster,spell_id,true,NULL);
948 return;
950 case 35745:
952 uint32 spell_id;
953 switch(m_caster->GetAreaId())
955 case 3900: spell_id = 35743; break;
956 case 3742: spell_id = 35744; break;
957 default: return;
960 m_caster->CastSpell(m_caster,spell_id,true);
961 return;
963 case 37674: // Chaos Blast
965 if(!unitTarget)
966 return;
968 int32 basepoints0 = 100;
969 m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true);
970 return;
972 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
974 // selecting one from Bloodstained Fortune item
975 uint32 newitemid;
976 switch(urand(1,20))
978 case 1: newitemid = 32688; break;
979 case 2: newitemid = 32689; break;
980 case 3: newitemid = 32690; break;
981 case 4: newitemid = 32691; break;
982 case 5: newitemid = 32692; break;
983 case 6: newitemid = 32693; break;
984 case 7: newitemid = 32700; break;
985 case 8: newitemid = 32701; break;
986 case 9: newitemid = 32702; break;
987 case 10: newitemid = 32703; break;
988 case 11: newitemid = 32704; break;
989 case 12: newitemid = 32705; break;
990 case 13: newitemid = 32706; break;
991 case 14: newitemid = 32707; break;
992 case 15: newitemid = 32708; break;
993 case 16: newitemid = 32709; break;
994 case 17: newitemid = 32710; break;
995 case 18: newitemid = 32711; break;
996 case 19: newitemid = 32712; break;
997 case 20: newitemid = 32713; break;
998 default:
999 return;
1002 DoCreateItem(i,newitemid);
1003 return;
1005 // Demon Broiled Surprise
1006 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1007 case 43723:
1009 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1010 return;
1012 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1013 return;
1016 case 44875: // Complete Raptor Capture
1018 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1019 return;
1021 Creature* creatureTarget = (Creature*)unitTarget;
1023 creatureTarget->setDeathState(JUST_DIED);
1024 creatureTarget->RemoveCorpse();
1025 creatureTarget->SetHealth(0); // just for nice GM-mode view
1027 //cast spell Raptor Capture Credit
1028 m_caster->CastSpell(m_caster,42337,true,NULL);
1029 return;
1031 case 34665: //Administer Antidote
1033 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1034 return;
1036 if(!unitTarget)
1037 return;
1039 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1040 if(!tempSummon)
1041 return;
1043 uint32 health = tempSummon->GetHealth();
1045 float x = tempSummon->GetPositionX();
1046 float y = tempSummon->GetPositionY();
1047 float z = tempSummon->GetPositionZ();
1048 float o = tempSummon->GetOrientation();
1049 tempSummon->UnSummon();
1051 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1052 if (!pCreature)
1053 return;
1055 pCreature->SetHealth(health);
1056 ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992,pCreature);
1058 if (pCreature->AI())
1059 pCreature->AI()->AttackStart(m_caster);
1061 return;
1063 case 44997: // Converting Sentry
1065 //Converted Sentry Credit
1066 m_caster->CastSpell(m_caster, 45009, true);
1067 return;
1069 case 45030: // Impale Emissary
1071 // Emissary of Hate Credit
1072 m_caster->CastSpell(m_caster, 45088, true);
1073 return;
1075 case 50243: // Teach Language
1077 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1078 return;
1080 // spell has a 1/3 chance to trigger one of the below
1081 if(roll_chance_i(66))
1082 return;
1083 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1085 // 1000001 - gnomish binary
1086 m_caster->CastSpell(m_caster, 50242, true);
1088 else
1090 // 01001000 - goblin binary
1091 m_caster->CastSpell(m_caster, 50246, true);
1094 return;
1096 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1098 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1099 return;
1101 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1102 bg->EventPlayerDroppedFlag((Player*)m_caster);
1104 m_caster->CastSpell(m_caster, 30452, true, NULL);
1105 return;
1107 case 52308:
1109 switch(i)
1111 case 0:
1113 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
1114 uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1);
1116 if (m_caster->HasAura(reqAuraID,0))
1117 m_caster->CastSpell(m_caster,spellID,true,NULL);
1118 return;
1120 case 1:
1121 return; // additional data for dummy[0]
1123 return;
1125 case 53341:
1126 case 53343:
1128 m_caster->CastSpell(m_caster,54586,true);
1129 return;
1131 case 58418: // Portal to Orgrimmar
1132 case 58420: // Portal to Stormwind
1133 return; // implemented in EffectScript[0]
1136 //All IconID Check in there
1137 switch(m_spellInfo->SpellIconID)
1139 // Berserking (troll racial traits)
1140 case 1661:
1142 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1143 int32 melee_mod = 10;
1144 if (healthPerc <= 40)
1145 melee_mod = 30;
1146 if (healthPerc < 100 && healthPerc > 40)
1147 melee_mod = 10+(100-healthPerc)/3;
1149 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1150 int32 hasteModBasePoints1 = (5-melee_mod);
1151 int32 hasteModBasePoints2 = 5;
1153 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1154 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1155 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1156 return;
1159 break;
1161 case SPELLFAMILY_MAGE:
1162 switch(m_spellInfo->Id )
1164 case 11958: // Cold Snap
1166 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1167 return;
1169 // immediately finishes the cooldown on Frost spells
1170 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1171 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1173 if (itr->second->state == PLAYERSPELL_REMOVED)
1174 continue;
1176 uint32 classspell = itr->first;
1177 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1179 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1180 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1181 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1183 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1185 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1186 data << uint32(classspell);
1187 data << uint64(m_caster->GetGUID());
1188 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1191 return;
1193 case 32826:
1195 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1197 //Polymorph Cast Visual Rank 1
1198 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1199 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1201 return;
1204 break;
1205 case SPELLFAMILY_WARRIOR:
1206 // Charge
1207 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1209 int32 chargeBasePoints0 = damage;
1210 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1211 return;
1213 // Execute
1214 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1216 if(!unitTarget)
1217 return;
1219 uint32 rage = m_caster->GetPower(POWER_RAGE);
1220 // Glyph of Execution bonus
1221 if (Aura *aura = m_caster->GetDummyAura(58367))
1222 rage+=aura->GetModifier()->m_amount;
1224 int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
1225 m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
1226 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1227 m_caster->SetPower(POWER_RAGE,0);
1228 return;
1230 // Slam
1231 if(m_spellInfo->SpellFamilyFlags & 0x0000000000200000LL)
1233 if(!unitTarget)
1234 return;
1235 m_damage+=m_caster->CalculateDamage(m_attackType, false);
1236 m_damage+=damage;
1237 return;
1239 // Concussion Blow
1240 if(m_spellInfo->SpellFamilyFlags & 0x0000000004000000LL)
1242 m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
1243 return;
1245 switch(m_spellInfo->Id)
1247 // Warrior's Wrath
1248 case 21977:
1250 if(!unitTarget)
1251 return;
1252 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1253 return;
1255 // Last Stand
1256 case 12975:
1258 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
1259 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
1260 return;
1262 // Bloodthirst
1263 case 23881:
1265 m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
1266 return;
1269 break;
1270 case SPELLFAMILY_WARLOCK:
1271 // Life Tap
1272 if (m_spellInfo->SpellFamilyFlags & 0x0000000000040000LL)
1274 // In 303 exist spirit depend
1275 uint32 spirit = uint32(m_caster->GetStat(STAT_SPIRIT));
1276 switch (m_spellInfo->Id)
1278 case 1454: damage+=spirit; break;
1279 case 1455: damage+=spirit*15/10; break;
1280 case 1456: damage+=spirit*2; break;
1281 case 11687: damage+=spirit*25/10; break;
1282 case 11688:
1283 case 11689:
1284 case 27222:
1285 case 57946: damage+=spirit*3; break;
1286 default:
1287 sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id);
1288 return;
1290 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1291 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1292 if(unitTarget && (int32(unitTarget->GetHealth()) > damage))
1294 // Shouldn't Appear in Combat Log
1295 unitTarget->ModifyHealth(-damage);
1297 int32 mana = damage;
1298 // Improved Life Tap mod
1299 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1300 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1302 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1303 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1305 m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true);
1307 // Mana Feed
1308 int32 manaFeedVal = 0;
1309 Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
1310 for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr)
1312 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982)
1313 manaFeedVal+= (*itr)->GetModifier()->m_amount;
1315 if(manaFeedVal > 0)
1317 manaFeedVal = manaFeedVal * mana / 100;
1318 m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL);
1321 else
1322 SendCastResult(SPELL_FAILED_FIZZLE);
1323 return;
1325 break;
1326 case SPELLFAMILY_PRIEST:
1327 // Penance
1328 if (m_spellInfo->SpellFamilyFlags & 0x0080000000000000LL)
1330 if (!unitTarget)
1331 return;
1333 int hurt = 0;
1334 int heal = 0;
1335 switch(m_spellInfo->Id)
1337 case 47540: hurt = 47758; heal = 47757; break;
1338 case 53005: hurt = 53001; heal = 52986; break;
1339 case 53006: hurt = 53002; heal = 52987; break;
1340 case 53007: hurt = 53003; heal = 52988; break;
1341 default:
1342 sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id);
1343 return;
1345 if (m_caster->IsFriendlyTo(unitTarget))
1346 m_caster->CastSpell(unitTarget, heal, true, 0);
1347 else
1348 m_caster->CastSpell(unitTarget, hurt, true, 0);
1349 return;
1351 break;
1352 case SPELLFAMILY_DRUID:
1353 // Starfall
1354 if (m_spellInfo->SpellFamilyFlags2 & 0x00000100LL)
1356 //Shapeshifting into an animal form or mounting cancels the effect.
1357 if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
1359 if(m_triggeredByAuraSpell)
1360 m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
1361 return;
1364 //Any effect which causes you to lose control of your character will supress the starfall effect.
1365 if(m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
1366 return;
1368 switch(m_spellInfo->Id)
1370 case 50286: m_caster->CastSpell(unitTarget, 50288, true); return;
1371 case 53196: m_caster->CastSpell(unitTarget, 53191, true); return;
1372 case 53197: m_caster->CastSpell(unitTarget, 53194, true); return;
1373 case 53198: m_caster->CastSpell(unitTarget, 53195, true); return;
1374 default:
1375 sLog.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo->Id);
1376 return;
1379 break;
1380 case SPELLFAMILY_ROGUE:
1381 switch(m_spellInfo->Id )
1383 case 5938: // Shiv
1385 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1386 return;
1388 Player *pCaster = ((Player*)m_caster);
1390 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1391 if(!item)
1392 return;
1394 // all poison enchantments is temporary
1395 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1396 if(!enchant_id)
1397 return;
1399 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1400 if(!pEnchant)
1401 return;
1403 for (int s=0;s<3;s++)
1405 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1406 continue;
1408 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1409 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1410 continue;
1412 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1415 m_caster->CastSpell(unitTarget, 5940, true);
1416 return;
1418 case 14185: // Preparation Rogue
1420 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1421 return;
1423 //immediately finishes the cooldown on certain Rogue abilities
1424 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1425 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1427 uint32 classspell = itr->first;
1428 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1430 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL))
1432 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1434 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1435 data << uint32(classspell);
1436 data << uint64(m_caster->GetGUID());
1437 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1440 return;
1442 case 31231: // Cheat Death
1444 m_caster->CastSpell(m_caster,45182,true);
1445 return;
1448 break;
1449 case SPELLFAMILY_HUNTER:
1450 // Steady Shot
1451 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1453 if( !unitTarget || !unitTarget->isAlive())
1454 return;
1456 bool found = false;
1458 // check dazed affect
1459 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1460 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1462 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1464 found = true;
1465 break;
1469 if(found)
1470 m_damage+= damage;
1471 return;
1474 switch(m_spellInfo->Id)
1476 case 23989: //Readiness talent
1478 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1479 return;
1481 //immediately finishes the cooldown for hunter abilities
1482 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1483 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1485 uint32 classspell = itr->first;
1486 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1488 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1490 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1492 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1493 data << uint32(classspell);
1494 data << uint64(m_caster->GetGUID());
1495 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1498 return;
1500 case 37506: // Scatter Shot
1502 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1503 return;
1505 // break Auto Shot and autohit
1506 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1507 m_caster->AttackStop();
1508 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1509 return;
1512 break;
1513 case SPELLFAMILY_PALADIN:
1514 switch(m_spellInfo->SpellIconID)
1516 case 156: // Holy Shock
1518 if(!unitTarget)
1519 return;
1521 int hurt = 0;
1522 int heal = 0;
1524 switch(m_spellInfo->Id)
1526 case 20473: hurt = 25912; heal = 25914; break;
1527 case 20929: hurt = 25911; heal = 25913; break;
1528 case 20930: hurt = 25902; heal = 25903; break;
1529 case 27174: hurt = 27176; heal = 27175; break;
1530 case 33072: hurt = 33073; heal = 33074; break;
1531 case 48824: hurt = 48822; heal = 48820; break;
1532 case 48825: hurt = 48823; heal = 48821; break;
1533 default:
1534 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1535 return;
1538 if(m_caster->IsFriendlyTo(unitTarget))
1539 m_caster->CastSpell(unitTarget, heal, true, 0);
1540 else
1541 m_caster->CastSpell(unitTarget, hurt, true, 0);
1543 return;
1545 case 561: // Judgement of command
1547 if(!unitTarget)
1548 return;
1550 uint32 spell_id = m_currentBasePoints[i]+1;
1551 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1552 if(!spell_proto)
1553 return;
1555 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1557 // decreased damage (/2) for non-stunned target.
1558 SpellModifier *mod = new SpellModifier;
1559 mod->op = SPELLMOD_DAMAGE;
1560 mod->value = -50;
1561 mod->type = SPELLMOD_PCT;
1562 mod->spellId = m_spellInfo->Id;
1563 mod->mask = 0x0000020000000000LL;
1564 mod->mask2= 0LL;
1566 ((Player*)m_caster)->AddSpellMod(mod, true);
1567 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1568 // mod deleted
1569 ((Player*)m_caster)->AddSpellMod(mod, false);
1571 else
1572 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1574 return;
1578 switch(m_spellInfo->Id)
1580 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1581 case 20187:
1583 if (!unitTarget)
1584 return;
1585 m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
1586 return;
1588 case 31789: // Righteous Defense (step 1)
1590 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1592 // non-standard cast requirement check
1593 if (!unitTarget || unitTarget->getAttackers().empty())
1595 // clear cooldown at fail
1596 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1598 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1600 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1601 data << uint32(m_spellInfo->Id);
1602 data << uint64(m_caster->GetGUID());
1603 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1606 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1607 return;
1610 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1611 // Clear targets for eff 1
1612 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1613 ihit->effectMask &= ~(1<<1);
1615 // not empty (checked)
1616 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1618 // chance to be selected from list
1619 float chance = 100.0f/attackers.size();
1620 uint32 count=0;
1621 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1623 if(!roll_chance_f(chance))
1624 continue;
1625 ++count;
1626 AddUnitTarget((*aItr), 1);
1629 // now let next effect cast spell at each target.
1630 return;
1632 case 37877: // Blessing of Faith
1634 if(!unitTarget)
1635 return;
1637 uint32 spell_id = 0;
1638 switch(unitTarget->getClass())
1640 case CLASS_DRUID: spell_id = 37878; break;
1641 case CLASS_PALADIN: spell_id = 37879; break;
1642 case CLASS_PRIEST: spell_id = 37880; break;
1643 case CLASS_SHAMAN: spell_id = 37881; break;
1644 default: return; // ignore for not healing classes
1647 m_caster->CastSpell(m_caster,spell_id,true);
1648 return;
1651 break;
1652 case SPELLFAMILY_SHAMAN:
1653 //Shaman Rockbiter Weapon
1654 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1656 // TODO: use expect spell for enchant (if exist talent)
1657 // In 3.0.3 no mods present for rockbiter
1658 uint32 spell_id = 0;
1659 switch(m_spellInfo->Id)
1661 case 8017: spell_id = 36494; break; // Rank 1
1662 case 8018: spell_id = 36750; break; // Rank 2
1663 case 8019: spell_id = 36755; break; // Rank 3
1664 case 10399: spell_id = 36759; break; // Rank 4
1665 default:
1666 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1667 return;
1670 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1672 if(!spellInfo)
1674 sLog.outError("WORLD: unknown spell id %i", spell_id);
1675 return;
1678 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1679 return;
1681 for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
1683 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(j)))
1685 if(item->IsFitToSpellRequirements(m_spellInfo))
1687 Spell *spell = new Spell(m_caster, spellInfo, true);
1689 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1690 // at calculation applied affect from Elemental Weapons talent
1691 // real enchantment damage-1
1692 spell->m_currentBasePoints[1] = damage-1;
1694 SpellCastTargets targets;
1695 targets.setItemTarget( item );
1696 spell->prepare(&targets);
1700 return;
1702 // Healing Stream Totem
1703 if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
1705 m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1706 return;
1708 // Mana Spring Totem
1709 if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
1711 if(unitTarget->getPowerType()!=POWER_MANA)
1712 return;
1713 m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID);
1714 return;
1716 if(m_spellInfo->Id == 39610) // Mana Tide Totem effect
1718 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1719 return;
1720 // Glyph of Mana Tide
1721 Unit *owner = m_caster->GetOwner();
1722 if (owner)
1723 if (Aura *dummy = owner->GetDummyAura(55441))
1724 damage+=dummy->GetModifier()->m_amount;
1725 // Regenerate 6% of Total Mana Every 3 secs
1726 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1727 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1728 return;
1730 // Lava Lash
1731 if (m_spellInfo->SpellFamilyFlags2 & 0x00000004)
1733 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1734 return;
1735 Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
1736 if (item)
1738 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1739 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1740 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1742 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
1743 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000200000LL &&
1744 (*itr)->GetCastItemGUID() == item->GetGUID())
1746 m_damage += m_damage * damage / 100;
1747 return;
1751 return;
1753 break;
1754 case SPELLFAMILY_DEATHKNIGHT:
1755 // Death Coil
1756 if(m_spellInfo->SpellFamilyFlags & 0x002000LL)
1758 if(m_caster->IsFriendlyTo(unitTarget))
1760 if(unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
1761 return;
1763 int32 bp = damage * 1.5f;
1764 m_caster->CastCustomSpell(unitTarget,47633,&bp,NULL,NULL,true);
1766 else
1768 int32 bp = damage;
1769 m_caster->CastCustomSpell(unitTarget,47632,&bp,NULL,NULL,true);
1771 return;
1773 break;
1776 // pet auras
1777 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1779 m_caster->AddPetAura(petSpell);
1780 return;
1783 // Script based implementation. Must be used only for not good for implementation in core spell effects
1784 // So called only for not proccessed cases
1785 if(gameObjTarget)
1786 Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
1787 else if(unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
1788 Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
1789 else if(itemTarget)
1790 Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
1793 void Spell::EffectTriggerSpellWithValue(uint32 i)
1795 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1797 // normal case
1798 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1800 if(!spellInfo)
1802 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1803 return;
1806 int32 bp = damage;
1807 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1810 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1812 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1813 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1815 if(!spellInfo)
1817 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1818 return;
1821 finish();
1822 Spell *spell = new Spell(m_caster, spellInfo, true);
1824 SpellCastTargets targets;
1825 targets.setUnitTarget( unitTarget);
1826 spell->prepare(&targets);
1828 m_caster->SetCurrentCastedSpell(spell);
1829 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1833 void Spell::EffectForceCast(uint32 i)
1835 if( !unitTarget )
1836 return;
1838 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1840 // normal case
1841 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1843 if(!spellInfo)
1845 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1846 return;
1849 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1852 void Spell::EffectTriggerSpell(uint32 i)
1854 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1856 // special cases
1857 switch(triggered_spell_id)
1859 // Vanish
1860 case 18461:
1862 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1863 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1864 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1866 // if this spell is given to NPC it must handle rest by it's own AI
1867 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1868 return;
1870 // get highest rank of the Stealth spell
1871 uint32 spellId = 0;
1872 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1873 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1875 // only highest rank is shown in spell book, so simply check if shown in spell book
1876 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1877 continue;
1879 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1880 if (!spellInfo)
1881 continue;
1883 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1885 spellId = spellInfo->Id;
1886 break;
1890 // no Stealth spell found
1891 if (!spellId)
1892 return;
1894 // reset cooldown on it if needed
1895 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1896 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1898 m_caster->CastSpell(m_caster, spellId, true);
1899 return;
1901 // just skip
1902 case 23770: // Sayge's Dark Fortune of *
1903 // not exist, common cooldown can be implemented in scripts if need.
1904 return;
1905 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1906 case 29284:
1908 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1909 if (!spell)
1910 return;
1912 for (int j=0; j < spell->StackAmount; ++j)
1913 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1914 return;
1916 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1917 case 29286:
1919 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1920 if (!spell)
1921 return;
1923 for (int j=0; j < spell->StackAmount; ++j)
1924 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1925 return;
1927 // Righteous Defense
1928 case 31980:
1930 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1931 return;
1933 // Cloak of Shadows
1934 case 35729 :
1936 Unit::AuraMap& Auras = m_caster->GetAuras();
1937 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1939 // remove all harmful spells on you...
1940 if( // ignore positive and passive auras
1941 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1942 // ignore physical auras
1943 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 )
1945 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1946 iter = Auras.begin();
1949 return;
1951 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1952 case 41967:
1954 if (Unit *pet = m_caster->GetPet())
1955 pet->CastSpell(pet, 28305, true);
1956 return;
1960 // normal case
1961 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1963 if(!spellInfo)
1965 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1966 return;
1969 // some triggered spells require specific equipment
1970 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1972 // main hand weapon required
1973 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1975 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1977 // skip spell if no weapon in slot or broken
1978 if(!item || item->IsBroken() )
1979 return;
1981 // skip spell if weapon not fit to triggered spell
1982 if(!item->IsFitToSpellRequirements(spellInfo))
1983 return;
1986 // offhand hand weapon required
1987 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1989 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1991 // skip spell if no weapon in slot or broken
1992 if(!item || item->IsBroken() )
1993 return;
1995 // skip spell if weapon not fit to triggered spell
1996 if(!item->IsFitToSpellRequirements(spellInfo))
1997 return;
2001 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
2002 bool instant = false;
2003 for(uint32 j = i+1; j < 3; ++j)
2005 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
2007 instant = true;
2008 break;
2012 if(instant)
2014 if (unitTarget)
2015 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
2017 else
2018 m_TriggerSpells.push_back(spellInfo);
2021 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
2023 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
2025 // normal case
2026 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
2028 if(!spellInfo)
2030 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2031 m_spellInfo->Id,effect_idx,triggered_spell_id);
2032 return;
2035 if (m_CastItem)
2036 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
2038 m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
2041 void Spell::EffectJump(uint32 i)
2043 if(m_caster->isInFlight())
2044 return;
2046 // Init dest coordinates
2047 float x,y,z,o;
2048 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2050 x = m_targets.m_destX;
2051 y = m_targets.m_destY;
2052 z = m_targets.m_destZ;
2054 if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
2056 // explicit cast data from client or server-side cast
2057 // some spell at client send caster
2058 Unit* pTarget = NULL;
2059 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
2060 pTarget = m_targets.getUnitTarget();
2061 else if(unitTarget->getVictim())
2062 pTarget = m_caster->getVictim();
2063 else if(m_caster->GetTypeId() == TYPEID_PLAYER)
2064 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
2066 o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
2068 else
2069 o = m_caster->GetOrientation();
2071 else if(unitTarget)
2073 unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2074 o = m_caster->GetOrientation();
2076 else if(gameObjTarget)
2078 gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
2079 o = m_caster->GetOrientation();
2081 else
2083 sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
2084 return;
2087 m_caster->NearTeleportTo(x,y,z,o,true);
2090 void Spell::EffectTeleportUnits(uint32 i)
2092 if(!unitTarget || unitTarget->isInFlight())
2093 return;
2095 switch (m_spellInfo->EffectImplicitTargetB[i])
2097 case TARGET_INNKEEPER_COORDINATES:
2099 // Only players can teleport to innkeeper
2100 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2101 return;
2103 ((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);
2104 return;
2106 case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2107 case TARGET_TABLE_X_Y_Z_COORDINATES:
2109 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
2110 if(!st)
2112 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
2113 return;
2116 if(st->target_mapId==unitTarget->GetMapId())
2117 unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
2118 else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
2119 ((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);
2120 break;
2122 case TARGET_BEHIND_VICTIM:
2124 Unit *pTarget = NULL;
2126 // explicit cast data from client or server-side cast
2127 // some spell at client send caster
2128 if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
2129 pTarget = m_targets.getUnitTarget();
2130 else if(unitTarget->getVictim())
2131 pTarget = unitTarget->getVictim();
2132 else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2133 pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
2135 // Init dest coordinates
2136 float x = m_targets.m_destX;
2137 float y = m_targets.m_destY;
2138 float z = m_targets.m_destZ;
2139 float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
2140 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2141 return;
2143 default:
2145 // If not exist data for dest location - return
2146 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2148 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2149 return;
2151 // Init dest coordinates
2152 uint32 mapid = m_caster->GetMapId();
2153 float x = m_targets.m_destX;
2154 float y = m_targets.m_destY;
2155 float z = m_targets.m_destZ;
2156 float orientation = unitTarget->GetOrientation();
2157 // Teleport
2158 unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
2159 return;
2163 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2164 switch ( m_spellInfo->Id )
2166 // Dimensional Ripper - Everlook
2167 case 23442:
2169 int32 r = irand(0, 119);
2170 if ( r >= 70 ) // 7/12 success
2172 if ( r < 100 ) // 4/12 evil twin
2173 m_caster->CastSpell(m_caster,23445,true);
2174 else // 1/12 fire
2175 m_caster->CastSpell(m_caster,23449,true);
2177 return;
2179 // Ultrasafe Transporter: Toshley's Station
2180 case 36941:
2182 if ( roll_chance_i(50) ) // 50% success
2184 int32 rand_eff = urand(1,7);
2185 switch ( rand_eff )
2187 case 1:
2188 // soul split - evil
2189 m_caster->CastSpell(m_caster,36900,true);
2190 break;
2191 case 2:
2192 // soul split - good
2193 m_caster->CastSpell(m_caster,36901,true);
2194 break;
2195 case 3:
2196 // Increase the size
2197 m_caster->CastSpell(m_caster,36895,true);
2198 break;
2199 case 4:
2200 // Decrease the size
2201 m_caster->CastSpell(m_caster,36893,true);
2202 break;
2203 case 5:
2204 // Transform
2206 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2207 m_caster->CastSpell(m_caster,36897,true);
2208 else
2209 m_caster->CastSpell(m_caster,36899,true);
2210 break;
2212 case 6:
2213 // chicken
2214 m_caster->CastSpell(m_caster,36940,true);
2215 break;
2216 case 7:
2217 // evil twin
2218 m_caster->CastSpell(m_caster,23445,true);
2219 break;
2222 return;
2224 // Dimensional Ripper - Area 52
2225 case 36890:
2227 if ( roll_chance_i(50) ) // 50% success
2229 int32 rand_eff = urand(1,4);
2230 switch ( rand_eff )
2232 case 1:
2233 // soul split - evil
2234 m_caster->CastSpell(m_caster,36900,true);
2235 break;
2236 case 2:
2237 // soul split - good
2238 m_caster->CastSpell(m_caster,36901,true);
2239 break;
2240 case 3:
2241 // Increase the size
2242 m_caster->CastSpell(m_caster,36895,true);
2243 break;
2244 case 4:
2245 // Transform
2247 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2248 m_caster->CastSpell(m_caster,36897,true);
2249 else
2250 m_caster->CastSpell(m_caster,36899,true);
2251 break;
2255 return;
2260 void Spell::EffectApplyAura(uint32 i)
2262 if(!unitTarget)
2263 return;
2265 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2266 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2267 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2268 return;
2270 Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
2271 if(!caster)
2272 return;
2274 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2276 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2278 // Now Reduce spell duration using data received at spell hit
2279 int32 duration = Aur->GetAuraMaxDuration();
2280 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2281 Aur->setDiminishGroup(m_diminishGroup);
2283 // if Aura removed and deleted, do not continue.
2284 if(duration== 0 && !(Aur->IsPermanent()))
2286 delete Aur;
2287 return;
2290 if(duration != Aur->GetAuraMaxDuration())
2292 Aur->SetAuraMaxDuration(duration);
2293 Aur->SetAuraDuration(duration);
2296 bool added = unitTarget->AddAura(Aur);
2298 // Aura not added and deleted in AddAura call;
2299 if (!added)
2300 return;
2302 // found crash at character loading, broken pointer to Aur...
2303 // Aur was deleted in AddAura()...
2304 if(!Aur)
2305 return;
2307 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2308 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2309 m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
2312 void Spell::EffectUnlearnSpecialization( uint32 i )
2314 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2315 return;
2317 Player *_player = (Player*)unitTarget;
2318 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2320 _player->removeSpell(spellToUnlearn);
2322 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2325 void Spell::EffectPowerDrain(uint32 i)
2327 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2328 return;
2330 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2332 if(!unitTarget)
2333 return;
2334 if(!unitTarget->isAlive())
2335 return;
2336 if(unitTarget->getPowerType() != drain_power)
2337 return;
2338 if(damage < 0)
2339 return;
2341 uint32 curPower = unitTarget->GetPower(drain_power);
2343 //add spell damage bonus
2344 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2346 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2347 uint32 power = damage;
2348 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2349 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2351 int32 new_damage;
2352 if(curPower < power)
2353 new_damage = curPower;
2354 else
2355 new_damage = power;
2357 unitTarget->ModifyPower(drain_power,-new_damage);
2359 // Don`t restore from self drain
2360 if(drain_power == POWER_MANA && m_caster != unitTarget)
2362 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2363 if(manaMultiplier==0)
2364 manaMultiplier = 1;
2366 if(Player *modOwner = m_caster->GetSpellModOwner())
2367 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2369 int32 gain = int32(new_damage*manaMultiplier);
2371 m_caster->ModifyPower(POWER_MANA,gain);
2372 //send log
2373 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2377 void Spell::EffectSendEvent(uint32 EffectIndex)
2380 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2382 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2383 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2386 void Spell::EffectPowerBurn(uint32 i)
2388 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2389 return;
2391 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2393 if(!unitTarget)
2394 return;
2395 if(!unitTarget->isAlive())
2396 return;
2397 if(unitTarget->getPowerType()!=powertype)
2398 return;
2399 if(damage < 0)
2400 return;
2402 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2403 if(m_spellInfo->ManaCostPercentage)
2405 uint32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100;
2406 damage = unitTarget->GetMaxPower(powertype) * damage / 100;
2407 if(damage > maxdamage) damage = maxdamage;
2410 int32 curPower = int32(unitTarget->GetPower(powertype));
2412 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2413 uint32 power = damage;
2414 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2415 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2417 int32 new_damage = (curPower < power) ? curPower : power;
2419 unitTarget->ModifyPower(powertype,-new_damage);
2420 float multiplier = m_spellInfo->EffectMultipleValue[i];
2422 if(Player *modOwner = m_caster->GetSpellModOwner())
2423 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2425 new_damage = int32(new_damage*multiplier);
2426 m_damage+=new_damage;
2429 void Spell::EffectHeal( uint32 /*i*/ )
2431 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2433 // Try to get original caster
2434 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2436 // Skip if m_originalCaster not available
2437 if (!caster)
2438 return;
2440 int32 addhealth = damage;
2442 // Vessel of the Naaru (Vial of the Sunwell trinket)
2443 if (m_spellInfo->Id == 45064)
2445 // Amount of heal - depends from stacked Holy Energy
2446 int damageAmount = 0;
2447 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2448 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2449 if((*i)->GetId() == 45062)
2450 damageAmount+=(*i)->GetModifier()->m_amount;
2451 if (damageAmount)
2452 m_caster->RemoveAurasDueToSpell(45062);
2454 addhealth += damageAmount;
2456 // Swiftmend - consumes Regrowth or Rejuvenation
2457 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2459 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2460 // find most short by duration
2461 Aura *targetAura = NULL;
2462 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2464 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2465 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2467 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2468 targetAura = *i;
2472 if(!targetAura)
2474 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2475 return;
2477 int idx = 0;
2478 while(idx < 3)
2480 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2481 break;
2482 idx++;
2485 int32 tickheal = caster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT);
2486 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2487 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2489 addhealth += tickheal * tickcount;
2491 else
2492 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
2494 m_healing+=addhealth;
2498 void Spell::EffectHealPct( uint32 /*i*/ )
2500 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2502 // Try to get original caster
2503 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2505 // Skip if m_originalCaster not available
2506 if (!caster)
2507 return;
2509 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2510 if(Player* modOwner = m_caster->GetSpellModOwner())
2511 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
2513 int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2514 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2518 void Spell::EffectHealMechanical( uint32 /*i*/ )
2520 // Mechanic creature type should be correctly checked by targetCreatureType field
2521 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2523 // Try to get original caster
2524 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2526 // Skip if m_originalCaster not available
2527 if (!caster)
2528 return;
2530 uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL);
2531 caster->DealHeal(unitTarget, addhealth, m_spellInfo);
2535 void Spell::EffectHealthLeech(uint32 i)
2537 if(!unitTarget)
2538 return;
2539 if(!unitTarget->isAlive())
2540 return;
2542 if(damage < 0)
2543 return;
2545 sLog.outDebug("HealthLeech :%i", damage);
2547 float multiplier = m_spellInfo->EffectMultipleValue[i];
2549 if(Player *modOwner = m_caster->GetSpellModOwner())
2550 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2552 int32 new_damage = int32(damage*multiplier);
2553 uint32 curHealth = unitTarget->GetHealth();
2554 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2555 if(curHealth < new_damage)
2556 new_damage = curHealth;
2558 if(m_caster->isAlive())
2560 new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
2561 m_caster->DealHeal(m_caster, uint32(new_damage), m_spellInfo);
2563 // m_healthLeech+=tmpvalue;
2564 // m_damage+=new_damage;
2567 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2569 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2570 return;
2572 Player* player = (Player*)unitTarget;
2574 uint32 newitemid = itemtype;
2575 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2576 if(!pProto)
2578 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2579 return;
2582 uint32 num_to_add;
2584 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2585 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2587 int32 basePoints = m_currentBasePoints[i];
2588 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2589 if (randomPoints)
2590 num_to_add = basePoints + irand(1, randomPoints);
2591 else
2592 num_to_add = basePoints + 1;
2594 else if (pProto->MaxCount == 1)
2595 num_to_add = 1;
2596 else if(player->getLevel() >= m_spellInfo->spellLevel)
2598 int32 basePoints = m_currentBasePoints[i];
2599 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2600 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2602 else
2603 num_to_add = 2;
2605 if (num_to_add < 1)
2606 num_to_add = 1;
2607 if (num_to_add > pProto->GetMaxStackSize())
2608 num_to_add = pProto->GetMaxStackSize();
2610 // init items_count to 1, since 1 item will be created regardless of specialization
2611 int items_count=1;
2612 // the chance to create additional items
2613 float additionalCreateChance=0.0f;
2614 // the maximum number of created additional items
2615 uint8 additionalMaxNum=0;
2616 // get the chance and maximum number for creating extra items
2617 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2619 // roll with this chance till we roll not to create or we create the max num
2620 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2621 ++items_count;
2624 // really will be created more items
2625 num_to_add *= items_count;
2627 // can the player store the new item?
2628 ItemPosCountVec dest;
2629 uint32 no_space = 0;
2630 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2631 if( msg != EQUIP_ERR_OK )
2633 // convert to possible store amount
2634 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2635 num_to_add -= no_space;
2636 else
2638 // if not created by another reason from full inventory or unique items amount limitation
2639 player->SendEquipError( msg, NULL, NULL );
2640 return;
2644 if(num_to_add)
2646 // create the new item and store it
2647 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2649 // was it successful? return error if not
2650 if(!pItem)
2652 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2653 return;
2656 // set the "Crafted by ..." property of the item
2657 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2658 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2660 // send info to the client
2661 if(pItem)
2662 player->SendNewItem(pItem, num_to_add, true, true);
2664 // we succeeded in creating at least one item, so a levelup is possible
2665 player->UpdateCraftSkill(m_spellInfo->Id);
2668 // for battleground marks send by mail if not add all expected
2669 if(no_space > 0 )
2671 BattleGroundTypeId bgType;
2672 switch(m_spellInfo->Id)
2674 case SPELL_AV_MARK_WINNER:
2675 case SPELL_AV_MARK_LOSER:
2676 bgType = BATTLEGROUND_AV;
2677 break;
2678 case SPELL_WS_MARK_WINNER:
2679 case SPELL_WS_MARK_LOSER:
2680 bgType = BATTLEGROUND_WS;
2681 break;
2682 case SPELL_AB_MARK_WINNER:
2683 case SPELL_AB_MARK_LOSER:
2684 bgType = BATTLEGROUND_AB;
2685 break;
2686 default:
2687 return;
2690 if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2691 bg->SendRewardMarkByMail(player,newitemid,no_space);
2695 void Spell::EffectCreateItem(uint32 i)
2697 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2700 void Spell::EffectCreateItem2(uint32 i)
2702 // special case: generate using spell_loot_template
2703 if(!m_spellInfo->EffectItemType[i])
2705 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
2706 return;
2708 // create some random items
2709 ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
2710 return;
2712 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2715 void Spell::EffectPersistentAA(uint32 i)
2717 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2719 if(Player* modOwner = m_caster->GetSpellModOwner())
2720 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2722 int32 duration = GetSpellDuration(m_spellInfo);
2723 DynamicObject* dynObj = new DynamicObject;
2724 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))
2726 delete dynObj;
2727 return;
2729 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2730 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2731 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2732 m_caster->AddDynObject(dynObj);
2733 dynObj->GetMap()->Add(dynObj);
2736 void Spell::EffectEnergize(uint32 i)
2738 if(!unitTarget)
2739 return;
2740 if(!unitTarget->isAlive())
2741 return;
2743 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2744 return;
2746 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2748 // Some level depends spells
2749 int multiplier = 0;
2750 int level_diff = 0;
2751 switch (m_spellInfo->Id)
2753 // Restore Energy
2754 case 9512:
2755 level_diff = m_caster->getLevel() - 40;
2756 multiplier = 2;
2757 break;
2758 // Blood Fury
2759 case 24571:
2760 level_diff = m_caster->getLevel() - 60;
2761 multiplier = 10;
2762 break;
2763 // Burst of Energy
2764 case 24532:
2765 level_diff = m_caster->getLevel() - 60;
2766 multiplier = 4;
2767 break;
2768 default:
2769 break;
2772 if (level_diff > 0)
2773 damage -= multiplier * level_diff;
2775 if(damage < 0)
2776 return;
2778 if(unitTarget->GetMaxPower(power) == 0)
2779 return;
2781 unitTarget->ModifyPower(power,damage);
2782 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2784 // Mad Alchemist's Potion
2785 if (m_spellInfo->Id == 45051)
2787 // find elixirs on target
2788 uint32 elixir_mask = 0;
2789 Unit::AuraMap& Auras = unitTarget->GetAuras();
2790 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2792 uint32 spell_id = itr->second->GetId();
2793 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2794 elixir_mask |= mask;
2797 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2798 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2800 // get all available elixirs by mask and spell level
2801 std::vector<uint32> elixirs;
2802 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2803 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2805 if (itr->second & elixir_mask)
2807 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2808 continue;
2810 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2811 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2812 continue;
2814 elixirs.push_back(itr->first);
2818 if (!elixirs.empty())
2820 // cast random elixir on target
2821 uint32 rand_spell = urand(0,elixirs.size()-1);
2822 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2827 void Spell::EffectEnergisePct(uint32 i)
2829 if(!unitTarget)
2830 return;
2831 if(!unitTarget->isAlive())
2832 return;
2834 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2835 return;
2837 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2839 uint32 maxPower = unitTarget->GetMaxPower(power);
2840 if(maxPower == 0)
2841 return;
2843 uint32 gain = damage * maxPower / 100;
2844 unitTarget->ModifyPower(power, gain);
2845 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
2848 void Spell::SendLoot(uint64 guid, LootType loottype)
2850 Player* player = (Player*)m_caster;
2851 if (!player)
2852 return;
2854 if (gameObjTarget)
2856 if (Script->GOHello(player, gameObjTarget))
2857 return;
2859 switch (gameObjTarget->GetGoType())
2861 case GAMEOBJECT_TYPE_DOOR:
2862 case GAMEOBJECT_TYPE_BUTTON:
2863 gameObjTarget->UseDoorOrButton();
2864 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2865 return;
2867 case GAMEOBJECT_TYPE_QUESTGIVER:
2868 // start or end quest
2869 player->PrepareQuestMenu(guid);
2870 player->SendPreparedQuest(guid);
2871 return;
2873 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2874 // triggering linked GO
2875 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2876 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2877 return;
2879 case GAMEOBJECT_TYPE_GOOBER:
2880 // goober_scripts can be triggered if the player don't have the quest
2881 if (gameObjTarget->GetGOInfo()->goober.eventId)
2883 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2884 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2887 // cast goober spell
2888 if (gameObjTarget->GetGOInfo()->goober.questId)
2889 ///Quest require to be active for GO using
2890 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2891 return;
2893 gameObjTarget->AddUniqueUse(player);
2894 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2896 //TODO? Objective counting called without spell check but with quest objective check
2897 // if send spell id then this line will duplicate to spell casting call (double counting)
2898 // So we or have this line and not required in quest_template have reqSpellIdN
2899 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2900 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2902 // triggering linked GO
2903 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2904 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2906 return;
2908 case GAMEOBJECT_TYPE_CHEST:
2909 // TODO: possible must be moved to loot release (in different from linked triggering)
2910 if (gameObjTarget->GetGOInfo()->chest.eventId)
2912 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2913 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2916 // triggering linked GO
2917 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2918 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2920 // Don't return, let loots been taken
2924 // Send loot
2925 player->SendLoot(guid, loottype);
2928 void Spell::EffectOpenLock(uint32 effIndex)
2930 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2932 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2933 return;
2936 Player* player = (Player*)m_caster;
2938 uint32 lockId = 0;
2939 uint64 guid = 0;
2941 // Get lockId
2942 if(gameObjTarget)
2944 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2945 // Arathi Basin banner opening !
2946 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2947 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2949 //CanUseBattleGroundObject() already called in CheckCast()
2950 // in battleground check
2951 if(BattleGround *bg = player->GetBattleGround())
2953 // check if it's correct bg
2954 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2955 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2956 return;
2959 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2961 //CanUseBattleGroundObject() already called in CheckCast()
2962 // in battleground check
2963 if(BattleGround *bg = player->GetBattleGround())
2965 if(bg->GetTypeID() == BATTLEGROUND_EY)
2966 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2967 return;
2970 lockId = gameObjTarget->GetLockId();
2971 guid = gameObjTarget->GetGUID();
2973 else if(itemTarget)
2975 lockId = itemTarget->GetProto()->LockID;
2976 guid = itemTarget->GetGUID();
2978 else
2980 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2981 return;
2984 SkillType skillId = SKILL_NONE;
2985 int32 reqSkillValue = 0;
2986 int32 skillValue;
2988 SpellCastResult res = CanOpenLock(effIndex,lockId,skillId,reqSkillValue,skillValue);
2989 if(res != SPELL_CAST_OK)
2991 SendCastResult(res);
2992 return;
2995 SendLoot(guid, LOOT_SKINNING);
2997 // not allow use skill grow at item base open
2998 if(!m_CastItem && skillId != SKILL_NONE)
3000 // update skill if really known
3001 if(uint32 pureSkillValue = player->GetPureSkillValue(skillId))
3003 if(gameObjTarget)
3005 // Allow one skill-up until respawned
3006 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3007 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue) )
3008 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3010 else if(itemTarget)
3012 // Do one skill-up
3013 player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
3019 void Spell::EffectSummonChangeItem(uint32 i)
3021 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3022 return;
3024 Player *player = (Player*)m_caster;
3026 // applied only to using item
3027 if(!m_CastItem)
3028 return;
3030 // ... only to item in own inventory/bank/equip_slot
3031 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3032 return;
3034 uint32 newitemid = m_spellInfo->EffectItemType[i];
3035 if(!newitemid)
3036 return;
3038 uint16 pos = m_CastItem->GetPos();
3040 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3041 if( !pNewItem )
3042 return;
3044 for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j)
3046 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
3047 pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
3050 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3052 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3053 player->DurabilityLoss(pNewItem, loosePercent);
3056 if( player->IsInventoryPos( pos ) )
3058 ItemPosCountVec dest;
3059 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3060 if( msg == EQUIP_ERR_OK )
3062 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3064 // prevent crash at access and unexpected charges counting with item update queue corrupt
3065 if(m_CastItem==m_targets.getItemTarget())
3066 m_targets.setItemTarget(NULL);
3068 m_CastItem = NULL;
3070 player->StoreItem( dest, pNewItem, true);
3071 return;
3074 else if( player->IsBankPos ( pos ) )
3076 ItemPosCountVec dest;
3077 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3078 if( msg == EQUIP_ERR_OK )
3080 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3082 // prevent crash at access and unexpected charges counting with item update queue corrupt
3083 if(m_CastItem==m_targets.getItemTarget())
3084 m_targets.setItemTarget(NULL);
3086 m_CastItem = NULL;
3088 player->BankItem( dest, pNewItem, true);
3089 return;
3092 else if( player->IsEquipmentPos ( pos ) )
3094 uint16 dest;
3095 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3096 if( msg == EQUIP_ERR_OK )
3098 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3100 // prevent crash at access and unexpected charges counting with item update queue corrupt
3101 if(m_CastItem==m_targets.getItemTarget())
3102 m_targets.setItemTarget(NULL);
3104 m_CastItem = NULL;
3106 player->EquipItem( dest, pNewItem, true);
3107 player->AutoUnequipOffhandIfNeed();
3108 return;
3112 // fail
3113 delete pNewItem;
3116 void Spell::EffectOpenSecretSafe(uint32 i)
3118 EffectOpenLock(i); //no difference for now
3121 void Spell::EffectProficiency(uint32 /*i*/)
3123 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3124 return;
3125 Player *p_target = (Player*)unitTarget;
3127 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3128 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3130 p_target->AddWeaponProficiency(subClassMask);
3131 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3133 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3135 p_target->AddArmorProficiency(subClassMask);
3136 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3140 void Spell::EffectApplyAreaAura(uint32 i)
3142 if(!unitTarget)
3143 return;
3144 if(!unitTarget->isAlive())
3145 return;
3147 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3148 unitTarget->AddAura(Aur);
3151 void Spell::EffectSummonType(uint32 i)
3153 switch(m_spellInfo->EffectMiscValueB[i])
3155 case SUMMON_TYPE_GUARDIAN:
3156 case SUMMON_TYPE_POSESSED:
3157 case SUMMON_TYPE_POSESSED2:
3158 case SUMMON_TYPE_FORCE_OF_NATURE:
3159 case SUMMON_TYPE_GUARDIAN2:
3160 EffectSummonGuardian(i);
3161 break;
3162 case SUMMON_TYPE_WILD:
3163 EffectSummonWild(i);
3164 break;
3165 case SUMMON_TYPE_DEMON:
3166 EffectSummonDemon(i);
3167 break;
3168 case SUMMON_TYPE_SUMMON:
3169 EffectSummon(i);
3170 break;
3171 case SUMMON_TYPE_CRITTER:
3172 case SUMMON_TYPE_CRITTER2:
3173 case SUMMON_TYPE_CRITTER3:
3174 EffectSummonCritter(i);
3175 break;
3176 case SUMMON_TYPE_TOTEM_SLOT1:
3177 case SUMMON_TYPE_TOTEM_SLOT2:
3178 case SUMMON_TYPE_TOTEM_SLOT3:
3179 case SUMMON_TYPE_TOTEM_SLOT4:
3180 case SUMMON_TYPE_TOTEM:
3181 EffectSummonTotem(i);
3182 break;
3183 case SUMMON_TYPE_UNKNOWN1:
3184 case SUMMON_TYPE_UNKNOWN2:
3185 case SUMMON_TYPE_UNKNOWN3:
3186 case SUMMON_TYPE_UNKNOWN4:
3187 case SUMMON_TYPE_UNKNOWN5:
3188 break;
3189 default:
3190 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3191 break;
3195 void Spell::EffectSummon(uint32 i)
3197 if(m_caster->GetPetGUID())
3198 return;
3200 if(!unitTarget)
3201 return;
3202 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3203 if(!pet_entry)
3204 return;
3205 uint32 level = m_caster->getLevel();
3206 Pet* spawnCreature = new Pet(SUMMON_PET);
3208 if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
3210 // set timer for unsummon
3211 int32 duration = GetSpellDuration(m_spellInfo);
3212 if(duration > 0)
3213 spawnCreature->SetDuration(duration);
3215 return;
3218 Map *map = m_caster->GetMap();
3219 uint32 pet_number = objmgr.GeneratePetNumber();
3220 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_caster->GetPhaseMask(),
3221 m_spellInfo->EffectMiscValue[i], pet_number))
3223 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3224 delete spawnCreature;
3225 return;
3228 // Summon in dest location
3229 float x,y,z;
3230 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3232 x = m_targets.m_destX;
3233 y = m_targets.m_destY;
3234 z = m_targets.m_destZ;
3236 else
3237 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3239 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3241 if(!spawnCreature->IsPositionValid())
3243 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3244 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3245 delete spawnCreature;
3246 return;
3249 // set timer for unsummon
3250 int32 duration = GetSpellDuration(m_spellInfo);
3251 if(duration > 0)
3252 spawnCreature->SetDuration(duration);
3254 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3255 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3256 spawnCreature->setPowerType(POWER_MANA);
3257 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3258 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3259 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3260 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3261 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3262 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3263 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3264 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3265 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3267 spawnCreature->InitStatsForLevel(level);
3269 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3271 spawnCreature->AIM_Initialize();
3272 spawnCreature->InitPetCreateSpells();
3273 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3274 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3276 std::string name = m_caster->GetName();
3277 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3278 spawnCreature->SetName( name );
3280 map->Add((Creature*)spawnCreature);
3282 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3284 m_caster->SetPet(spawnCreature);
3285 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3286 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3287 ((Player*)m_caster)->PetSpellInitialize();
3291 void Spell::EffectLearnSpell(uint32 i)
3293 if(!unitTarget)
3294 return;
3296 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3298 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3299 EffectLearnPetSpell(i);
3301 return;
3304 Player *player = (Player*)unitTarget;
3306 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3307 player->learnSpell(spellToLearn,false);
3309 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3312 void Spell::EffectDispel(uint32 i)
3314 if(!unitTarget)
3315 return;
3317 // Fill possible dispell list
3318 std::vector <Aura *> dispel_list;
3320 // Create dispel mask by dispel type
3321 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3322 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3323 Unit::AuraMap const& auras = unitTarget->GetAuras();
3324 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3326 Aura *aur = (*itr).second;
3327 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3329 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3331 bool positive = true;
3332 if (!aur->IsPositive())
3333 positive = false;
3334 else
3335 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3337 // do not remove positive auras if friendly target
3338 // negative auras if non-friendly target
3339 if(positive == unitTarget->IsFriendlyTo(m_caster))
3340 continue;
3342 // Add aura to dispel list
3343 dispel_list.push_back(aur);
3346 // Ok if exist some buffs for dispel try dispel it
3347 if (!dispel_list.empty())
3349 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3350 std::list < uint32 > fail_list; // spell_id
3351 int32 list_size = dispel_list.size();
3352 // Dispell N = damage buffs (or while exist buffs for dispel)
3353 for (int32 count=0; count < damage && list_size > 0; ++count)
3355 // Random select buff for dispel
3356 Aura *aur = dispel_list[urand(0, list_size-1)];
3358 SpellEntry const* spellInfo = aur->GetSpellProto();
3359 // Base dispel chance
3360 // TODO: possible chance depend from spell level??
3361 int32 miss_chance = 0;
3362 // Apply dispel mod from aura caster
3363 if (Unit *caster = aur->GetCaster())
3365 if ( Player* modOwner = caster->GetSpellModOwner() )
3366 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3368 // Try dispel
3369 if (roll_chance_i(miss_chance))
3370 fail_list.push_back(aur->GetId());
3371 else
3372 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3373 // Remove buff from list for prevent doubles
3374 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3376 Aura *dispeled = *j;
3377 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3379 j = dispel_list.erase(j);
3380 --list_size;
3382 else
3383 ++j;
3386 // Send success log and really remove auras
3387 if (!success_list.empty())
3389 int32 count = success_list.size();
3390 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3391 data.append(unitTarget->GetPackGUID()); // Victim GUID
3392 data.append(m_caster->GetPackGUID()); // Caster GUID
3393 data << uint32(m_spellInfo->Id); // Dispell spell id
3394 data << uint8(0); // not used
3395 data << uint32(count); // count
3396 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3398 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3399 data << uint32(spellInfo->Id); // Spell Id
3400 data << uint8(0); // 0 - dispeled !=0 cleansed
3401 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3403 m_caster->SendMessageToSet(&data, true);
3405 // On succes dispel
3406 // Devour Magic
3407 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
3409 uint32 heal_spell = 0;
3410 switch (m_spellInfo->Id)
3412 case 19505: heal_spell = 19658; break;
3413 case 19731: heal_spell = 19732; break;
3414 case 19734: heal_spell = 19733; break;
3415 case 19736: heal_spell = 19735; break;
3416 case 27276: heal_spell = 27278; break;
3417 case 27277: heal_spell = 27279; break;
3418 default:
3419 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3420 break;
3422 if (heal_spell)
3423 m_caster->CastSpell(m_caster, heal_spell, true);
3426 // Send fail log to client
3427 if (!fail_list.empty())
3429 // Failed to dispell
3430 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3431 data << uint64(m_caster->GetGUID()); // Caster GUID
3432 data << uint64(unitTarget->GetGUID()); // Victim GUID
3433 data << uint32(m_spellInfo->Id); // Dispell spell id
3434 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3435 data << uint32(*j); // Spell Id
3436 m_caster->SendMessageToSet(&data, true);
3441 void Spell::EffectDualWield(uint32 /*i*/)
3443 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
3444 ((Player*)unitTarget)->SetCanDualWield(true);
3447 void Spell::EffectPull(uint32 /*i*/)
3449 // TODO: create a proper pull towards distract spell center for distract
3450 sLog.outDebug("WORLD: Spell Effect DUMMY");
3453 void Spell::EffectDistract(uint32 /*i*/)
3455 // Check for possible target
3456 if (!unitTarget || unitTarget->isInCombat())
3457 return;
3459 // target must be OK to do this
3460 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3461 return;
3463 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3465 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3467 // For players just turn them
3468 WorldPacket data;
3469 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3470 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3471 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3473 else
3475 // Set creature Distracted, Stop it, And turn it
3476 unitTarget->SetOrientation(angle);
3477 unitTarget->StopMoving();
3478 unitTarget->GetMotionMaster()->MoveDistract(damage*IN_MILISECONDS);
3482 void Spell::EffectPickPocket(uint32 /*i*/)
3484 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3485 return;
3487 // victim must be creature and attackable
3488 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3489 return;
3491 // victim have to be alive and humanoid or undead
3492 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3494 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3496 if (chance > irand(0, 19))
3498 // Stealing successful
3499 //sLog.outDebug("Sending loot from pickpocket");
3500 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3502 else
3504 // Reveal action + get attack
3505 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3506 if (((Creature*)unitTarget)->AI())
3507 ((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
3512 void Spell::EffectAddFarsight(uint32 i)
3514 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3515 int32 duration = GetSpellDuration(m_spellInfo);
3516 DynamicObject* dynObj = new DynamicObject;
3517 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))
3519 delete dynObj;
3520 return;
3522 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3523 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3524 m_caster->AddDynObject(dynObj);
3525 dynObj->GetMap()->Add(dynObj);
3526 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3527 ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
3530 void Spell::EffectSummonWild(uint32 i)
3532 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3533 if(!creature_entry)
3534 return;
3536 uint32 level = m_caster->getLevel();
3538 // level of creature summoned using engineering item based at engineering skill level
3539 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3541 ItemPrototype const *proto = m_CastItem->GetProto();
3542 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3544 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3545 if(skill202)
3547 level = skill202/5;
3552 // select center of summon position
3553 float center_x = m_targets.m_destX;
3554 float center_y = m_targets.m_destY;
3555 float center_z = m_targets.m_destZ;
3557 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3559 int32 amount = damage > 0 ? damage : 1;
3561 for(int32 count = 0; count < amount; ++count)
3563 float px, py, pz;
3564 // If dest location if present
3565 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3567 // Summon 1 unit in dest location
3568 if (count == 0)
3570 px = m_targets.m_destX;
3571 py = m_targets.m_destY;
3572 pz = m_targets.m_destZ;
3574 // Summon in random point all other units if location present
3575 else
3576 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3578 // Summon if dest location not present near caster
3579 else
3580 m_caster->GetClosePoint(px,py,pz,3.0f);
3582 int32 duration = GetSpellDuration(m_spellInfo);
3584 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3586 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3590 void Spell::EffectSummonGuardian(uint32 i)
3592 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3593 if(!pet_entry)
3594 return;
3596 // Jewelery statue case (totem like)
3597 if(m_spellInfo->SpellIconID==2056)
3599 EffectSummonTotem(i);
3600 return;
3603 // set timer for unsummon
3604 int32 duration = GetSpellDuration(m_spellInfo);
3606 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3607 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3608 // so this code hack in fact
3609 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3610 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3611 return; // find old guardian, ignore summon
3613 // in another case summon new
3614 uint32 level = m_caster->getLevel();
3616 // level of pet summoned using engineering item based at engineering skill level
3617 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3619 ItemPrototype const *proto = m_CastItem->GetProto();
3620 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3622 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3623 if(skill202)
3625 level = skill202/5;
3630 // select center of summon position
3631 float center_x = m_targets.m_destX;
3632 float center_y = m_targets.m_destY;
3633 float center_z = m_targets.m_destZ;
3635 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3637 int32 amount = damage > 0 ? damage : 1;
3639 for(int32 count = 0; count < amount; ++count)
3641 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3643 Map *map = m_caster->GetMap();
3644 uint32 pet_number = objmgr.GeneratePetNumber();
3645 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(),
3646 m_spellInfo->EffectMiscValue[i], pet_number))
3648 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3649 delete spawnCreature;
3650 return;
3653 float px, py, pz;
3654 // If dest location if present
3655 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3657 // Summon 1 unit in dest location
3658 if (count == 0)
3660 px = m_targets.m_destX;
3661 py = m_targets.m_destY;
3662 pz = m_targets.m_destZ;
3664 // Summon in random point all other units if location present
3665 else
3666 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3668 // Summon if dest location not present near caster
3669 else
3670 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3672 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3674 if(!spawnCreature->IsPositionValid())
3676 sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3677 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3678 delete spawnCreature;
3679 return;
3682 if(duration > 0)
3683 spawnCreature->SetDuration(duration);
3685 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3686 spawnCreature->setPowerType(POWER_MANA);
3687 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3688 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3689 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3690 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3691 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3692 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3693 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3695 spawnCreature->InitStatsForLevel(level);
3696 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3698 spawnCreature->AIM_Initialize();
3700 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3701 ((Player*)m_caster)->AddGuardian(spawnCreature);
3703 map->Add((Creature*)spawnCreature);
3707 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3709 if(!unitTarget)
3710 return;
3712 if(unitTarget->isInFlight())
3713 return;
3715 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3717 float fx,fy,fz;
3718 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3720 unitTarget->NearTeleportTo(fx,fy,fz,-m_caster->GetOrientation(),unitTarget==m_caster);
3723 void Spell::EffectLearnSkill(uint32 i)
3725 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3726 return;
3728 if(damage < 0)
3729 return;
3731 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3732 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3733 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3736 void Spell::EffectAddHonor(uint32 /*i*/)
3738 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3739 return;
3741 // not scale value for item based reward (/10 value expected)
3742 if(m_CastItem)
3744 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage/10);
3745 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
3746 return;
3749 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
3750 if( damage <= 50)
3752 uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
3753 ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
3754 sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
3756 else
3758 //maybe we have correct honor_gain in damage already
3759 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3760 sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3764 void Spell::EffectTradeSkill(uint32 /*i*/)
3766 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3767 return;
3768 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3769 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3770 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3773 void Spell::EffectEnchantItemPerm(uint32 effect_idx)
3775 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3776 return;
3777 if (!itemTarget)
3778 return;
3780 Player* p_caster = (Player*)m_caster;
3782 // not grow at item use at item case
3783 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3785 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3786 if (!enchant_id)
3787 return;
3789 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3790 if(!pEnchant)
3791 return;
3793 // item can be in trade slot and have owner diff. from caster
3794 Player* item_owner = itemTarget->GetOwner();
3795 if(!item_owner)
3796 return;
3798 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3800 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3801 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3802 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3803 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3806 // remove old enchanting before applying new if equipped
3807 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3809 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3811 // add new enchanting if equipped
3812 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3815 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx)
3817 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3818 return;
3819 if (!itemTarget)
3820 return;
3822 Player* p_caster = (Player*)m_caster;
3824 uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx];
3825 if (!enchant_id)
3826 return;
3828 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3829 if(!pEnchant)
3830 return;
3832 // support only enchantings with add socket in this slot
3834 bool add_socket = false;
3835 for(int i = 0; i < 3; ++i)
3837 if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
3839 add_socket = true;
3840 break;
3843 if(!add_socket)
3845 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.",
3846 m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
3847 return;
3851 // item can be in trade slot and have owner diff. from caster
3852 Player* item_owner = itemTarget->GetOwner();
3853 if(!item_owner)
3854 return;
3856 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3858 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3859 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3860 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3861 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3864 // remove old enchanting before applying new if equipped
3865 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false);
3867 itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3869 // add new enchanting if equipped
3870 item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true);
3873 void Spell::EffectEnchantItemTmp(uint32 i)
3875 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3876 return;
3878 Player* p_caster = (Player*)m_caster;
3880 if(!itemTarget)
3881 return;
3883 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3885 // Shaman Rockbiter Weapon
3886 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3888 int32 enchnting_damage = m_currentBasePoints[1]+1;
3890 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3891 // with already applied percent bonus from Elemental Weapons talent
3892 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3893 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3894 switch(enchnting_damage)
3896 // Rank 1
3897 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3898 // Rank 2
3899 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3900 case 5: enchant_id = 3025; break; // 20%
3901 // Rank 3
3902 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3903 case 7: enchant_id = 3027; break; // 20%
3904 // Rank 4
3905 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3906 case 10: enchant_id = 503; break; // 14%
3907 case 11: enchant_id = 3031; break; // 20%
3908 // Rank 5
3909 case 15: enchant_id = 3035; break; // 0%
3910 case 16: enchant_id = 1663; break; // 7%
3911 case 17: enchant_id = 3033; break; // 14%
3912 case 18: enchant_id = 3034; break; // 20%
3913 // Rank 6
3914 case 28: enchant_id = 3038; break; // 0%
3915 case 29: enchant_id = 683; break; // 7%
3916 case 31: enchant_id = 3036; break; // 14%
3917 case 33: enchant_id = 3037; break; // 20%
3918 // Rank 7
3919 case 40: enchant_id = 3041; break; // 0%
3920 case 42: enchant_id = 1664; break; // 7%
3921 case 45: enchant_id = 3039; break; // 14%
3922 case 48: enchant_id = 3040; break; // 20%
3923 // Rank 8
3924 case 49: enchant_id = 3044; break; // 0%
3925 case 52: enchant_id = 2632; break; // 7%
3926 case 55: enchant_id = 3042; break; // 14%
3927 case 58: enchant_id = 3043; break; // 20%
3928 // Rank 9
3929 case 62: enchant_id = 2633; break; // 0%
3930 case 66: enchant_id = 3018; break; // 7%
3931 case 70: enchant_id = 3019; break; // 14%
3932 case 74: enchant_id = 3020; break; // 20%
3933 default:
3934 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3935 return;
3939 if (!enchant_id)
3941 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3942 return;
3945 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3946 if(!pEnchant)
3948 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3949 return;
3952 // select enchantment duration
3953 uint32 duration;
3955 // rogue family enchantments exception by duration
3956 if(m_spellInfo->Id==38615)
3957 duration = 1800; // 30 mins
3958 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3959 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3960 duration = 3600; // 1 hour
3961 // shaman family enchantments
3962 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3963 duration = 1800; // 30 mins
3964 // other cases with this SpellVisual already selected
3965 else if(m_spellInfo->SpellVisual[0]==215)
3966 duration = 1800; // 30 mins
3967 // some fishing pole bonuses
3968 else if(m_spellInfo->SpellVisual[0]==563)
3969 duration = 600; // 10 mins
3970 // shaman rockbiter enchantments
3971 else if(m_spellInfo->SpellVisual[0]==0)
3972 duration = 1800; // 30 mins
3973 else if(m_spellInfo->Id==29702)
3974 duration = 300; // 5 mins
3975 else if(m_spellInfo->Id==37360)
3976 duration = 300; // 5 mins
3977 // default case
3978 else
3979 duration = 3600; // 1 hour
3981 // item can be in trade slot and have owner diff. from caster
3982 Player* item_owner = itemTarget->GetOwner();
3983 if(!item_owner)
3984 return;
3986 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3988 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3989 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3990 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3991 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3994 // remove old enchanting before applying new if equipped
3995 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3997 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3999 // add new enchanting if equipped
4000 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
4003 void Spell::EffectTameCreature(uint32 /*i*/)
4005 if(m_caster->GetPetGUID())
4006 return;
4008 if(!unitTarget)
4009 return;
4011 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4012 return;
4014 Creature* creatureTarget = (Creature*)unitTarget;
4016 if(creatureTarget->isPet())
4017 return;
4019 if(m_caster->getClass() != CLASS_HUNTER)
4020 return;
4022 // cast finish successfully
4023 //SendChannelUpdate(0);
4024 finish();
4026 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
4028 // kill original creature
4029 creatureTarget->setDeathState(JUST_DIED);
4030 creatureTarget->RemoveCorpse();
4031 creatureTarget->SetHealth(0); // just for nice GM-mode view
4033 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
4035 // prepare visual effect for levelup
4036 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4038 // add to world
4039 pet->GetMap()->Add((Creature*)pet);
4041 // visual effect for levelup
4042 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4044 // caster have pet now
4045 m_caster->SetPet(pet);
4047 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4049 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4050 ((Player*)m_caster)->PetSpellInitialize();
4054 void Spell::EffectSummonPet(uint32 i)
4056 uint32 petentry = m_spellInfo->EffectMiscValue[i];
4058 Pet *OldSummon = m_caster->GetPet();
4060 // if pet requested type already exist
4061 if( OldSummon )
4063 if(petentry == 0 || OldSummon->GetEntry() == petentry)
4065 // pet in corpse state can't be summoned
4066 if( OldSummon->isDead() )
4067 return;
4069 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
4070 OldSummon->SetMapId(m_caster->GetMapId());
4072 float px, py, pz;
4073 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4075 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4076 m_caster->GetMap()->Add((Creature*)OldSummon);
4078 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4080 ((Player*)m_caster)->PetSpellInitialize();
4082 return;
4085 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4086 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4087 else
4088 return;
4091 Pet* NewSummon = new Pet;
4093 // petentry==0 for hunter "call pet" (current pet summoned if any)
4094 if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry))
4096 if(NewSummon->getPetType()==SUMMON_PET)
4098 // Remove Demonic Sacrifice auras (known pet)
4099 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4100 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4102 if((*itr)->GetModifier()->m_miscvalue==2228)
4104 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4105 itr = auraClassScripts.begin();
4107 else
4108 ++itr;
4112 return;
4115 // not error in case fail hunter call pet
4116 if(!petentry)
4118 delete NewSummon;
4119 return;
4122 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4124 if(!cInfo)
4126 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4127 delete NewSummon;
4128 return;
4131 Map *map = m_caster->GetMap();
4132 uint32 pet_number = objmgr.GeneratePetNumber();
4133 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
4134 petentry, pet_number))
4136 delete NewSummon;
4137 return;
4140 float px, py, pz;
4141 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4143 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4145 if(!NewSummon->IsPositionValid())
4147 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4148 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4149 delete NewSummon;
4150 return;
4153 uint32 petlevel = m_caster->getLevel();
4154 NewSummon->setPetType(SUMMON_PET);
4156 uint32 faction = m_caster->getFaction();
4157 if(m_caster->GetTypeId() == TYPEID_UNIT)
4159 if ( ((Creature*)m_caster)->isTotem() )
4160 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4161 else
4162 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4165 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4166 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4167 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4168 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4169 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4170 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4171 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4172 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4173 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4174 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4176 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4177 // this enables pet details window (Shift+P)
4179 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4180 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4181 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4183 NewSummon->InitStatsForLevel(petlevel);
4184 NewSummon->InitPetCreateSpells();
4185 NewSummon->InitTalentForLevel();
4187 if(NewSummon->getPetType()==SUMMON_PET)
4189 // Remove Demonic Sacrifice auras (new pet)
4190 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4191 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4193 if((*itr)->GetModifier()->m_miscvalue==2228)
4195 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4196 itr = auraClassScripts.begin();
4198 else
4199 ++itr;
4202 // generate new name for summon pet
4203 std::string new_name=objmgr.GeneratePetName(petentry);
4204 if(!new_name.empty())
4205 NewSummon->SetName(new_name);
4207 else if(NewSummon->getPetType()==HUNTER_PET)
4208 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4210 NewSummon->AIM_Initialize();
4211 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4212 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4214 map->Add((Creature*)NewSummon);
4216 m_caster->SetPet(NewSummon);
4217 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4219 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4221 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4222 ((Player*)m_caster)->PetSpellInitialize();
4226 void Spell::EffectLearnPetSpell(uint32 i)
4228 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4229 return;
4231 Player *_player = (Player*)m_caster;
4233 Pet *pet = _player->GetPet();
4234 if(!pet)
4235 return;
4236 if(!pet->isAlive())
4237 return;
4239 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4240 if(!learn_spellproto)
4241 return;
4243 pet->learnSpell(learn_spellproto->Id);
4245 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4246 _player->PetSpellInitialize();
4249 void Spell::EffectTaunt(uint32 /*i*/)
4251 if (!unitTarget)
4252 return;
4254 // this effect use before aura Taunt apply for prevent taunt already attacking target
4255 // for spell as marked "non effective at already attacking target"
4256 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4258 if (unitTarget->getVictim()==m_caster)
4260 SendCastResult(SPELL_FAILED_DONT_REPORT);
4261 return;
4265 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4266 if (unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4267 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4270 void Spell::EffectWeaponDmg(uint32 i)
4272 if(!unitTarget)
4273 return;
4274 if(!unitTarget->isAlive())
4275 return;
4277 // multiple weapon dmg effect workaround
4278 // execute only the last weapon damage
4279 // and handle all effects at once
4280 for (int j = 0; j < 3; j++)
4282 switch(m_spellInfo->Effect[j])
4284 case SPELL_EFFECT_WEAPON_DAMAGE:
4285 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4286 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4287 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4288 if (j < i) // we must calculate only at last weapon effect
4289 return;
4290 break;
4294 // some spell specific modifiers
4295 bool spellBonusNeedWeaponDamagePercentMod = false; // if set applied weapon damage percent mode to spell bonus
4297 float weaponDamagePercentMod = 1.0f; // applied to weapon damage and to fixed effect damage bonus
4298 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4299 bool normalized = false;
4301 int32 spell_bonus = 0; // bonus specific for spell
4302 switch(m_spellInfo->SpellFamilyName)
4304 case SPELLFAMILY_WARRIOR:
4306 // Whirlwind, single only spell with 2 weapon white damage apply if have
4307 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4309 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4310 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4312 // Devastate bonus and sunder armor refresh
4313 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4315 uint32 stack = 0;
4316 // Need refresh all Sunder Armor auras from this caster
4317 Unit::AuraMap& suAuras = unitTarget->GetAuras();
4318 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
4320 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
4321 if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
4322 spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
4323 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
4325 (*itr).second->RefreshAura();
4326 stack = (*itr).second->GetStackAmount();
4329 if (stack)
4330 spell_bonus += stack * CalculateDamage(2, unitTarget);
4332 break;
4334 case SPELLFAMILY_ROGUE:
4336 // Mutilate (for each hand)
4337 if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4339 bool found = false;
4340 // fast check
4341 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4342 found = true;
4343 // full aura scan
4344 else
4346 Unit::AuraMap const& auras = unitTarget->GetAuras();
4347 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4349 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4351 found = true;
4352 break;
4357 if(found)
4358 totalDamagePercentMod *= 1.2f; // 120% if poisoned
4360 break;
4362 case SPELLFAMILY_PALADIN:
4364 // Seal of Command - receive benefit from Spell Damage and Healing
4365 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4367 spellBonusNeedWeaponDamagePercentMod = true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4368 spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4369 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4371 break;
4373 case SPELLFAMILY_SHAMAN:
4375 // Skyshatter Harness item set bonus
4376 // Stormstrike
4377 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4379 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4380 for(Unit::AuraList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr)
4382 // Stormstrike AP Buff
4383 if ( (*citr)->GetModifier()->m_miscvalue == 5634 )
4385 m_caster->CastSpell(m_caster,38430,true,NULL,*citr);
4386 break;
4393 int32 fixed_bonus = 0;
4394 for (int j = 0; j < 3; j++)
4396 switch(m_spellInfo->Effect[j])
4398 case SPELL_EFFECT_WEAPON_DAMAGE:
4399 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4400 fixed_bonus += CalculateDamage(j,unitTarget);
4401 break;
4402 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4403 fixed_bonus += CalculateDamage(j,unitTarget);
4404 normalized = true;
4405 break;
4406 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4407 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4409 // applied only to prev.effects fixed damage
4410 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4411 break;
4412 default:
4413 break; // not weapon damage effect, just skip
4417 // apply weaponDamagePercentMod to spell bonus also
4418 if(spellBonusNeedWeaponDamagePercentMod)
4419 spell_bonus = int32(spell_bonus*weaponDamagePercentMod);
4421 // non-weapon damage
4422 int32 bonus = spell_bonus + fixed_bonus;
4424 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4425 if(bonus)
4427 UnitMods unitMod;
4428 switch(m_attackType)
4430 default:
4431 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4432 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4433 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4436 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4437 bonus = int32(bonus*weapon_total_pct);
4440 // + weapon damage with applied weapon% dmg to base weapon damage in call
4441 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4443 // total damage
4444 bonus = int32(bonus*totalDamagePercentMod);
4446 // prevent negative damage
4447 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4449 // Add melee damage bonuses (also check for negative)
4450 m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
4451 m_damage+= eff_damage;
4453 // Hemorrhage
4454 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4456 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4457 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4460 // Mangle (Cat): CP
4461 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4463 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4464 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4467 // take ammo
4468 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4470 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4472 // wands don't have ammo
4473 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4474 return;
4476 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4478 if(pItem->GetMaxStackCount()==1)
4480 // decrease durability for non-stackable throw weapon
4481 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4483 else
4485 // decrease items amount for stackable throw weapon
4486 uint32 count = 1;
4487 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4490 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4491 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4495 void Spell::EffectThreat(uint32 /*i*/)
4497 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4498 return;
4500 if(!unitTarget->CanHaveThreatList())
4501 return;
4503 unitTarget->AddThreat(m_caster, float(damage));
4506 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4508 if(!unitTarget)
4509 return;
4510 if(!unitTarget->isAlive())
4511 return;
4513 uint32 heal = m_caster->GetMaxHealth();
4515 m_healing+=heal;
4518 void Spell::EffectInterruptCast(uint32 /*i*/)
4520 if(!unitTarget)
4521 return;
4522 if(!unitTarget->isAlive())
4523 return;
4525 // TODO: not all spells that used this effect apply cooldown at school spells
4526 // also exist case: apply cooldown to interrupted cast only and to all spells
4527 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4529 if (unitTarget->m_currentSpells[i])
4531 // check if we can interrupt spell
4532 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4534 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4535 unitTarget->InterruptSpell(i,false);
4541 void Spell::EffectSummonObjectWild(uint32 i)
4543 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4545 GameObject* pGameObj = new GameObject;
4547 WorldObject* target = focusObject;
4548 if( !target )
4549 target = m_caster;
4551 float x,y,z;
4552 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4554 x = m_targets.m_destX;
4555 y = m_targets.m_destY;
4556 z = m_targets.m_destZ;
4558 else
4559 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4561 Map *map = target->GetMap();
4563 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4564 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4566 delete pGameObj;
4567 return;
4570 int32 duration = GetSpellDuration(m_spellInfo);
4571 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4572 pGameObj->SetSpellId(m_spellInfo->Id);
4574 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4575 m_caster->AddGameObject(pGameObj);
4576 map->Add(pGameObj);
4578 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4580 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4582 Player *pl = (Player*)m_caster;
4583 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4584 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4586 uint32 team = ALLIANCE;
4588 if(pl->GetTeam() == team)
4589 team = HORDE;
4591 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4596 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4598 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4600 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4601 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4603 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4608 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4610 GameObject* linkedGO = new GameObject;
4611 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4612 m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
4614 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
4615 linkedGO->SetSpellId(m_spellInfo->Id);
4617 m_caster->AddGameObject(linkedGO);
4618 map->Add(linkedGO);
4620 else
4622 delete linkedGO;
4623 linkedGO = NULL;
4624 return;
4629 void Spell::EffectScriptEffect(uint32 effIndex)
4631 // TODO: we must implement hunter pet summon at login there (spell 6962)
4633 switch(m_spellInfo->SpellFamilyName)
4635 case SPELLFAMILY_GENERIC:
4637 switch(m_spellInfo->Id)
4639 // PX-238 Winter Wondervolt TRAP
4640 case 26275:
4642 uint32 spells[4] = { 26272, 26157, 26273, 26274 };
4644 // check presence
4645 for(int j = 0; j < 4; ++j)
4646 if(unitTarget->HasAura(spells[j],0))
4647 return;
4649 // select spell
4650 uint32 iTmpSpellId = spells[urand(0,3)];
4652 // cast
4653 unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
4654 return;
4656 // Bending Shinbone
4657 case 8856:
4659 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4660 return;
4662 uint32 spell_id = 0;
4663 switch(urand(1,5))
4665 case 1: spell_id = 8854; break;
4666 default: spell_id = 8855; break;
4669 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4670 return;
4672 // Brittle Armor - need remove one 24575 Brittle Armor aura
4673 case 24590:
4674 unitTarget->RemoveSingleSpellAurasFromStack(24575);
4675 return;
4676 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4677 case 26465:
4678 unitTarget->RemoveSingleSpellAurasFromStack(26464);
4679 return;
4680 // Orb teleport spells
4681 case 25140:
4682 case 25143:
4683 case 25650:
4684 case 25652:
4685 case 29128:
4686 case 29129:
4687 case 35376:
4688 case 35727:
4690 if(!unitTarget)
4691 return;
4693 uint32 spellid;
4694 switch(m_spellInfo->Id)
4696 case 25140: spellid = 32571; break;
4697 case 25143: spellid = 32572; break;
4698 case 25650: spellid = 30140; break;
4699 case 25652: spellid = 30141; break;
4700 case 29128: spellid = 32568; break;
4701 case 29129: spellid = 32569; break;
4702 case 35376: spellid = 25649; break;
4703 case 35727: spellid = 35730; break;
4704 default:
4705 return;
4708 unitTarget->CastSpell(unitTarget,spellid,false);
4709 return;
4711 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4712 case 22539:
4713 case 22972:
4714 case 22975:
4715 case 22976:
4716 case 22977:
4717 case 22978:
4718 case 22979:
4719 case 22980:
4720 case 22981:
4721 case 22982:
4722 case 22983:
4723 case 22984:
4724 case 22985:
4726 if(!unitTarget || !unitTarget->isAlive())
4727 return;
4729 // Onyxia Scale Cloak
4730 if(unitTarget->GetDummyAura(22683))
4731 return;
4733 // Shadow Flame
4734 m_caster->CastSpell(unitTarget, 22682, true);
4735 return;
4737 // Summon Black Qiraji Battle Tank
4738 case 26656:
4740 if(!unitTarget)
4741 return;
4743 // Prevent stacking of mounts
4744 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4746 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4747 if (unitTarget->GetAreaId() == 3428)
4748 unitTarget->CastSpell(unitTarget, 25863, false);
4749 else
4750 unitTarget->CastSpell(unitTarget, 26655, false);
4751 return;
4753 // Piccolo of the Flaming Fire
4754 case 17512:
4756 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4757 return;
4758 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4759 return;
4761 // Escape artist
4762 case 20589:
4764 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4765 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
4766 return;
4768 // Mirren's Drinking Hat
4769 case 29830:
4771 uint32 item = 0;
4772 switch ( urand(1,6) )
4774 case 1:case 2:case 3:
4775 item = 23584;break; // Loch Modan Lager
4776 case 4:case 5:
4777 item = 23585;break; // Stouthammer Lite
4778 case 6:
4779 item = 23586;break; // Aerie Peak Pale Ale
4781 if (item)
4782 DoCreateItem(effIndex,item);
4783 break;
4785 // Improved Sprint
4786 case 30918:
4788 // Removes snares and roots.
4789 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4790 Unit::AuraMap& Auras = unitTarget->GetAuras();
4791 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4793 next = iter;
4794 ++next;
4795 Aura *aur = iter->second;
4796 if (!aur->IsPositive()) //only remove negative spells
4798 // check for mechanic mask
4799 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4801 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4802 if(Auras.empty())
4803 break;
4804 else
4805 next = Auras.begin();
4809 break;
4811 // Flame Crash
4812 case 41126:
4814 if(!unitTarget)
4815 return;
4817 unitTarget->CastSpell(unitTarget, 41131, true);
4818 break;
4820 // Force Cast - Portal Effect: Sunwell Isle
4821 case 44876:
4823 if(!unitTarget)
4824 return;
4826 unitTarget->CastSpell(unitTarget, 44870, true);
4827 break;
4829 // Goblin Weather Machine
4830 case 46203:
4832 if(!unitTarget)
4833 return;
4835 uint32 spellId = 0;
4836 switch(rand()%4)
4838 case 0: spellId = 46740; break;
4839 case 1: spellId = 46739; break;
4840 case 2: spellId = 46738; break;
4841 case 3: spellId = 46736; break;
4843 unitTarget->CastSpell(unitTarget, spellId, true);
4844 break;
4846 //5,000 Gold
4847 case 46642:
4849 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4850 return;
4852 ((Player*)unitTarget)->ModifyMoney(50000000);
4854 break;
4856 // Emblazon Runeblade
4857 case 51770:
4859 if(!unitTarget)
4860 return;
4862 unitTarget->CastSpell(unitTarget,51771,false);
4863 break;
4865 // Death Gate
4866 case 52751:
4868 if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT)
4869 return;
4870 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
4871 unitTarget->CastSpell(unitTarget, damage, false);
4872 break;
4874 // Winged Steed of the Ebon Blade
4875 case 54729:
4877 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4878 return;
4880 // Prevent stacking of mounts
4881 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4883 // Triggered spell id dependent of riding skill
4884 if(uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING))
4886 if (skillval >= 300)
4887 unitTarget->CastSpell(unitTarget, 54727, true);
4888 else
4889 unitTarget->CastSpell(unitTarget, 54726, true);
4891 return;
4893 case 58418: // Portal to Orgrimmar
4894 case 58420: // Portal to Stormwind
4896 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0)
4897 return;
4899 uint32 spellID = m_spellInfo->CalculateSimpleValue(0);
4900 uint32 questID = m_spellInfo->CalculateSimpleValue(1);
4902 if( ((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID) )
4903 unitTarget->CastSpell(unitTarget, spellID, true);
4905 return;
4907 // random spell learn instead placeholder
4908 case 60893: // Northrend Alchemy Research
4909 case 61177: // Northrend Inscription Research
4910 case 61288: // Minor Inscription Research
4911 case 61756: // Northrend Inscription Research (FAST QA VERSION)
4913 if(!IsExplicitDiscoverySpell(m_spellInfo))
4915 sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id);
4916 return;
4919 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
4920 return;
4921 Player* player = (Player*)m_caster;
4923 // need replace effect 0 item by loot
4924 uint32 reagent_id = m_spellInfo->EffectItemType[0];
4926 if(!player->HasItemCount(reagent_id,1))
4927 return;
4929 // remove reagent
4930 uint32 count = 1;
4931 player->DestroyItemCount (reagent_id,count,true);
4933 // create some random items
4934 player->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell);
4936 // learn random explicit discovery recipe (if any)
4937 if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
4938 player->learnSpell(discoveredSpell,false);
4939 return;
4942 break;
4944 case SPELLFAMILY_WARLOCK:
4946 switch(m_spellInfo->Id)
4948 // Healthstone creating spells
4949 case 6201:
4950 case 6202:
4951 case 5699:
4952 case 11729:
4953 case 11730:
4954 case 27230:
4955 case 47871:
4956 case 47878:
4958 uint32 itemtype;
4959 uint32 rank = 0;
4960 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4961 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4963 if((*i)->GetId() == 18692)
4965 rank = 1;
4966 break;
4968 else if((*i)->GetId() == 18693)
4970 rank = 2;
4971 break;
4975 static uint32 const itypes[8][3] = {
4976 { 5512,19004,19005}, // Minor Healthstone
4977 { 5511,19006,19007}, // Lesser Healthstone
4978 { 5509,19008,19009}, // Healthstone
4979 { 5510,19010,19011}, // Greater Healthstone
4980 { 9421,19012,19013}, // Major Healthstone
4981 {22103,22104,22105}, // Master Healthstone
4982 {36889,36890,36891}, // Demonic Healthstone
4983 {36892,36893,36894} // Fel Healthstone
4986 switch(m_spellInfo->Id)
4988 case 6201:
4989 itemtype=itypes[0][rank];break; // Minor Healthstone
4990 case 6202:
4991 itemtype=itypes[1][rank];break; // Lesser Healthstone
4992 case 5699:
4993 itemtype=itypes[2][rank];break; // Healthstone
4994 case 11729:
4995 itemtype=itypes[3][rank];break; // Greater Healthstone
4996 case 11730:
4997 itemtype=itypes[4][rank];break; // Major Healthstone
4998 case 27230:
4999 itemtype=itypes[5][rank];break; // Master Healthstone
5000 case 47871:
5001 itemtype=itypes[6][rank];break; // Demonic Healthstone
5002 case 47878:
5003 itemtype=itypes[7][rank];break; // Fel Healthstone
5004 default:
5005 return;
5007 DoCreateItem( effIndex, itemtype );
5008 return;
5010 // Everlasting Affliction
5011 case 47422:
5013 // Need refresh caster corruption auras on target
5014 Unit::AuraMap& suAuras = unitTarget->GetAuras();
5015 for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
5017 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5018 if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
5019 spellInfo->SpellFamilyFlags & 0x0000000000000002LL &&
5020 (*itr).second->GetCasterGUID()==m_caster->GetGUID())
5021 (*itr).second->RefreshAura();
5023 return;
5026 break;
5028 case SPELLFAMILY_PRIEST:
5030 switch(m_spellInfo->Id)
5032 // Pain and Suffering
5033 case 47948:
5035 if (!unitTarget)
5036 return;
5037 // Refresh Shadow Word: Pain on target
5038 Unit::AuraMap& auras = unitTarget->GetAuras();
5039 for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
5041 SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
5042 if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
5043 spellInfo->SpellFamilyFlags & 0x0000000000008000LL &&
5044 (*itr).second->GetCasterGUID() == m_caster->GetGUID())
5046 (*itr).second->RefreshAura();
5047 return;
5050 return;
5052 default:
5053 break;
5055 break;
5057 case SPELLFAMILY_HUNTER:
5059 switch(m_spellInfo->Id)
5061 // Chimera Shot
5062 case 53209:
5064 uint32 spellId = 0;
5065 int32 basePoint = 0;
5066 Unit::AuraMap& Auras = unitTarget->GetAuras();
5067 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
5069 Aura *aura = (*i).second;
5070 if (aura->GetCasterGUID() != m_caster->GetGUID())
5071 continue;
5072 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5073 uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
5074 if (!(familyFlag & 0x000000800000C000LL))
5075 continue;
5076 // Refresh aura duration
5077 aura->RefreshAura();
5079 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5080 if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
5082 spellId = 53353; // 53353 Chimera Shot - Serpent
5083 basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
5085 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5086 if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
5088 spellId = 53358; // 53358 Chimera Shot - Viper
5089 basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
5091 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5092 if (familyFlag & 0x0000000000008000LL)
5093 spellId = 53359; // 53359 Chimera Shot - Scorpid
5094 // ?? nothing say in spell desc (possibly need addition check)
5095 //if (familyFlag & 0x0000010000000000LL || // dot
5096 // familyFlag & 0x0000100000000000LL) // stun
5098 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5101 if (spellId)
5102 m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
5103 return;
5105 default:
5106 break;
5108 break;
5110 case SPELLFAMILY_PALADIN:
5112 // Judgement
5113 if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
5115 if(!unitTarget || !unitTarget->isAlive())
5116 return;
5117 uint32 spellId1 = 0;
5118 uint32 spellId2 = 0;
5120 // Judgement self add switch
5121 switch (m_spellInfo->Id)
5123 case 41467: break; // Judgement
5124 case 53407: spellId1 = 20184; break; // Judgement of Justice
5125 case 20271: // Judgement of Light
5126 case 57774: spellId1 = 20185; break; // Judgement of Light
5127 case 53408: spellId1 = 20186; break; // Judgement of Wisdom
5128 default:
5129 return;
5131 // all seals have aura dummy in 2 effect
5132 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
5133 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
5135 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
5136 // search seal (all seals have judgement's aura dummy spell id in 2 effect
5137 if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
5138 continue;
5139 spellId2 = (*itr)->GetModifier()->m_amount;
5140 SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
5141 if (!judge)
5142 continue;
5143 break;
5145 if (spellId1)
5146 m_caster->CastSpell(unitTarget, spellId1, true);
5147 if (spellId2)
5148 m_caster->CastSpell(unitTarget, spellId2, true);
5149 return;
5152 case SPELLFAMILY_POTION:
5154 switch(m_spellInfo->Id)
5156 // Dreaming Glory
5157 case 28698:
5159 if(!unitTarget)
5160 return;
5161 unitTarget->CastSpell(unitTarget, 28694, true);
5162 break;
5164 // Netherbloom
5165 case 28702:
5167 if(!unitTarget)
5168 return;
5169 // 25% chance of casting a random buff
5170 if(roll_chance_i(75))
5171 return;
5173 // triggered spells are 28703 to 28707
5174 // Note: some sources say, that there was the possibility of
5175 // receiving a debuff. However, this seems to be removed by a patch.
5176 const uint32 spellid = 28703;
5178 // don't overwrite an existing aura
5179 for(uint8 i=0; i<5; i++)
5180 if(unitTarget->HasAura(spellid+i, 0))
5181 return;
5182 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
5183 break;
5186 // Nightmare Vine
5187 case 28720:
5189 if(!unitTarget)
5190 return;
5191 // 25% chance of casting Nightmare Pollen
5192 if(roll_chance_i(75))
5193 return;
5194 unitTarget->CastSpell(unitTarget, 28721, true);
5195 break;
5198 break;
5202 // normal DB scripted effect
5203 if(!unitTarget)
5204 return;
5206 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
5207 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
5210 void Spell::EffectSanctuary(uint32 /*i*/)
5212 if(!unitTarget)
5213 return;
5214 //unitTarget->CombatStop();
5216 unitTarget->CombatStop();
5217 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
5218 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5219 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
5221 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
5225 void Spell::EffectAddComboPoints(uint32 /*i*/)
5227 if(!unitTarget)
5228 return;
5230 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5231 return;
5233 if(damage <= 0)
5234 return;
5236 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5239 void Spell::EffectDuel(uint32 i)
5241 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5242 return;
5244 Player *caster = (Player*)m_caster;
5245 Player *target = (Player*)unitTarget;
5247 // caster or target already have requested duel
5248 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5249 return;
5251 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5252 // Don't have to check the target's map since you cannot challenge someone across maps
5253 uint32 mapid = caster->GetMapId();
5254 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
5256 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5257 return;
5260 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5261 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5263 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5264 return;
5267 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5268 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5270 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5271 return;
5274 //CREATE DUEL FLAG OBJECT
5275 GameObject* pGameObj = new GameObject;
5277 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5279 Map *map = m_caster->GetMap();
5280 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
5281 map, m_caster->GetPhaseMask(),
5282 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5283 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5284 m_caster->GetPositionZ(),
5285 m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5287 delete pGameObj;
5288 return;
5291 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5292 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5293 int32 duration = GetSpellDuration(m_spellInfo);
5294 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5295 pGameObj->SetSpellId(m_spellInfo->Id);
5297 m_caster->AddGameObject(pGameObj);
5298 map->Add(pGameObj);
5299 //END
5301 // Send request
5302 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5303 data << pGameObj->GetGUID();
5304 data << caster->GetGUID();
5305 caster->GetSession()->SendPacket(&data);
5306 target->GetSession()->SendPacket(&data);
5308 // create duel-info
5309 DuelInfo *duel = new DuelInfo;
5310 duel->initiator = caster;
5311 duel->opponent = target;
5312 duel->startTime = 0;
5313 duel->startTimer = 0;
5314 caster->duel = duel;
5316 DuelInfo *duel2 = new DuelInfo;
5317 duel2->initiator = caster;
5318 duel2->opponent = caster;
5319 duel2->startTime = 0;
5320 duel2->startTimer = 0;
5321 target->duel = duel2;
5323 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5324 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5327 void Spell::EffectStuck(uint32 /*i*/)
5329 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5330 return;
5332 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5333 return;
5335 Player* pTarget = (Player*)unitTarget;
5337 sLog.outDebug("Spell Effect: Stuck");
5338 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());
5340 if(pTarget->isInFlight())
5341 return;
5343 // homebind location is loaded always
5344 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5346 // Stuck spell trigger Hearthstone cooldown
5347 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5348 if(!spellInfo)
5349 return;
5350 Spell spell(pTarget,spellInfo,true,0);
5351 spell.SendSpellCooldown();
5354 void Spell::EffectSummonPlayer(uint32 /*i*/)
5356 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5357 return;
5359 // Evil Twin (ignore player summon, but hide this for summoner)
5360 if(unitTarget->GetDummyAura(23445))
5361 return;
5363 float x,y,z;
5364 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5366 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5368 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5369 data << uint64(m_caster->GetGUID()); // summoner guid
5370 data << uint32(m_caster->GetZoneId()); // summoner zone
5371 data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs
5372 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5375 static ScriptInfo generateActivateCommand()
5377 ScriptInfo si;
5378 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5379 return si;
5382 void Spell::EffectActivateObject(uint32 effect_idx)
5384 if(!gameObjTarget)
5385 return;
5387 static ScriptInfo activateCommand = generateActivateCommand();
5389 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5391 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5394 void Spell::EffectApplyGlyph(uint32 i)
5396 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5397 return;
5399 Player *player = (Player*)m_caster;
5401 // apply new one
5402 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5404 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5406 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5408 if(gp->TypeFlags != gs->TypeFlags)
5410 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5411 return; // glyph slot mismatch
5415 // remove old glyph
5416 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5418 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5420 player->RemoveAurasDueToSpell(old_gp->SpellId);
5421 player->SetGlyph(m_glyphIndex, 0);
5425 player->CastSpell(m_caster, gp->SpellId, true);
5426 player->SetGlyph(m_glyphIndex, glyph);
5431 void Spell::EffectSummonTotem(uint32 i)
5433 uint8 slot = 0;
5434 switch(m_spellInfo->EffectMiscValueB[i])
5436 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5437 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5438 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5439 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5440 // Battle standard case
5441 case SUMMON_TYPE_TOTEM: slot = 254; break;
5442 // jewelery statue case, like totem without slot
5443 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5444 default: return;
5447 if(slot < MAX_TOTEM)
5449 uint64 guid = m_caster->m_TotemSlot[slot];
5450 if(guid != 0)
5452 Creature *OldTotem = m_caster->GetMap()->GetCreature(guid);
5453 if(OldTotem && OldTotem->isTotem())
5454 ((Totem*)OldTotem)->UnSummon();
5458 uint32 team = 0;
5459 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5460 team = ((Player*)m_caster)->GetTeam();
5462 Totem* pTotem = new Totem;
5464 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
5465 m_spellInfo->EffectMiscValue[i], team ))
5467 delete pTotem;
5468 return;
5471 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5473 float x,y,z;
5474 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5476 // totem must be at same Z in case swimming caster and etc.
5477 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5478 z = m_caster->GetPositionZ();
5480 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5482 if(slot < MAX_TOTEM)
5483 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5485 pTotem->SetOwner(m_caster->GetGUID());
5486 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5488 int32 duration=GetSpellDuration(m_spellInfo);
5489 if(Player* modOwner = m_caster->GetSpellModOwner())
5490 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5491 pTotem->SetDuration(duration);
5493 if (damage) // if not spell info, DB values used
5495 pTotem->SetMaxHealth(damage);
5496 pTotem->SetHealth(damage);
5499 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5501 if(m_caster->GetTypeId() == TYPEID_PLAYER)
5502 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5504 pTotem->Summon(m_caster);
5506 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5508 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5509 data << uint8(slot);
5510 data << uint64(pTotem->GetGUID());
5511 data << uint32(duration);
5512 data << uint32(m_spellInfo->Id);
5513 ((Player*)m_caster)->SendDirectMessage(&data);
5517 void Spell::EffectEnchantHeldItem(uint32 i)
5519 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5520 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5521 return;
5523 Player* item_owner = (Player*)unitTarget;
5524 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5526 if(!item )
5527 return;
5529 // must be equipped
5530 if(!item ->IsEquipped())
5531 return;
5533 if (m_spellInfo->EffectMiscValue[i])
5535 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5536 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5537 if(!duration)
5538 duration = m_currentBasePoints[i]+1; //Base points after ..
5539 if(!duration)
5540 duration = 10; //10 seconds for enchants which don't have listed duration
5542 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5543 if(!pEnchant)
5544 return;
5546 // Always go to temp enchantment slot
5547 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5549 // Enchantment will not be applied if a different one already exists
5550 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5551 return;
5553 // Apply the temporary enchantment
5554 item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0);
5555 item_owner->ApplyEnchantment(item,slot,true);
5559 void Spell::EffectDisEnchant(uint32 /*i*/)
5561 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5562 return;
5564 Player* p_caster = (Player*)m_caster;
5565 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5566 return;
5568 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5570 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5572 // item will be removed at disenchanting end
5575 void Spell::EffectInebriate(uint32 /*i*/)
5577 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5578 return;
5580 Player *player = (Player*)unitTarget;
5581 uint16 currentDrunk = player->GetDrunkValue();
5582 uint16 drunkMod = damage * 256;
5583 if (currentDrunk + drunkMod > 0xFFFF)
5584 currentDrunk = 0xFFFF;
5585 else
5586 currentDrunk += drunkMod;
5587 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5590 void Spell::EffectFeedPet(uint32 i)
5592 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5593 return;
5595 Player *_player = (Player*)m_caster;
5597 Item* foodItem = m_targets.getItemTarget();
5598 if(!foodItem)
5599 return;
5601 Pet *pet = _player->GetPet();
5602 if(!pet)
5603 return;
5605 if(!pet->isAlive())
5606 return;
5608 int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel);
5609 if(benefit <= 0)
5610 return;
5612 uint32 count = 1;
5613 _player->DestroyItemCount(foodItem,count,true);
5614 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5616 m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5619 void Spell::EffectDismissPet(uint32 /*i*/)
5621 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5622 return;
5624 Pet* pet = m_caster->GetPet();
5626 // not let dismiss dead pet
5627 if(!pet||!pet->isAlive())
5628 return;
5630 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5633 void Spell::EffectSummonObject(uint32 i)
5635 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5637 uint8 slot = 0;
5638 switch(m_spellInfo->Effect[i])
5640 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5641 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5642 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5643 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5644 default: return;
5647 uint64 guid = m_caster->m_ObjectSlot[slot];
5648 if(guid != 0)
5650 GameObject* obj = NULL;
5651 if( m_caster )
5652 obj = m_caster->GetMap()->GetGameObject(guid);
5654 if(obj) obj->Delete();
5655 m_caster->m_ObjectSlot[slot] = 0;
5658 GameObject* pGameObj = new GameObject;
5660 float x,y,z;
5661 // If dest location if present
5662 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5664 x = m_targets.m_destX;
5665 y = m_targets.m_destY;
5666 z = m_targets.m_destZ;
5668 // Summon in random point all other units if location present
5669 else
5670 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5672 Map *map = m_caster->GetMap();
5673 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
5674 m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
5676 delete pGameObj;
5677 return;
5680 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5681 int32 duration = GetSpellDuration(m_spellInfo);
5682 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
5683 pGameObj->SetSpellId(m_spellInfo->Id);
5684 m_caster->AddGameObject(pGameObj);
5686 map->Add(pGameObj);
5687 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5688 data << pGameObj->GetGUID();
5689 m_caster->SendMessageToSet(&data,true);
5691 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5694 void Spell::EffectResurrect(uint32 /*effIndex*/)
5696 if(!unitTarget)
5697 return;
5698 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5699 return;
5701 if(unitTarget->isAlive())
5702 return;
5703 if(!unitTarget->IsInWorld())
5704 return;
5706 switch (m_spellInfo->Id)
5708 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5709 case 8342:
5710 if (roll_chance_i(67))
5712 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5713 return;
5715 break;
5716 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5717 case 22999:
5718 if (roll_chance_i(50))
5720 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5721 return;
5723 break;
5724 default:
5725 break;
5728 Player* pTarget = ((Player*)unitTarget);
5730 if(pTarget->isRessurectRequested()) // already have one active request
5731 return;
5733 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5734 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5736 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5737 SendResurrectRequest(pTarget);
5740 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5742 if(!unitTarget || !unitTarget->isAlive())
5743 return;
5745 if( unitTarget->m_extraAttacks )
5746 return;
5748 unitTarget->m_extraAttacks = damage;
5751 void Spell::EffectParry(uint32 /*i*/)
5753 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5754 ((Player*)unitTarget)->SetCanParry(true);
5757 void Spell::EffectBlock(uint32 /*i*/)
5759 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
5760 ((Player*)unitTarget)->SetCanBlock(true);
5763 void Spell::EffectMomentMove(uint32 i)
5765 if(unitTarget->isInFlight())
5766 return;
5768 if( m_spellInfo->rangeIndex== 1) //self range
5770 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5772 // before caster
5773 float fx,fy,fz;
5774 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5775 float ox,oy,oz;
5776 unitTarget->GetPosition(ox,oy,oz);
5778 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5779 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5781 fx = fx2;
5782 fy = fy2;
5783 fz = fz2;
5784 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5787 unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(),unitTarget==m_caster);
5791 void Spell::EffectReputation(uint32 i)
5793 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5794 return;
5796 Player *_player = (Player*)unitTarget;
5798 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5800 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5802 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5804 if(!factionEntry)
5805 return;
5807 _player->GetReputationMgr().ModifyReputation(factionEntry,rep_change);
5810 void Spell::EffectQuestComplete(uint32 i)
5812 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5813 return;
5815 Player *_player = (Player*)m_caster;
5817 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5818 _player->AreaExploredOrEventHappens(quest_id);
5821 void Spell::EffectSelfResurrect(uint32 i)
5823 if(!unitTarget || unitTarget->isAlive())
5824 return;
5825 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5826 return;
5827 if(!unitTarget->IsInWorld())
5828 return;
5830 uint32 health = 0;
5831 uint32 mana = 0;
5833 // flat case
5834 if(damage < 0)
5836 health = uint32(-damage);
5837 mana = m_spellInfo->EffectMiscValue[i];
5839 // percent case
5840 else
5842 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5843 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5844 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5847 Player *plr = ((Player*)unitTarget);
5848 plr->ResurrectPlayer(0.0f);
5850 plr->SetHealth( health );
5851 plr->SetPower(POWER_MANA, mana );
5852 plr->SetPower(POWER_RAGE, 0 );
5853 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5855 plr->SpawnCorpseBones();
5857 plr->SaveToDB();
5860 void Spell::EffectSkinning(uint32 /*i*/)
5862 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5863 return;
5864 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5865 return;
5867 Creature* creature = (Creature*) unitTarget;
5868 int32 targetLevel = creature->getLevel();
5870 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5872 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5873 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5875 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5877 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5879 // Double chances for elites
5880 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5883 void Spell::EffectCharge(uint32 /*i*/)
5885 if(!unitTarget || !m_caster)
5886 return;
5888 float x, y, z;
5889 unitTarget->GetContactPoint(m_caster, x, y, z);
5890 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5891 ((Creature *)unitTarget)->StopMoving();
5893 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5894 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5896 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5897 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5899 // not all charge effects used in negative spells
5900 if ( !IsPositiveSpell(m_spellInfo->Id))
5901 m_caster->Attack(unitTarget,true);
5904 void Spell::EffectSummonCritter(uint32 i)
5906 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5907 return;
5908 Player* player = (Player*)m_caster;
5910 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5911 if(!pet_entry)
5912 return;
5914 Pet* old_critter = player->GetMiniPet();
5916 // for same pet just despawn
5917 if(old_critter && old_critter->GetEntry() == pet_entry)
5919 player->RemoveMiniPet();
5920 return;
5923 // despawn old pet before summon new
5924 if(old_critter)
5925 player->RemoveMiniPet();
5927 // summon new pet
5928 Pet* critter = new Pet(MINI_PET);
5930 Map *map = m_caster->GetMap();
5931 uint32 pet_number = objmgr.GeneratePetNumber();
5932 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
5933 pet_entry, pet_number))
5935 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5936 delete critter;
5937 return;
5940 float x,y,z;
5941 // If dest location if present
5942 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5944 x = m_targets.m_destX;
5945 y = m_targets.m_destY;
5946 z = m_targets.m_destZ;
5948 // Summon if dest location not present near caster
5949 else
5950 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5952 critter->Relocate(x,y,z,m_caster->GetOrientation());
5954 if(!critter->IsPositionValid())
5956 sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5957 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5958 delete critter;
5959 return;
5962 critter->SetOwnerGUID(m_caster->GetGUID());
5963 critter->SetCreatorGUID(m_caster->GetGUID());
5964 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5965 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5967 critter->AIM_Initialize();
5968 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5969 critter->SetMaxHealth(1);
5970 critter->SetHealth(1);
5971 critter->SetLevel(1);
5973 // set timer for unsummon
5974 int32 duration = GetSpellDuration(m_spellInfo);
5975 if(duration > 0)
5976 critter->SetDuration(duration);
5978 std::string name = player->GetName();
5979 name.append(petTypeSuffix[critter->getPetType()]);
5980 critter->SetName( name );
5981 player->SetMiniPet(critter);
5983 map->Add((Creature*)critter);
5986 void Spell::EffectKnockBack(uint32 i)
5988 if(!unitTarget || !m_caster)
5989 return;
5991 // Effect only works on players
5992 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5993 return;
5995 float vsin = sin(m_caster->GetAngle(unitTarget));
5996 float vcos = cos(m_caster->GetAngle(unitTarget));
5998 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5999 data.append(unitTarget->GetPackGUID());
6000 data << uint32(0); // Sequence
6001 data << float(vcos); // x direction
6002 data << float(vsin); // y direction
6003 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
6004 data << float(damage/-10); // Z Movement speed (vertical)
6006 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6009 void Spell::EffectSendTaxi(uint32 i)
6011 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6012 return;
6014 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
6015 if(!entry)
6016 return;
6018 std::vector<uint32> nodes;
6020 nodes.resize(2);
6021 nodes[0] = entry->from;
6022 nodes[1] = entry->to;
6024 uint32 mountid = 0;
6025 switch(m_spellInfo->Id)
6027 case 31606: //Stormcrow Amulet
6028 mountid = 17447;
6029 break;
6030 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
6031 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
6032 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
6033 mountid = 22840;
6034 break;
6035 case 34905: //Stealth Flight
6036 mountid = 6851;
6037 break;
6038 case 45883: //Amber Ledge to Beryl Point
6039 mountid = 23524;
6040 break;
6041 case 46064: //Amber Ledge to Coldarra
6042 mountid = 6371;
6043 break;
6044 case 53335: //Stormwind Harbor Flight - Peaceful
6045 mountid = 6852;
6046 break;
6049 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
6053 void Spell::EffectPlayerPull(uint32 i)
6055 if(!unitTarget || !m_caster)
6056 return;
6058 // Effect only works on players
6059 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
6060 return;
6062 float vsin = sin(unitTarget->GetAngle(m_caster));
6063 float vcos = cos(unitTarget->GetAngle(m_caster));
6065 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
6066 data.append(unitTarget->GetPackGUID());
6067 data << uint32(0); // Sequence
6068 data << float(vcos); // x direction
6069 data << float(vsin); // y direction
6070 // Horizontal speed
6071 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
6072 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
6074 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
6077 void Spell::EffectDispelMechanic(uint32 i)
6079 if(!unitTarget)
6080 return;
6082 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
6084 Unit::AuraMap& Auras = unitTarget->GetAuras();
6085 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
6087 next = iter;
6088 ++next;
6089 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
6090 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
6092 unitTarget->RemoveAurasDueToSpell(spell->Id);
6093 if(Auras.empty())
6094 break;
6095 else
6096 next = Auras.begin();
6099 return;
6102 void Spell::EffectSummonDeadPet(uint32 /*i*/)
6104 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6105 return;
6106 Player *_player = (Player*)m_caster;
6107 Pet *pet = _player->GetPet();
6108 if(!pet)
6109 return;
6110 if(pet->isAlive())
6111 return;
6112 if(damage < 0)
6113 return;
6114 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
6115 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
6116 pet->setDeathState( ALIVE );
6117 pet->clearUnitState(UNIT_STAT_ALL_STATE);
6118 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
6120 pet->AIM_Initialize();
6122 _player->PetSpellInitialize();
6123 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
6126 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
6128 float mana = 0;
6129 for(int slot = 0; slot < MAX_TOTEM; ++slot)
6131 if(!m_caster->m_TotemSlot[slot])
6132 continue;
6134 Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]);
6135 if(totem && totem->isTotem())
6137 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
6138 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
6139 if(spellInfo)
6140 mana += spellInfo->manaCost * damage / 100;
6141 ((Totem*)totem)->UnSummon();
6145 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
6146 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
6149 void Spell::EffectDurabilityDamage(uint32 i)
6151 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6152 return;
6154 int32 slot = m_spellInfo->EffectMiscValue[i];
6156 // FIXME: some spells effects have value -1/-2
6157 // Possibly its mean -1 all player equipped items and -2 all items
6158 if(slot < 0)
6160 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
6161 return;
6164 // invalid slot value
6165 if(slot >= INVENTORY_SLOT_BAG_END)
6166 return;
6168 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6169 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
6172 void Spell::EffectDurabilityDamagePCT(uint32 i)
6174 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6175 return;
6177 int32 slot = m_spellInfo->EffectMiscValue[i];
6179 // FIXME: some spells effects have value -1/-2
6180 // Possibly its mean -1 all player equipped items and -2 all items
6181 if(slot < 0)
6183 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
6184 return;
6187 // invalid slot value
6188 if(slot >= INVENTORY_SLOT_BAG_END)
6189 return;
6191 if(damage <= 0)
6192 return;
6194 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
6195 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
6198 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
6200 if(!unitTarget)
6201 return;
6203 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
6206 void Spell::EffectTransmitted(uint32 effIndex)
6208 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
6210 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
6212 if (!goinfo)
6214 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
6215 return;
6218 float fx,fy,fz;
6220 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6222 fx = m_targets.m_destX;
6223 fy = m_targets.m_destY;
6224 fz = m_targets.m_destZ;
6226 //FIXME: this can be better check for most objects but still hack
6227 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
6229 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
6230 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6232 else
6234 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6235 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
6236 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
6238 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
6241 Map *cMap = m_caster->GetMap();
6243 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
6245 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
6246 { // but this is not proper, we really need to ignore not materialized objects
6247 SendCastResult(SPELL_FAILED_NOT_HERE);
6248 SendChannelUpdate(0);
6249 return;
6252 // replace by water level in this case
6253 fz = cMap->GetWaterLevel(fx,fy);
6255 // if gameobject is summoning object, it should be spawned right on caster's position
6256 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6258 m_caster->GetPosition(fx,fy,fz);
6261 GameObject* pGameObj = new GameObject;
6263 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6264 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6266 delete pGameObj;
6267 return;
6270 int32 duration = GetSpellDuration(m_spellInfo);
6272 switch(goinfo->type)
6274 case GAMEOBJECT_TYPE_FISHINGNODE:
6276 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6277 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6279 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6280 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6281 int32 lastSec = 0;
6282 switch(urand(0, 3))
6284 case 0: lastSec = 3; break;
6285 case 1: lastSec = 7; break;
6286 case 2: lastSec = 13; break;
6287 case 3: lastSec = 17; break;
6290 duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS;
6291 break;
6293 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6295 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6297 pGameObj->AddUniqueUse((Player*)m_caster);
6298 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6300 break;
6302 case GAMEOBJECT_TYPE_FISHINGHOLE:
6303 case GAMEOBJECT_TYPE_CHEST:
6304 default:
6306 break;
6310 pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6312 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6314 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6315 pGameObj->SetSpellId(m_spellInfo->Id);
6317 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6318 //m_caster->AddGameObject(pGameObj);
6319 //m_ObjToDel.push_back(pGameObj);
6321 cMap->Add(pGameObj);
6323 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6324 data << uint64(pGameObj->GetGUID());
6325 m_caster->SendMessageToSet(&data,true);
6327 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6329 GameObject* linkedGO = new GameObject;
6330 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6331 m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
6333 linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0);
6334 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6335 linkedGO->SetSpellId(m_spellInfo->Id);
6336 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6338 linkedGO->GetMap()->Add(linkedGO);
6340 else
6342 delete linkedGO;
6343 linkedGO = NULL;
6344 return;
6349 void Spell::EffectProspecting(uint32 /*i*/)
6351 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6352 return;
6354 Player* p_caster = (Player*)m_caster;
6355 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6356 return;
6358 if(itemTarget->GetCount() < 5)
6359 return;
6361 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6363 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6364 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6365 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6368 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6371 void Spell::EffectMilling(uint32 /*i*/)
6373 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6374 return;
6376 Player* p_caster = (Player*)m_caster;
6377 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6378 return;
6380 if(itemTarget->GetCount() < 5)
6381 return;
6383 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6385 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6386 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6387 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6390 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6393 void Spell::EffectSkill(uint32 /*i*/)
6395 sLog.outDebug("WORLD: SkillEFFECT");
6398 void Spell::EffectSummonDemon(uint32 i)
6400 // select center of summon position
6401 float center_x = m_targets.m_destX;
6402 float center_y = m_targets.m_destY;
6403 float center_z = m_targets.m_destZ;
6405 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
6407 int32 amount = damage > 0 ? damage : 1;
6409 for(int32 count = 0; count < amount; ++count)
6411 float px, py, pz;
6412 // If dest location if present
6413 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
6415 // Summon 1 unit in dest location
6416 if (count == 0)
6418 px = m_targets.m_destX;
6419 py = m_targets.m_destY;
6420 pz = m_targets.m_destZ;
6422 // Summon in random point all other units if location present
6423 else
6424 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
6426 // Summon if dest location not present near caster
6427 else
6428 m_caster->GetClosePoint(px,py,pz,3.0f);
6430 int32 duration = GetSpellDuration(m_spellInfo);
6432 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration);
6433 if (!Charmed) // something fatal, not attempt more
6434 return;
6436 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6437 Charmed->SetLevel(m_caster->getLevel());
6439 // TODO: Add damage/mana/hp according to level
6441 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6443 // Enslave demon effect, without mana cost and cooldown
6444 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6446 // Inferno effect
6447 Charmed->CastSpell(Charmed, 22703, true, 0);
6452 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6453 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6454 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6455 This is why we use a half sec delay between the visual effect and the resurrection itself */
6456 void Spell::EffectSpiritHeal(uint32 /*i*/)
6459 if(!unitTarget || unitTarget->isAlive())
6460 return;
6461 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6462 return;
6463 if(!unitTarget->IsInWorld())
6464 return;
6466 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6467 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6468 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6469 ((Player*)unitTarget)->SpawnCorpseBones();
6473 // remove insignia spell effect
6474 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6476 sLog.outDebug("Effect: SkinPlayerCorpse");
6477 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6478 return;
6480 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6483 void Spell::EffectStealBeneficialBuff(uint32 i)
6485 sLog.outDebug("Effect: StealBeneficialBuff");
6487 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6488 return;
6490 std::vector <Aura *> steal_list;
6491 // Create dispel mask by dispel type
6492 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6493 Unit::AuraMap const& auras = unitTarget->GetAuras();
6494 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6496 Aura *aur = (*itr).second;
6497 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6499 // Need check for passive? this
6500 if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
6501 steal_list.push_back(aur);
6504 // Ok if exist some buffs for dispel try dispel it
6505 if (!steal_list.empty())
6507 std::list < std::pair<uint32,uint64> > success_list;
6508 int32 list_size = steal_list.size();
6509 // Dispell N = damage buffs (or while exist buffs for dispel)
6510 for (int32 count=0; count < damage && list_size > 0; ++count)
6512 // Random select buff for dispel
6513 Aura *aur = steal_list[urand(0, list_size-1)];
6514 // Not use chance for steal
6515 // TODO possible need do it
6516 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6518 // Remove buff from list for prevent doubles
6519 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6521 Aura *stealed = *j;
6522 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6524 j = steal_list.erase(j);
6525 --list_size;
6527 else
6528 ++j;
6531 // Really try steal and send log
6532 if (!success_list.empty())
6534 int32 count = success_list.size();
6535 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6536 data.append(unitTarget->GetPackGUID()); // Victim GUID
6537 data.append(m_caster->GetPackGUID()); // Caster GUID
6538 data << uint32(m_spellInfo->Id); // Dispell spell id
6539 data << uint8(0); // not used
6540 data << uint32(count); // count
6541 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6543 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6544 data << uint32(spellInfo->Id); // Spell Id
6545 data << uint8(0); // 0 - steals !=0 transfers
6546 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6548 m_caster->SendMessageToSet(&data, true);
6553 void Spell::EffectKillCredit(uint32 i)
6555 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6556 return;
6558 ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(m_spellInfo->EffectMiscValue[i], unitTarget);
6561 void Spell::EffectQuestFail(uint32 i)
6563 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6564 return;
6566 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6569 void Spell::EffectActivateRune(uint32 eff_idx)
6571 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6572 return;
6574 Player *plr = (Player*)m_caster;
6576 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6577 return;
6579 for(uint32 j = 0; j < MAX_RUNES; ++j)
6581 if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
6583 plr->SetRuneCooldown(j, 0);
6588 void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
6590 if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
6591 ((Player*)unitTarget)->SetCanTitanGrip(true);
6594 void Spell::EffectRenamePet(uint32 /*eff_idx*/)
6596 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6597 !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6598 return;
6600 unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);