Some work on Runic Power and Milling Spell Effect
[getmangos.git] / src / game / SpellEffects.cpp
blob2e101b6db2dd9374fe9efa88a7b518e31c881f47
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "SharedDefines.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
24 #include "Opcodes.h"
25 #include "Log.h"
26 #include "UpdateMask.h"
27 #include "World.h"
28 #include "ObjectMgr.h"
29 #include "SpellMgr.h"
30 #include "Player.h"
31 #include "SkillExtraItems.h"
32 #include "Unit.h"
33 #include "CreatureAI.h"
34 #include "Spell.h"
35 #include "DynamicObject.h"
36 #include "SpellAuras.h"
37 #include "Group.h"
38 #include "UpdateData.h"
39 #include "MapManager.h"
40 #include "ObjectAccessor.h"
41 #include "SharedDefines.h"
42 #include "Pet.h"
43 #include "GameObject.h"
44 #include "GossipDef.h"
45 #include "Creature.h"
46 #include "Totem.h"
47 #include "CreatureAI.h"
48 #include "BattleGround.h"
49 #include "BattleGroundEY.h"
50 #include "BattleGroundWS.h"
51 #include "VMapFactory.h"
52 #include "Language.h"
53 #include "SocialMgr.h"
54 #include "Util.h"
55 #include "TemporarySummon.h"
57 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
59 &Spell::EffectNULL, // 0
60 &Spell::EffectInstaKill, // 1 SPELL_EFFECT_INSTAKILL
61 &Spell::EffectSchoolDMG, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
62 &Spell::EffectDummy, // 3 SPELL_EFFECT_DUMMY
63 &Spell::EffectUnused, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
64 &Spell::EffectTeleportUnits, // 5 SPELL_EFFECT_TELEPORT_UNITS
65 &Spell::EffectApplyAura, // 6 SPELL_EFFECT_APPLY_AURA
66 &Spell::EffectEnvirinmentalDMG, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
67 &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
68 &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
69 &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL
70 &Spell::EffectUnused, // 11 SPELL_EFFECT_BIND
71 &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL
72 &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
73 &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
74 &Spell::EffectUnused, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
75 &Spell::EffectQuestComplete, // 16 SPELL_EFFECT_QUEST_COMPLETE
76 &Spell::EffectWeaponDmg, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
77 &Spell::EffectResurrect, // 18 SPELL_EFFECT_RESURRECT
78 &Spell::EffectAddExtraAttacks, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
79 &Spell::EffectUnused, // 20 SPELL_EFFECT_DODGE one spell: Dodge
80 &Spell::EffectUnused, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
81 &Spell::EffectParry, // 22 SPELL_EFFECT_PARRY
82 &Spell::EffectBlock, // 23 SPELL_EFFECT_BLOCK one spell: Block
83 &Spell::EffectCreateItem, // 24 SPELL_EFFECT_CREATE_ITEM
84 &Spell::EffectUnused, // 25 SPELL_EFFECT_WEAPON
85 &Spell::EffectUnused, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
86 &Spell::EffectPersistentAA, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
87 &Spell::EffectSummonType, // 28 SPELL_EFFECT_SUMMON
88 &Spell::EffectMomentMove, // 29 SPELL_EFFECT_LEAP
89 &Spell::EffectEnergize, // 30 SPELL_EFFECT_ENERGIZE
90 &Spell::EffectWeaponDmg, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
91 &Spell::EffectTriggerMissileSpell, // 32 SPELL_EFFECT_TRIGGER_MISSILE
92 &Spell::EffectOpenLock, // 33 SPELL_EFFECT_OPEN_LOCK
93 &Spell::EffectSummonChangeItem, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
94 &Spell::EffectApplyAreaAura, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
95 &Spell::EffectLearnSpell, // 36 SPELL_EFFECT_LEARN_SPELL
96 &Spell::EffectUnused, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
97 &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
98 &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
99 &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
100 &Spell::EffectSummonWild, // 41 SPELL_EFFECT_SUMMON_WILD
101 &Spell::EffectSummonGuardian, // 42 SPELL_EFFECT_SUMMON_GUARDIAN
102 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
103 &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
104 &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
105 &Spell::EffectNULL, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
106 &Spell::EffectTradeSkill, // 47 SPELL_EFFECT_TRADE_SKILL
107 &Spell::EffectUnused, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
108 &Spell::EffectUnused, // 49 SPELL_EFFECT_DETECT one spell: Detect
109 &Spell::EffectTransmitted, // 50 SPELL_EFFECT_TRANS_DOOR
110 &Spell::EffectUnused, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
111 &Spell::EffectUnused, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
112 &Spell::EffectEnchantItemPerm, // 53 SPELL_EFFECT_ENCHANT_ITEM
113 &Spell::EffectEnchantItemTmp, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
114 &Spell::EffectTameCreature, // 55 SPELL_EFFECT_TAMECREATURE
115 &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET
116 &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL
117 &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE
118 &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
119 &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY
120 &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT
121 &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
122 &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
123 &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
124 &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
125 &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused
126 &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
127 &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
128 &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
129 &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
130 &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
131 &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
132 &Spell::EffectSummonGuardian, // 73 SPELL_EFFECT_SUMMON_POSSESSED
133 &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
134 &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
135 &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
136 &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
137 &Spell::EffectUnused, // 78 SPELL_EFFECT_ATTACK
138 &Spell::EffectSanctuary, // 79 SPELL_EFFECT_SANCTUARY
139 &Spell::EffectAddComboPoints, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
140 &Spell::EffectUnused, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
141 &Spell::EffectNULL, // 82 SPELL_EFFECT_BIND_SIGHT
142 &Spell::EffectDuel, // 83 SPELL_EFFECT_DUEL
143 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
144 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
145 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
146 &Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
147 &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
148 &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
149 &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
150 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
151 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
152 &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
153 &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
154 &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
155 &Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
156 &Spell::EffectSummonCritter, // 97 SPELL_EFFECT_SUMMON_CRITTER
157 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
158 &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
159 &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
160 &Spell::EffectFeedPet, //101 SPELL_EFFECT_FEED_PET
161 &Spell::EffectDismissPet, //102 SPELL_EFFECT_DISMISS_PET
162 &Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
163 &Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
164 &Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
165 &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
166 &Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
167 &Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
168 &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET
169 &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
170 &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE
171 &Spell::EffectSummonDemon, //112 SPELL_EFFECT_SUMMON_DEMON
172 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW
173 &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME
174 &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
175 &Spell::EffectSkinPlayerCorpse, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
176 &Spell::EffectSpiritHeal, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
177 &Spell::EffectSkill, //118 SPELL_EFFECT_SKILL professions and more
178 &Spell::EffectApplyAreaAura, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
179 &Spell::EffectUnused, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
180 &Spell::EffectWeaponDmg, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
181 &Spell::EffectUnused, //122 SPELL_EFFECT_122 unused
182 &Spell::EffectSendTaxi, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
183 &Spell::EffectPlayerPull, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
184 &Spell::EffectModifyThreatPercent, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
185 &Spell::EffectStealBeneficialBuff, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
186 &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
187 &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
188 &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
189 &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
190 &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
191 &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value
192 &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
193 &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
194 &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
195 &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
196 &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
197 &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
198 &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused
199 &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
200 &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
201 &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
202 &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
203 &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
204 &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
205 &Spell::EffectUnused, //146 SPELL_EFFECT_146 unused
206 &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
207 &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
208 &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
209 &Spell::EffectUnused, //150 SPELL_EFFECT_150 unused
210 &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
211 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
212 &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
213 &Spell::EffectNULL, //154 unused
214 &Spell::EffectNULL, //155 Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
215 &Spell::EffectNULL, //156 Add Socket
216 &Spell::EffectNULL, //157 create/learn random item/spell for profession
217 &Spell::EffectMilling, //158 milling
218 &Spell::EffectNULL //159 allow rename pet once again
221 void Spell::EffectNULL(uint32 /*i*/)
223 sLog.outDebug("WORLD: Spell Effect DUMMY");
226 void Spell::EffectUnused(uint32 /*i*/)
228 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
231 void Spell::EffectResurrectNew(uint32 i)
233 if(!unitTarget || unitTarget->isAlive())
234 return;
236 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
237 return;
239 if(!unitTarget->IsInWorld())
240 return;
242 Player* pTarget = ((Player*)unitTarget);
244 if(pTarget->isRessurectRequested()) // already have one active request
245 return;
247 uint32 health = damage;
248 uint32 mana = m_spellInfo->EffectMiscValue[i];
249 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
250 SendResurrectRequest(pTarget);
253 void Spell::EffectInstaKill(uint32 /*i*/)
255 if( !unitTarget || !unitTarget->isAlive() )
256 return;
258 // Demonic Sacrifice
259 if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
261 uint32 entry = unitTarget->GetEntry();
262 uint32 spellID;
263 switch(entry)
265 case 416: spellID=18789; break; //imp
266 case 417: spellID=18792; break; //fellhunter
267 case 1860: spellID=18790; break; //void
268 case 1863: spellID=18791; break; //succubus
269 case 17252: spellID=35701; break; //fellguard
270 default:
271 sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
272 return;
275 m_caster->CastSpell(m_caster,spellID,true);
278 if(m_caster==unitTarget) // prevent interrupt message
279 finish();
281 uint32 health = unitTarget->GetHealth();
282 m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
285 void Spell::EffectEnvirinmentalDMG(uint32 i)
287 uint32 absorb = 0;
288 uint32 resist = 0;
290 // Note: this hack with damage replace required until GO casting not implemented
291 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
292 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
293 damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i];
295 m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
297 m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
298 if(m_caster->GetTypeId() == TYPEID_PLAYER)
299 ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage);
302 void Spell::EffectSchoolDMG(uint32 effect_idx)
304 if( unitTarget && unitTarget->isAlive())
306 switch(m_spellInfo->SpellFamilyName)
308 case SPELLFAMILY_GENERIC:
310 //Gore
311 if(m_spellInfo->SpellIconID == 2269 )
313 damage+= rand()%2 ? damage : 0;
316 switch(m_spellInfo->Id) // better way to check unknown
318 // Meteor like spells (divided damage to targets)
319 case 24340: case 26558: case 28884: // Meteor
320 case 36837: case 38903: case 41276: // Meteor
321 case 26789: // Shard of the Fallen Star
322 case 31436: // Malevolent Cleave
323 case 35181: // Dive Bomb
324 case 40810: case 43267: case 43268: // Saber Lash
325 case 42384: // Brutal Swipe
326 case 45150: // Meteor Slash
328 uint32 count = 0;
329 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
330 if(ihit->effectMask & (1<<effect_idx))
331 ++count;
333 damage /= count; // divide to all targets
334 break;
336 // percent from health with min
337 case 25599: // Thundercrash
339 damage = unitTarget->GetHealth() / 2;
340 if(damage < 200)
341 damage = 200;
342 break;
345 break;
348 case SPELLFAMILY_MAGE:
350 // Arcane Blast
351 if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
353 m_caster->CastSpell(m_caster,36032,true);
355 break;
357 case SPELLFAMILY_WARRIOR:
359 // Bloodthirst
360 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
362 damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
364 // Shield Slam
365 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
366 damage += int32(m_caster->GetShieldBlockValue());
367 // Victory Rush
368 else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
370 damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
371 m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
373 break;
375 case SPELLFAMILY_WARLOCK:
377 // Incinerate Rank 1 & 2
378 if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
380 // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
381 if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
382 damage += int32(damage*0.25);
384 break;
386 case SPELLFAMILY_DRUID:
388 // Ferocious Bite
389 if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
391 // converts each extra point of energy into ($f1+$AP/630) additional damage
392 float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx];
393 damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
394 m_caster->SetPower(POWER_ENERGY,0);
396 // Rake
397 else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
399 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
401 // Swipe
402 else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
404 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
406 // Starfire
407 else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL )
409 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
410 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
412 // Starfire Bonus (caster)
413 switch((*i)->GetModifier()->m_miscvalue)
415 case 5481: // Nordrassil Regalia - bonus
417 Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
418 for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr)
420 // Moonfire or Insect Swarm (target debuff from any casters)
421 if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL )
423 int32 mod = (*i)->GetModifier()->m_amount;
424 damage += damage*mod/100;
425 break;
428 break;
430 case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura
432 damage += (*i)->GetModifier()->m_amount;
433 break;
438 //Mangle Bonus for the initial damage of Lacerate and Rake
439 if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
440 (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
442 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
443 for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
444 if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
446 damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
447 break;
450 break;
452 case SPELLFAMILY_ROGUE:
454 // Envenom
455 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
457 // consume from stack dozes not more that have combo-points
458 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
460 // count consumed deadly poison doses at target
461 uint32 doses = 0;
463 // remove consumed poison doses
464 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
465 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;)
467 // Deadly poison (only attacker applied)
468 if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) &&
469 (*itr)->GetSpellProto()->SpellVisual[0]==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() )
471 --combo;
472 ++doses;
474 unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex());
476 itr = auras.begin();
478 else
479 ++itr;
482 damage *= doses;
483 damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
485 // Eviscerate and Envenom Bonus Damage (item set effect)
486 if(m_caster->GetDummyAura(37169))
487 damage += ((Player*)m_caster)->GetComboPoints()*40;
490 // Eviscerate
491 else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
493 if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
495 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f);
497 // Eviscerate and Envenom Bonus Damage (item set effect)
498 if(m_caster->GetDummyAura(37169))
499 damage += combo*40;
502 break;
504 case SPELLFAMILY_HUNTER:
506 // Mongoose Bite
507 if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
509 damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2);
511 // Arcane Shot
512 else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
514 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15);
516 // Steady Shot
517 else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
519 int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
520 damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
522 //Explosive Trap Effect
523 else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
525 damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1);
527 break;
529 case SPELLFAMILY_PALADIN:
531 //Judgement of Vengeance
532 if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
534 uint32 stacks = 0;
535 Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
536 for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
537 if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
538 ++stacks;
539 if(!stacks)
540 //No damage if the target isn't affected by this
541 damage = -1;
542 else
543 damage *= stacks;
545 break;
549 if(damage >= 0)
551 uint32 finalDamage;
552 if(m_originalCaster) // m_caster only passive source of cast
553 finalDamage = m_originalCaster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
554 else
555 finalDamage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
557 // post effects
558 switch(m_spellInfo->SpellFamilyName)
560 case SPELLFAMILY_WARRIOR:
562 // Bloodthirst
563 if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
565 uint32 BTAura = 0;
566 switch(m_spellInfo->Id)
568 case 23881: BTAura = 23885; break;
569 case 23892: BTAura = 23886; break;
570 case 23893: BTAura = 23887; break;
571 case 23894: BTAura = 23888; break;
572 case 25251: BTAura = 25252; break;
573 case 30335: BTAura = 30339; break;
574 default:
575 sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id);
576 break;
579 if (BTAura)
580 m_caster->CastSpell(m_caster,BTAura,true);
582 break;
584 case SPELLFAMILY_PRIEST:
586 // Shadow Word: Death
587 if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) && unitTarget->isAlive())
588 // deals damage equal to damage done to caster if victim is not killed
589 m_caster->SpellNonMeleeDamageLog( m_caster, m_spellInfo->Id, finalDamage, m_IsTriggeredSpell, false);
591 break;
593 case SPELLFAMILY_PALADIN:
595 // Judgement of Blood
596 if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL) && m_spellInfo->SpellIconID==153)
598 int32 damagePoint = finalDamage * 33 / 100;
599 m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
601 break;
608 void Spell::EffectDummy(uint32 i)
610 if(!unitTarget && !gameObjTarget && !itemTarget)
611 return;
613 // selection by spell family
614 switch(m_spellInfo->SpellFamilyName)
616 case SPELLFAMILY_GENERIC:
618 switch(m_spellInfo->Id )
620 case 8063: // Deviate Fish
622 if(m_caster->GetTypeId() != TYPEID_PLAYER)
623 return;
625 uint32 spell_id = 0;
626 switch(urand(1,5))
628 case 1: spell_id = 8064; break; // Sleepy
629 case 2: spell_id = 8065; break; // Invigorate
630 case 3: spell_id = 8066; break; // Shrink
631 case 4: spell_id = 8067; break; // Party Time!
632 case 5: spell_id = 8068; break; // Healthy Spirit
634 m_caster->CastSpell(m_caster,spell_id,true,NULL);
635 return;
637 case 8213: // Savory Deviate Delight
639 if(m_caster->GetTypeId() != TYPEID_PLAYER)
640 return;
642 uint32 spell_id = 0;
643 switch(urand(1,2))
645 // Flip Out - ninja
646 case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
647 // Yaaarrrr - pirate
648 case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
650 m_caster->CastSpell(m_caster,spell_id,true,NULL);
651 return;
653 case 8593: // Symbol of life (restore creature to life)
654 case 31225: // Shimmering Vessel (restore creature to life)
656 if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
657 return;
658 ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
659 return;
661 case 12162: // Deep wounds
662 case 12850: // (now good common check for this spells)
663 case 12868:
665 if(!unitTarget)
666 return;
668 float damage;
669 // DW should benefit of attack power, damage percent mods etc.
670 // TODO: check if using offhand damage is correct and if it should be divided by 2
671 if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
672 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
673 else
674 damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
676 switch (m_spellInfo->Id)
678 case 12850: damage *= 0.2f; break;
679 case 12162: damage *= 0.4f; break;
680 case 12868: damage *= 0.6f; break;
681 default:
682 sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
683 return;
686 int32 deepWoundsDotBasePoints0 = int32(damage / 4);
687 m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
688 return;
690 case 12975: //Last Stand
692 int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
693 m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
694 return;
696 case 13120: // net-o-matic
698 if(!unitTarget)
699 return;
701 uint32 spell_id = 0;
703 uint32 roll = urand(0, 99);
705 if(roll < 2) // 2% for 30 sec self root (off-like chance unknown)
706 spell_id = 16566;
707 else if(roll < 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
708 spell_id = 13119;
709 else // normal root
710 spell_id = 13099;
712 m_caster->CastSpell(unitTarget,spell_id,true,NULL);
713 return;
715 case 13567: // Dummy Trigger
717 // can be used for different aura triggering, so select by aura
718 if(!m_triggeredByAuraSpell || !unitTarget)
719 return;
721 switch(m_triggeredByAuraSpell->Id)
723 case 26467: // Persistent Shield
724 m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
725 break;
726 default:
727 sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
728 break;
730 return;
732 case 14185: // Preparation Rogue
734 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
735 return;
737 //immediately finishes the cooldown on certain Rogue abilities
738 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
739 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
741 uint32 classspell = itr->first;
742 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
744 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL))
746 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
748 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
749 data << uint32(classspell);
750 data << uint64(m_caster->GetGUID());
751 ((Player*)m_caster)->GetSession()->SendPacket(&data);
754 return;
756 case 15998: // Capture Worg Pup
757 case 29435: // Capture Female Kaliri Hatchling
759 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
760 return;
762 Creature* creatureTarget = (Creature*)unitTarget;
763 creatureTarget->setDeathState(JUST_DIED);
764 creatureTarget->RemoveCorpse();
765 creatureTarget->SetHealth(0); // just for nice GM-mode view
766 return;
768 case 16589: // Noggenfogger Elixir
770 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
771 return;
773 uint32 spell_id = 0;
774 switch(urand(1,3))
776 case 1: spell_id = 16595; break;
777 case 2: spell_id = 16593; break;
778 default:spell_id = 16591; break;
781 m_caster->CastSpell(m_caster,spell_id,true,NULL);
782 return;
784 case 17251: // Spirit Healer Res
786 if(!unitTarget || !m_originalCaster)
787 return;
789 if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
791 WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
792 data << unitTarget->GetGUID();
793 ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
795 return;
797 case 17271: // Test Fetid Skull
799 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
800 return;
802 uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
804 m_caster->CastSpell(m_caster,spell_id,true,NULL);
805 return;
807 case 20577: // Cannibalize
808 if (unitTarget)
809 m_caster->CastSpell(m_caster,20578,false,NULL);
810 return;
811 case 23019: // Crystal Prison Dummy DND
813 if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
814 return;
816 Creature* creatureTarget = (Creature*)unitTarget;
817 if(creatureTarget->isPet())
818 return;
820 creatureTarget->setDeathState(JUST_DIED);
821 creatureTarget->RemoveCorpse();
822 creatureTarget->SetHealth(0); // just for nice GM-mode view
824 GameObject* pGameObj = new GameObject;
826 Map *map = creatureTarget->GetMap();
828 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map,
829 creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(),
830 creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1) )
832 delete pGameObj;
833 return;
836 pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime()-time(NULL));
837 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
838 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
839 pGameObj->SetSpellId(m_spellInfo->Id);
841 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy\n");
842 map->Add(pGameObj);
844 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
845 data << uint64(pGameObj->GetGUID());
846 m_caster->SendMessageToSet(&data,true);
848 return;
850 case 23074: // Arc. Dragonling
851 if (!m_CastItem) return;
852 m_caster->CastSpell(m_caster,19804,true,m_CastItem);
853 return;
854 case 23075: // Mithril Mechanical Dragonling
855 if (!m_CastItem) return;
856 m_caster->CastSpell(m_caster,12749,true,m_CastItem);
857 return;
858 case 23076: // Mechanical Dragonling
859 if (!m_CastItem) return;
860 m_caster->CastSpell(m_caster,4073,true,m_CastItem);
861 return;
862 case 23133: // Gnomish Battle Chicken
863 if (!m_CastItem) return;
864 m_caster->CastSpell(m_caster,13166,true,m_CastItem);
865 return;
866 case 23448: // Ultrasafe Transporter: Gadgetzan - backfires
868 int32 r = irand(0, 119);
869 if ( r < 20 ) // 1/6 polymorph
870 m_caster->CastSpell(m_caster,23444,true);
871 else if ( r < 100 ) // 4/6 evil twin
872 m_caster->CastSpell(m_caster,23445,true);
873 else // 1/6 miss the target
874 m_caster->CastSpell(m_caster,36902,true);
875 return;
877 case 23453: // Ultrasafe Transporter: Gadgetzan
878 if ( roll_chance_i(50) ) // success
879 m_caster->CastSpell(m_caster,23441,true);
880 else // failure
881 m_caster->CastSpell(m_caster,23446,true);
882 return;
883 case 23645: // Hourglass Sand
884 m_caster->RemoveAurasDueToSpell(23170);
885 return;
886 case 23725: // Gift of Life (warrior bwl trinket)
887 m_caster->CastSpell(m_caster,23782,true);
888 m_caster->CastSpell(m_caster,23783,true);
889 return;
890 case 25860: // Reindeer Transformation
892 if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
893 return;
895 float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT);
896 float speed = m_caster->GetSpeedRate(MOVE_RUN);
898 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
900 //5 different spells used depending on mounted speed and if mount can fly or not
901 if (flyspeed >= 4.1f)
902 m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
903 else if (flyspeed >= 3.8f)
904 m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
905 else if (flyspeed >= 1.6f)
906 m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
907 else if (speed >= 2.0f)
908 m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
909 else
910 m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
912 return;
914 //case 26074: // Holiday Cheer
915 // return; -- implemented at client side
916 case 28006: // Arcane Cloaking
918 if( unitTarget->GetTypeId() == TYPEID_PLAYER )
919 m_caster->CastSpell(unitTarget,29294,true);
920 return;
922 case 28730: // Arcane Torrent (Mana)
924 int32 count = 0;
925 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
926 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
927 if ((*i)->GetId() == 28734)
928 ++count;
929 if (count)
931 m_caster->RemoveAurasDueToSpell(28734);
932 int32 bp = damage * count;
933 m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
935 return;
937 case 29200: // Purify Helboar Meat
939 if( m_caster->GetTypeId() != TYPEID_PLAYER )
940 return;
942 uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
944 m_caster->CastSpell(m_caster,spell_id,true,NULL);
945 return;
947 case 29858: // Soulshatter
948 if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
949 m_caster->CastSpell(unitTarget,32835,true);
950 return;
951 case 30458: // Nigh Invulnerability
952 if (!m_CastItem) return;
953 if(roll_chance_i(86)) // success
954 m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
955 else // backfire in 14% casts
956 m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
957 return;
958 case 30507: // Poultryizer
959 if (!m_CastItem) return;
960 if(roll_chance_i(80)) // success
961 m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
962 else // backfire 20%
963 m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
964 return;
965 case 33060: // Make a Wish
967 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
968 return;
970 uint32 spell_id = 0;
972 switch(urand(1,5))
974 case 1: spell_id = 33053; break;
975 case 2: spell_id = 33057; break;
976 case 3: spell_id = 33059; break;
977 case 4: spell_id = 33062; break;
978 case 5: spell_id = 33064; break;
981 m_caster->CastSpell(m_caster,spell_id,true,NULL);
982 return;
984 case 35745:
986 uint32 spell_id;
987 switch(m_caster->GetAreaId())
989 case 3900: spell_id = 35743; break;
990 case 3742: spell_id = 35744; break;
991 default: return;
994 m_caster->CastSpell(m_caster,spell_id,true);
995 return;
997 case 37674: // Chaos Blast
998 if(unitTarget)
999 m_caster->CastSpell(unitTarget,37675,true);
1000 return;
1001 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1003 // selecting one from Bloodstained Fortune item
1004 uint32 newitemid;
1005 switch(urand(1,20))
1007 case 1: newitemid = 32688; break;
1008 case 2: newitemid = 32689; break;
1009 case 3: newitemid = 32690; break;
1010 case 4: newitemid = 32691; break;
1011 case 5: newitemid = 32692; break;
1012 case 6: newitemid = 32693; break;
1013 case 7: newitemid = 32700; break;
1014 case 8: newitemid = 32701; break;
1015 case 9: newitemid = 32702; break;
1016 case 10: newitemid = 32703; break;
1017 case 11: newitemid = 32704; break;
1018 case 12: newitemid = 32705; break;
1019 case 13: newitemid = 32706; break;
1020 case 14: newitemid = 32707; break;
1021 case 15: newitemid = 32708; break;
1022 case 16: newitemid = 32709; break;
1023 case 17: newitemid = 32710; break;
1024 case 18: newitemid = 32711; break;
1025 case 19: newitemid = 32712; break;
1026 case 20: newitemid = 32713; break;
1027 default:
1028 return;
1031 DoCreateItem(i,newitemid);
1032 return;
1034 // Demon Broiled Surprise
1035 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1036 case 43723:
1038 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1039 return;
1041 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1042 return;
1045 case 44875: // Complete Raptor Capture
1047 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1048 return;
1050 Creature* creatureTarget = (Creature*)unitTarget;
1052 creatureTarget->setDeathState(JUST_DIED);
1053 creatureTarget->RemoveCorpse();
1054 creatureTarget->SetHealth(0); // just for nice GM-mode view
1056 //cast spell Raptor Capture Credit
1057 m_caster->CastSpell(m_caster,42337,true,NULL);
1058 return;
1060 case 37573: //Temporal Phase Modulator
1062 if(!unitTarget)
1063 return;
1065 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1066 if(!tempSummon)
1067 return;
1069 uint32 health = tempSummon->GetHealth();
1070 const uint32 entry_list[6] = {21821, 21820, 21817};
1072 float x = tempSummon->GetPositionX();
1073 float y = tempSummon->GetPositionY();
1074 float z = tempSummon->GetPositionZ();
1075 float o = tempSummon->GetOrientation();
1077 tempSummon->UnSummon();
1079 Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1080 if (!pCreature)
1081 return;
1083 pCreature->SetHealth(health);
1085 if(pCreature->AI())
1086 pCreature->AI()->AttackStart(m_caster);
1088 return;
1090 case 34665: //Administer Antidote
1092 if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1093 return;
1095 if(!unitTarget)
1096 return;
1098 TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1099 if(!tempSummon)
1100 return;
1102 uint32 health = tempSummon->GetHealth();
1104 float x = tempSummon->GetPositionX();
1105 float y = tempSummon->GetPositionY();
1106 float z = tempSummon->GetPositionZ();
1107 float o = tempSummon->GetOrientation();
1108 tempSummon->UnSummon();
1110 Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1111 if (!pCreature)
1112 return;
1114 pCreature->SetHealth(health);
1115 ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
1117 if (pCreature->AI())
1118 pCreature->AI()->AttackStart(m_caster);
1120 return;
1122 case 44997: // Converting Sentry
1124 //Converted Sentry Credit
1125 m_caster->CastSpell(m_caster, 45009, true);
1126 return;
1128 case 45030: // Impale Emissary
1130 // Emissary of Hate Credit
1131 m_caster->CastSpell(m_caster, 45088, true);
1132 return;
1134 case 50243: // Teach Language
1136 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1137 return;
1139 // spell has a 1/3 chance to trigger one of the below
1140 if(roll_chance_i(66))
1141 return;
1142 if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1144 // 1000001 - gnomish binary
1145 m_caster->CastSpell(m_caster, 50242, true);
1147 else
1149 // 01001000 - goblin binary
1150 m_caster->CastSpell(m_caster, 50246, true);
1153 return;
1155 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1157 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1158 return;
1160 if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1161 bg->EventPlayerDroppedFlag((Player*)m_caster);
1163 m_caster->CastSpell(m_caster, 30452, true, NULL);
1164 return;
1168 //All IconID Check in there
1169 switch(m_spellInfo->SpellIconID)
1171 // Berserking (troll racial traits)
1172 case 1661:
1174 uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1175 int32 melee_mod = 10;
1176 if (healthPerc <= 40)
1177 melee_mod = 30;
1178 if (healthPerc < 100 && healthPerc > 40)
1179 melee_mod = 10+(100-healthPerc)/3;
1181 int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1182 int32 hasteModBasePoints1 = (5-melee_mod);
1183 int32 hasteModBasePoints2 = 5;
1185 // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1186 m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1187 m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1188 return;
1191 break;
1193 case SPELLFAMILY_MAGE:
1194 switch(m_spellInfo->Id )
1196 case 11958: // Cold Snap
1198 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1199 return;
1201 // immediately finishes the cooldown on Frost spells
1202 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1203 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1205 if (itr->second->state == PLAYERSPELL_REMOVED)
1206 continue;
1208 uint32 classspell = itr->first;
1209 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1211 if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1212 (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1213 spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1215 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1217 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1218 data << uint32(classspell);
1219 data << uint64(m_caster->GetGUID());
1220 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1223 return;
1225 case 32826:
1227 if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1229 //Polymorph Cast Visual Rank 1
1230 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1231 unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true);
1233 return;
1236 break;
1237 case SPELLFAMILY_WARRIOR:
1238 // Charge
1239 if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
1241 int32 chargeBasePoints0 = damage;
1242 m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1243 return;
1245 // Execute
1246 if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1248 if(!unitTarget)
1249 return;
1251 int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]);
1252 m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1253 m_caster->SetPower(POWER_RAGE,0);
1254 return;
1256 if(m_spellInfo->Id==21977) //Warrior's Wrath
1258 if(!unitTarget)
1259 return;
1261 m_caster->CastSpell(unitTarget,21887,true); // spell mod
1262 return;
1264 break;
1265 case SPELLFAMILY_WARLOCK:
1266 //Life Tap (only it have this with dummy effect)
1267 if (m_spellInfo->SpellFamilyFlags == 0x40000)
1269 float cost = m_currentBasePoints[0]+1;
1271 if(Player* modOwner = m_caster->GetSpellModOwner())
1272 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this);
1274 int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE);
1276 if(int32(m_caster->GetHealth()) > dmg)
1278 // Shouldn't Appear in Combat Log
1279 m_caster->ModifyHealth(-dmg);
1281 int32 mana = dmg;
1283 Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1284 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1286 // only Imp. Life Tap have this in combination with dummy aura
1287 if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1288 mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1291 m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL);
1293 // Mana Feed
1294 int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster);
1295 manaFeedVal = manaFeedVal * mana / 100;
1296 if(manaFeedVal > 0)
1297 m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL);
1299 else
1300 SendCastResult(SPELL_FAILED_FIZZLE);
1301 return;
1303 break;
1304 case SPELLFAMILY_PRIEST:
1305 switch(m_spellInfo->Id )
1307 case 28598: // Touch of Weakness triggered spell
1309 if(!unitTarget || !m_triggeredByAuraSpell)
1310 return;
1312 uint32 spellid = 0;
1313 switch(m_triggeredByAuraSpell->Id)
1315 case 2652: spellid = 2943; break; // Rank 1
1316 case 19261: spellid = 19249; break; // Rank 2
1317 case 19262: spellid = 19251; break; // Rank 3
1318 case 19264: spellid = 19252; break; // Rank 4
1319 case 19265: spellid = 19253; break; // Rank 5
1320 case 19266: spellid = 19254; break; // Rank 6
1321 case 25461: spellid = 25460; break; // Rank 7
1322 default:
1323 sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id);
1324 return;
1326 m_caster->CastSpell(unitTarget, spellid, true, NULL);
1327 return;
1330 break;
1331 case SPELLFAMILY_DRUID:
1332 switch(m_spellInfo->Id )
1334 case 5420: // Tree of Life passive
1336 // Tree of Life area effect
1337 int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4);
1338 m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL);
1339 return;
1342 break;
1343 case SPELLFAMILY_ROGUE:
1344 switch(m_spellInfo->Id )
1346 case 31231: // Cheat Death
1348 m_caster->CastSpell(m_caster,45182,true);
1349 return;
1351 case 5938: // Shiv
1353 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1354 return;
1356 Player *pCaster = ((Player*)m_caster);
1358 Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1359 if(!item)
1360 return;
1362 // all poison enchantments is temporary
1363 uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1364 if(!enchant_id)
1365 return;
1367 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1368 if(!pEnchant)
1369 return;
1371 for (int s=0;s<3;s++)
1373 if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1374 continue;
1376 SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1377 if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1378 continue;
1380 m_caster->CastSpell(unitTarget, combatEntry, true, item);
1383 m_caster->CastSpell(unitTarget, 5940, true);
1384 return;
1387 break;
1388 case SPELLFAMILY_HUNTER:
1389 // Steady Shot
1390 if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1392 if( !unitTarget || !unitTarget->isAlive())
1393 return;
1395 bool found = false;
1397 // check dazed affect
1398 Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1399 for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1401 if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1403 found = true;
1404 break;
1408 if(found)
1409 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
1410 return;
1412 // Kill command
1413 if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL)
1415 if(m_caster->getClass()!=CLASS_HUNTER)
1416 return;
1418 // clear hunter crit aura state
1419 m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false);
1421 // additional damage from pet to pet target
1422 Pet* pet = m_caster->GetPet();
1423 if(!pet || !pet->getVictim())
1424 return;
1426 uint32 spell_id = 0;
1427 switch (m_spellInfo->Id)
1429 case 34026: spell_id = 34027; break; // rank 1
1430 default:
1431 sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id);
1432 return;
1435 pet->CastSpell(pet->getVictim(), spell_id, true);
1436 return;
1439 switch(m_spellInfo->Id)
1441 case 23989: //Readiness talent
1443 if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1444 return;
1446 //immediately finishes the cooldown for hunter abilities
1447 const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1448 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1450 uint32 classspell = itr->first;
1451 SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1453 if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1455 ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1457 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1458 data << uint32(classspell);
1459 data << uint64(m_caster->GetGUID());
1460 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1463 return;
1465 case 37506: // Scatter Shot
1467 if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1468 return;
1470 // break Auto Shot and autohit
1471 m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1472 m_caster->AttackStop();
1473 ((Player*)m_caster)->SendAttackSwingCancelAttack();
1474 return;
1477 break;
1478 case SPELLFAMILY_PALADIN:
1479 switch(m_spellInfo->SpellIconID)
1481 case 156: // Holy Shock
1483 if(!unitTarget)
1484 return;
1486 int hurt = 0;
1487 int heal = 0;
1489 switch(m_spellInfo->Id)
1491 case 20473: hurt = 25912; heal = 25914; break;
1492 case 20929: hurt = 25911; heal = 25913; break;
1493 case 20930: hurt = 25902; heal = 25903; break;
1494 case 27174: hurt = 27176; heal = 27175; break;
1495 case 33072: hurt = 33073; heal = 33074; break;
1496 default:
1497 sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1498 return;
1501 if(m_caster->IsFriendlyTo(unitTarget))
1502 m_caster->CastSpell(unitTarget, heal, true, 0);
1503 else
1504 m_caster->CastSpell(unitTarget, hurt, true, 0);
1506 return;
1508 case 561: // Judgement of command
1510 if(!unitTarget)
1511 return;
1513 uint32 spell_id = m_currentBasePoints[i]+1;
1514 SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1515 if(!spell_proto)
1516 return;
1518 if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1520 // decreased damage (/2) for non-stunned target.
1521 SpellModifier *mod = new SpellModifier;
1522 mod->op = SPELLMOD_DAMAGE;
1523 mod->value = -50;
1524 mod->type = SPELLMOD_PCT;
1525 mod->spellId = m_spellInfo->Id;
1526 mod->effectId = i;
1527 mod->lastAffected = NULL;
1528 mod->mask = 0x0000020000000000LL;
1529 mod->charges = 0;
1531 ((Player*)m_caster)->AddSpellMod(mod, true);
1532 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1533 // mod deleted
1534 ((Player*)m_caster)->AddSpellMod(mod, false);
1536 else
1537 m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1539 return;
1543 switch(m_spellInfo->Id)
1545 case 31789: // Righteous Defense (step 1)
1547 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1549 // non-standard cast requirement check
1550 if (!unitTarget || unitTarget->getAttackers().empty())
1552 // clear cooldown at fail
1553 if(m_caster->GetTypeId()==TYPEID_PLAYER)
1555 ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1557 WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1558 data << uint32(m_spellInfo->Id);
1559 data << uint64(m_caster->GetGUID());
1560 ((Player*)m_caster)->GetSession()->SendPacket(&data);
1563 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1564 return;
1567 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1568 // Clear targets for eff 1
1569 for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1570 ihit->effectMask &= ~(1<<1);
1572 // not empty (checked)
1573 Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1575 // chance to be selected from list
1576 float chance = 100.0f/attackers.size();
1577 uint32 count=0;
1578 for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1580 if(!roll_chance_f(chance))
1581 continue;
1582 ++count;
1583 AddUnitTarget((*aItr), 1);
1586 // now let next effect cast spell at each target.
1587 return;
1589 case 37877: // Blessing of Faith
1591 if(!unitTarget)
1592 return;
1594 uint32 spell_id = 0;
1595 switch(unitTarget->getClass())
1597 case CLASS_DRUID: spell_id = 37878; break;
1598 case CLASS_PALADIN: spell_id = 37879; break;
1599 case CLASS_PRIEST: spell_id = 37880; break;
1600 case CLASS_SHAMAN: spell_id = 37881; break;
1601 default: return; // ignore for not healing classes
1604 m_caster->CastSpell(m_caster,spell_id,true);
1605 return;
1608 break;
1609 case SPELLFAMILY_SHAMAN:
1610 //Shaman Rockbiter Weapon
1611 if (m_spellInfo->SpellFamilyFlags == 0x400000)
1613 uint32 spell_id = 0;
1614 switch(m_spellInfo->Id)
1616 case 8017: spell_id = 36494; break; // Rank 1
1617 case 8018: spell_id = 36750; break; // Rank 2
1618 case 8019: spell_id = 36755; break; // Rank 3
1619 case 10399: spell_id = 36759; break; // Rank 4
1620 case 16314: spell_id = 36763; break; // Rank 5
1621 case 16315: spell_id = 36766; break; // Rank 6
1622 case 16316: spell_id = 36771; break; // Rank 7
1623 case 25479: spell_id = 36775; break; // Rank 8
1624 case 25485: spell_id = 36499; break; // Rank 9
1625 default:
1626 sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1627 return;
1630 SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1632 if(!spellInfo)
1634 sLog.outError("WORLD: unknown spell id %i\n", spell_id);
1635 return;
1638 if(m_caster->GetTypeId() != TYPEID_PLAYER)
1639 return;
1641 for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1643 if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1645 if(item->IsFitToSpellRequirements(m_spellInfo))
1647 Spell *spell = new Spell(m_caster, spellInfo, true);
1649 // enchanting spell selected by calculated damage-per-sec in enchanting effect
1650 // at calculation applied affect from Elemental Weapons talent
1651 // real enchantment damage-1
1652 spell->m_currentBasePoints[1] = damage-1;
1654 SpellCastTargets targets;
1655 targets.setItemTarget( item );
1656 spell->prepare(&targets);
1660 return;
1663 if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect
1665 if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1666 return;
1668 // Regenerate 6% of Total Mana Every 3 secs
1669 int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100;
1670 m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1671 return;
1674 break;
1677 // pet auras
1678 if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1680 m_caster->AddPetAura(petSpell);
1681 return;
1685 void Spell::EffectTriggerSpellWithValue(uint32 i)
1687 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1689 // normal case
1690 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1692 if(!spellInfo)
1694 sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id);
1695 return;
1698 int32 bp = damage;
1699 m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1702 void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1704 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1705 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1707 if(!spellInfo)
1709 sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1710 return;
1713 finish();
1714 Spell *spell = new Spell(m_caster, spellInfo, true);
1716 SpellCastTargets targets;
1717 targets.setUnitTarget( unitTarget);
1718 spell->prepare(&targets);
1720 m_caster->SetCurrentCastedSpell(spell);
1721 spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1725 void Spell::EffectForceCast(uint32 i)
1727 if( !unitTarget )
1728 return;
1730 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1732 // normal case
1733 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1735 if(!spellInfo)
1737 sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1738 return;
1741 unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1744 void Spell::EffectTriggerSpell(uint32 i)
1746 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1748 // special cases
1749 switch(triggered_spell_id)
1751 // Vanish
1752 case 18461:
1754 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1755 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1756 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1758 // if this spell is given to NPC it must handle rest by it's own AI
1759 if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1760 return;
1762 // get highest rank of the Stealth spell
1763 uint32 spellId = 0;
1764 const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1765 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1767 // only highest rank is shown in spell book, so simply check if shown in spell book
1768 if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1769 continue;
1771 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1772 if (!spellInfo)
1773 continue;
1775 if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1777 spellId = spellInfo->Id;
1778 break;
1782 // no Stealth spell found
1783 if (!spellId)
1784 return;
1786 // reset cooldown on it if needed
1787 if(((Player*)m_caster)->HasSpellCooldown(spellId))
1788 ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1790 m_caster->CastSpell(m_caster, spellId, true);
1791 return;
1793 // just skip
1794 case 23770: // Sayge's Dark Fortune of *
1795 // not exist, common cooldown can be implemented in scripts if need.
1796 return;
1797 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1798 case 29284:
1800 const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1801 if (!spell)
1802 return;
1804 for (int i=0; i < spell->StackAmount; ++i)
1805 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1806 return;
1808 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1809 case 29286:
1811 const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1812 if (!spell)
1813 return;
1815 for (int i=0; i < spell->StackAmount; ++i)
1816 m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1817 return;
1819 // Righteous Defense
1820 case 31980:
1822 m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1823 return;
1825 // Cloak of Shadows
1826 case 35729 :
1828 Unit::AuraMap& Auras = m_caster->GetAuras();
1829 for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1831 // remove all harmful spells on you...
1832 if( // ignore positive and passive auras
1833 !iter->second->IsPositive() && !iter->second->IsPassive() &&
1834 // ignore physical auras
1835 (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 &&
1836 // ignore immunity persistent spells
1837 !( iter->second->GetSpellProto()->AttributesEx & 0x10000 ) )
1839 m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1840 iter = Auras.begin();
1843 return;
1845 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1846 case 41967:
1848 if (Unit *pet = m_caster->GetPet())
1849 pet->CastSpell(pet, 28305, true);
1850 return;
1854 // normal case
1855 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1857 if(!spellInfo)
1859 sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1860 return;
1863 // some triggered spells require specific equipment
1864 if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1866 // main hand weapon required
1867 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1869 Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1871 // skip spell if no weapon in slot or broken
1872 if(!item || item->IsBroken() )
1873 return;
1875 // skip spell if weapon not fit to triggered spell
1876 if(!item->IsFitToSpellRequirements(spellInfo))
1877 return;
1880 // offhand hand weapon required
1881 if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1883 Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1885 // skip spell if no weapon in slot or broken
1886 if(!item || item->IsBroken() )
1887 return;
1889 // skip spell if weapon not fit to triggered spell
1890 if(!item->IsFitToSpellRequirements(spellInfo))
1891 return;
1895 // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1896 bool instant = false;
1897 for(uint32 j = i+1; j < 3; ++j)
1899 if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
1901 instant = true;
1902 break;
1906 if(instant)
1908 if (unitTarget)
1909 m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
1911 else
1912 m_TriggerSpells.push_back(spellInfo);
1915 void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
1917 uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
1919 // normal case
1920 SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1922 if(!spellInfo)
1924 sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
1925 m_spellInfo->Id,effect_idx,triggered_spell_id);
1926 return;
1929 if (m_CastItem)
1930 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1932 Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID );
1934 SpellCastTargets targets;
1935 targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ);
1936 spell->m_CastItem = m_CastItem;
1937 spell->prepare(&targets, NULL);
1940 void Spell::EffectTeleportUnits(uint32 i)
1942 if(!unitTarget || unitTarget->isInFlight())
1943 return;
1945 switch (m_spellInfo->EffectImplicitTargetB[i])
1947 case TARGET_INNKEEPER_COORDINATES:
1949 // Only players can teleport to innkeeper
1950 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
1951 return;
1953 ((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);
1954 return;
1956 case TARGET_TABLE_X_Y_Z_COORDINATES:
1958 // TODO: Only players can teleport?
1959 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
1960 return;
1961 SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
1962 if(!st)
1964 sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id );
1965 return;
1967 ((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);
1968 break;
1970 case TARGET_BEHIND_VICTIM:
1972 // Get selected target for player (or victim for units)
1973 Unit *pTarget = NULL;
1974 if(m_caster->GetTypeId() == TYPEID_PLAYER)
1975 pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
1976 else
1977 pTarget = m_caster->getVictim();
1978 // No target present - return
1979 if (!pTarget)
1980 return;
1981 // Init dest coordinates
1982 uint32 mapid = m_caster->GetMapId();
1983 float x = m_targets.m_destX;
1984 float y = m_targets.m_destY;
1985 float z = m_targets.m_destZ;
1986 float orientation = pTarget->GetOrientation();
1987 // Teleport
1988 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1989 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
1990 else
1992 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
1993 WorldPacket data;
1994 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
1995 unitTarget->SendMessageToSet(&data, false);
1997 return;
1999 default:
2001 // If not exist data for dest location - return
2002 if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2004 sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
2005 return;
2007 // Init dest coordinates
2008 uint32 mapid = m_caster->GetMapId();
2009 float x = m_targets.m_destX;
2010 float y = m_targets.m_destY;
2011 float z = m_targets.m_destZ;
2012 float orientation = unitTarget->GetOrientation();
2013 // Teleport
2014 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
2015 ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
2016 else
2018 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
2019 WorldPacket data;
2020 unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
2021 unitTarget->SendMessageToSet(&data, false);
2023 return;
2027 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2028 switch ( m_spellInfo->Id )
2030 // Dimensional Ripper - Everlook
2031 case 23442:
2033 int32 r = irand(0, 119);
2034 if ( r >= 70 ) // 7/12 success
2036 if ( r < 100 ) // 4/12 evil twin
2037 m_caster->CastSpell(m_caster,23445,true);
2038 else // 1/12 fire
2039 m_caster->CastSpell(m_caster,23449,true);
2041 return;
2043 // Ultrasafe Transporter: Toshley's Station
2044 case 36941:
2046 if ( roll_chance_i(50) ) // 50% success
2048 int32 rand_eff = urand(1,7);
2049 switch ( rand_eff )
2051 case 1:
2052 // soul split - evil
2053 m_caster->CastSpell(m_caster,36900,true);
2054 break;
2055 case 2:
2056 // soul split - good
2057 m_caster->CastSpell(m_caster,36901,true);
2058 break;
2059 case 3:
2060 // Increase the size
2061 m_caster->CastSpell(m_caster,36895,true);
2062 break;
2063 case 4:
2064 // Decrease the size
2065 m_caster->CastSpell(m_caster,36893,true);
2066 break;
2067 case 5:
2068 // Transform
2070 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2071 m_caster->CastSpell(m_caster,36897,true);
2072 else
2073 m_caster->CastSpell(m_caster,36899,true);
2074 break;
2076 case 6:
2077 // chicken
2078 m_caster->CastSpell(m_caster,36940,true);
2079 break;
2080 case 7:
2081 // evil twin
2082 m_caster->CastSpell(m_caster,23445,true);
2083 break;
2086 return;
2088 // Dimensional Ripper - Area 52
2089 case 36890:
2091 if ( roll_chance_i(50) ) // 50% success
2093 int32 rand_eff = urand(1,4);
2094 switch ( rand_eff )
2096 case 1:
2097 // soul split - evil
2098 m_caster->CastSpell(m_caster,36900,true);
2099 break;
2100 case 2:
2101 // soul split - good
2102 m_caster->CastSpell(m_caster,36901,true);
2103 break;
2104 case 3:
2105 // Increase the size
2106 m_caster->CastSpell(m_caster,36895,true);
2107 break;
2108 case 4:
2109 // Transform
2111 if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2112 m_caster->CastSpell(m_caster,36897,true);
2113 else
2114 m_caster->CastSpell(m_caster,36899,true);
2115 break;
2119 return;
2124 void Spell::EffectApplyAura(uint32 i)
2126 if(!unitTarget)
2127 return;
2129 SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE];
2130 for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
2131 if(itr->type == m_spellInfo->EffectApplyAuraName[i])
2132 return;
2134 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2135 if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2136 (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2137 return;
2139 Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2140 if(!caster)
2141 return;
2143 sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2145 Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2147 // Now Reduce spell duration using data received at spell hit
2148 int32 duration = Aur->GetAuraMaxDuration();
2149 unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2150 Aur->setDiminishGroup(m_diminishGroup);
2152 // if Aura removed and deleted, do not continue.
2153 if(duration== 0 && !(Aur->IsPermanent()))
2155 delete Aur;
2156 return;
2159 if(duration != Aur->GetAuraMaxDuration())
2161 Aur->SetAuraMaxDuration(duration);
2162 Aur->SetAuraDuration(duration);
2165 bool added = unitTarget->AddAura(Aur);
2167 // Aura not added and deleted in AddAura call;
2168 if (!added)
2169 return;
2171 // found crash at character loading, broken pointer to Aur...
2172 // Aur was deleted in AddAura()...
2173 if(!Aur)
2174 return;
2176 // TODO Make a way so it works for every related spell!
2177 if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players
2179 uint32 spellId = 0;
2180 if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL)
2181 spellId = 6788; // Weakened Soul
2182 else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE)
2183 spellId = 25771; // Forbearance
2184 else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA)
2185 spellId = 41425; // Hypothermia
2186 else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
2187 spellId = 11196; // Recently Bandaged
2188 else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) )
2189 spellId = 23230; // Blood Fury - Healing Reduction
2191 SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId);
2192 if (AdditionalSpellInfo)
2194 // applied at target by target
2195 Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unitTarget,unitTarget, 0);
2196 unitTarget->AddAura(AdditionalAura);
2197 sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]);
2201 // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2202 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2203 m_caster->CastSpell(unitTarget,41637,true,NULL,Aur);
2206 void Spell::EffectUnlearnSpecialization( uint32 i )
2208 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2209 return;
2211 Player *_player = (Player*)unitTarget;
2212 uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2214 _player->removeSpell(spellToUnlearn);
2216 sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2219 void Spell::EffectPowerDrain(uint32 i)
2221 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2222 return;
2224 Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2226 if(!unitTarget)
2227 return;
2228 if(!unitTarget->isAlive())
2229 return;
2230 if(unitTarget->getPowerType() != drain_power)
2231 return;
2232 if(damage < 0)
2233 return;
2235 uint32 curPower = unitTarget->GetPower(drain_power);
2237 //add spell damage bonus
2238 damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2240 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2241 uint32 power = damage;
2242 if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2243 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2245 int32 new_damage;
2246 if(curPower < power)
2247 new_damage = curPower;
2248 else
2249 new_damage = power;
2251 unitTarget->ModifyPower(drain_power,-new_damage);
2253 if(drain_power == POWER_MANA)
2255 float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2256 if(manaMultiplier==0)
2257 manaMultiplier = 1;
2259 if(Player *modOwner = m_caster->GetSpellModOwner())
2260 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2262 int32 gain = int32(new_damage*manaMultiplier);
2264 m_caster->ModifyPower(POWER_MANA,gain);
2265 //send log
2266 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA);
2270 void Spell::EffectSendEvent(uint32 EffectIndex)
2272 if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround())
2274 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
2275 if(bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2277 switch(m_spellInfo->Id)
2279 case 23333: // Pickup Horde Flag
2280 /*do not uncomment .
2281 if(bg->GetTypeID()==BATTLEGROUND_WS)
2282 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2283 sLog.outDebug("Send Event Horde Flag Picked Up");
2284 break;
2285 /* not used :
2286 case 23334: // Drop Horde Flag
2287 if(bg->GetTypeID()==BATTLEGROUND_WS)
2288 bg->EventPlayerDroppedFlag((Player*)m_caster);
2289 sLog.outDebug("Drop Horde Flag");
2290 break;
2292 case 23335: // Pickup Alliance Flag
2293 /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2294 if(bg->GetTypeID()==BATTLEGROUND_WS)
2295 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2296 sLog.outDebug("Send Event Alliance Flag Picked Up");
2297 break;
2298 /* not used :
2299 case 23336: // Drop Alliance Flag
2300 if(bg->GetTypeID()==BATTLEGROUND_WS)
2301 bg->EventPlayerDroppedFlag((Player*)m_caster);
2302 sLog.outDebug("Drop Alliance Flag");
2303 break;
2304 case 23385: // Alliance Flag Returns
2305 if(bg->GetTypeID()==BATTLEGROUND_WS)
2306 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2307 sLog.outDebug("Alliance Flag Returned");
2308 break;
2309 case 23386: // Horde Flag Returns
2310 if(bg->GetTypeID()==BATTLEGROUND_WS)
2311 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2312 sLog.outDebug("Horde Flag Returned");
2313 break;*/
2314 case 34976:
2316 if(bg->GetTypeID()==BATTLEGROUND_EY)
2317 bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget);
2319 break;
2320 default:
2321 sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2322 break;
2326 sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2327 sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2330 void Spell::EffectPowerBurn(uint32 i)
2332 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2333 return;
2335 Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2337 if(!unitTarget)
2338 return;
2339 if(!unitTarget->isAlive())
2340 return;
2341 if(unitTarget->getPowerType()!=powertype)
2342 return;
2343 if(damage < 0)
2344 return;
2346 int32 curPower = int32(unitTarget->GetPower(powertype));
2348 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2349 uint32 power = damage;
2350 if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2351 power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2353 int32 new_damage = (curPower < power) ? curPower : power;
2355 unitTarget->ModifyPower(powertype,-new_damage);
2356 float multiplier = m_spellInfo->EffectMultipleValue[i];
2358 if(Player *modOwner = m_caster->GetSpellModOwner())
2359 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2361 new_damage = int32(new_damage*multiplier);
2362 m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2365 void Spell::EffectHeal( uint32 /*i*/ )
2367 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2369 // Try to get original caster
2370 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2372 // Skip if m_originalCaster not available
2373 if (!caster)
2374 return;
2376 int32 addhealth = damage;
2378 // Vessel of the Naaru (Vial of the Sunwell trinket)
2379 if (m_spellInfo->Id == 45064)
2381 // Amount of heal - depends from stacked Holy Energy
2382 int damageAmount = 0;
2383 Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2384 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2385 if((*i)->GetId() == 45062)
2386 damageAmount+=(*i)->GetModifier()->m_amount;
2387 if (damageAmount)
2388 m_caster->RemoveAurasDueToSpell(45062);
2390 addhealth += damageAmount;
2392 // Swiftmend - consumes Regrowth or Rejuvenation
2393 else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2395 Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2396 // find most short by duration
2397 Aura *targetAura = NULL;
2398 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2400 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2401 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2403 if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2404 targetAura = *i;
2408 if(!targetAura)
2410 sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2411 return;
2413 int idx = 0;
2414 while(idx < 3)
2416 if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2417 break;
2418 idx++;
2421 int32 tickheal = caster->SpellHealingBonus(targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT, unitTarget);
2422 int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2423 unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2425 addhealth += tickheal * tickcount;
2427 else
2428 addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
2430 bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask, m_attackType);
2431 if (crit)
2432 addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, unitTarget);
2433 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, crit);
2435 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2436 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2438 if(caster->GetTypeId()==TYPEID_PLAYER)
2439 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2440 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2442 // ignore item heals
2443 if(m_CastItem)
2444 return;
2446 uint32 procHealer = PROC_FLAG_HEAL;
2447 if (crit)
2448 procHealer |= PROC_FLAG_CRIT_HEAL;
2450 m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_HEALED,addhealth,SPELL_SCHOOL_MASK_NONE,m_spellInfo,m_IsTriggeredSpell);
2454 void Spell::EffectHealPct( uint32 /*i*/ )
2456 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2458 // Try to get original caster
2459 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2461 // Skip if m_originalCaster not available
2462 if (!caster)
2463 return;
2465 uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2466 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2468 int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2469 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2471 if(caster->GetTypeId()==TYPEID_PLAYER)
2472 if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2473 bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2477 void Spell::EffectHealMechanical( uint32 /*i*/ )
2479 // Mechanic creature type should be correctly checked by targetCreatureType field
2480 if( unitTarget && unitTarget->isAlive() && damage >= 0)
2482 // Try to get original caster
2483 Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2485 // Skip if m_originalCaster not available
2486 if (!caster)
2487 return;
2489 uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget);
2490 caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2491 unitTarget->ModifyHealth( int32(damage) );
2495 void Spell::EffectHealthLeech(uint32 i)
2497 if(!unitTarget)
2498 return;
2499 if(!unitTarget->isAlive())
2500 return;
2502 if(damage < 0)
2503 return;
2505 sLog.outDebug("HealthLeech :%i", damage);
2507 float multiplier = m_spellInfo->EffectMultipleValue[i];
2509 if(Player *modOwner = m_caster->GetSpellModOwner())
2510 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2512 int32 new_damage = int32(damage*multiplier);
2513 uint32 curHealth = unitTarget->GetHealth();
2514 new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2515 if(curHealth < new_damage)
2516 new_damage = curHealth;
2518 if(m_caster->isAlive())
2520 new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster);
2522 m_caster->ModifyHealth(new_damage);
2524 if(m_caster->GetTypeId() == TYPEID_PLAYER)
2525 m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2529 void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2531 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2532 return;
2534 Player* player = (Player*)unitTarget;
2536 uint32 newitemid = itemtype;
2537 ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2538 if(!pProto)
2540 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2541 return;
2544 uint32 num_to_add;
2546 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2547 if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2549 int32 basePoints = m_currentBasePoints[i];
2550 int32 randomPoints = m_spellInfo->EffectDieSides[i];
2551 if (randomPoints)
2552 num_to_add = basePoints + irand(1, randomPoints);
2553 else
2554 num_to_add = basePoints + 1;
2556 else if (pProto->MaxCount == 1)
2557 num_to_add = 1;
2558 else if(player->getLevel() >= m_spellInfo->spellLevel)
2560 int32 basePoints = m_currentBasePoints[i];
2561 float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2562 num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2564 else
2565 num_to_add = 2;
2567 if (num_to_add < 1)
2568 num_to_add = 1;
2569 if (num_to_add > pProto->Stackable)
2570 num_to_add = pProto->Stackable;
2572 // init items_count to 1, since 1 item will be created regardless of specialization
2573 int items_count=1;
2574 // the chance to create additional items
2575 float additionalCreateChance=0.0f;
2576 // the maximum number of created additional items
2577 uint8 additionalMaxNum=0;
2578 // get the chance and maximum number for creating extra items
2579 if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2581 // roll with this chance till we roll not to create or we create the max num
2582 while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2583 ++items_count;
2586 // really will be created more items
2587 num_to_add *= items_count;
2589 // can the player store the new item?
2590 ItemPosCountVec dest;
2591 uint32 no_space = 0;
2592 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2593 if( msg != EQUIP_ERR_OK )
2595 // convert to possible store amount
2596 if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2597 num_to_add -= no_space;
2598 else
2600 // if not created by another reason from full inventory or unique items amount limitation
2601 player->SendEquipError( msg, NULL, NULL );
2602 return;
2606 if(num_to_add)
2608 // create the new item and store it
2609 Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2611 // was it successful? return error if not
2612 if(!pItem)
2614 player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2615 return;
2618 // set the "Crafted by ..." property of the item
2619 if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2620 pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2622 // send info to the client
2623 if(pItem)
2624 player->SendNewItem(pItem, num_to_add, true, true);
2626 // we succeeded in creating at least one item, so a levelup is possible
2627 player->UpdateCraftSkill(m_spellInfo->Id);
2630 // for battleground marks send by mail if not add all expected
2631 if(no_space > 0 )
2633 BattleGroundTypeId bgType;
2634 switch(m_spellInfo->Id)
2636 case SPELL_AV_MARK_WINNER:
2637 case SPELL_AV_MARK_LOSER:
2638 bgType = BATTLEGROUND_AV;
2639 break;
2640 case SPELL_WS_MARK_WINNER:
2641 case SPELL_WS_MARK_LOSER:
2642 bgType = BATTLEGROUND_WS;
2643 break;
2644 case SPELL_AB_MARK_WINNER:
2645 case SPELL_AB_MARK_LOSER:
2646 bgType = BATTLEGROUND_AB;
2647 break;
2648 default:
2649 return;
2652 if(BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgType))
2653 bg->SendRewardMarkByMail(player,newitemid,no_space);
2657 void Spell::EffectCreateItem(uint32 i)
2659 DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2662 void Spell::EffectPersistentAA(uint32 i)
2664 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2666 if(Player* modOwner = m_caster->GetSpellModOwner())
2667 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2669 int32 duration = GetSpellDuration(m_spellInfo);
2670 DynamicObject* dynObj = new DynamicObject;
2671 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))
2673 delete dynObj;
2674 return;
2676 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2677 dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2678 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2679 m_caster->AddDynObject(dynObj);
2680 dynObj->GetMap()->Add(dynObj);
2683 void Spell::EffectEnergize(uint32 i)
2685 if(!unitTarget)
2686 return;
2687 if(!unitTarget->isAlive())
2688 return;
2690 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2691 return;
2693 // Some level depends spells
2694 int multiplier = 0;
2695 int level_diff = 0;
2696 switch (m_spellInfo->Id)
2698 // Restore Energy
2699 case 9512:
2700 level_diff = m_caster->getLevel() - 40;
2701 multiplier = 2;
2702 break;
2703 // Blood Fury
2704 case 24571:
2705 level_diff = m_caster->getLevel() - 60;
2706 multiplier = 10;
2707 break;
2708 // Burst of Energy
2709 case 24532:
2710 level_diff = m_caster->getLevel() - 60;
2711 multiplier = 4;
2712 break;
2713 default:
2714 break;
2717 if (level_diff > 0)
2718 damage -= multiplier * level_diff;
2720 if(damage < 0)
2721 return;
2723 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2725 if(unitTarget->GetMaxPower(power) == 0)
2726 return;
2728 unitTarget->ModifyPower(power,damage);
2729 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2731 // Mad Alchemist's Potion
2732 if (m_spellInfo->Id == 45051)
2734 // find elixirs on target
2735 uint32 elixir_mask = 0;
2736 Unit::AuraMap& Auras = unitTarget->GetAuras();
2737 for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2739 uint32 spell_id = itr->second->GetId();
2740 if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2741 elixir_mask |= mask;
2744 // get available elixir mask any not active type from battle/guardian (and flask if no any)
2745 elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2747 // get all available elixirs by mask and spell level
2748 std::vector<uint32> elixirs;
2749 SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2750 for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2752 if (itr->second & elixir_mask)
2754 if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2755 continue;
2757 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2758 if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2759 continue;
2761 elixirs.push_back(itr->first);
2765 if (!elixirs.empty())
2767 // cast random elixir on target
2768 uint32 rand_spell = urand(0,elixirs.size()-1);
2769 m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2774 void Spell::EffectEnergisePct(uint32 i)
2776 if(!unitTarget)
2777 return;
2778 if(!unitTarget->isAlive())
2779 return;
2781 if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2782 return;
2784 Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2786 uint32 maxPower = unitTarget->GetMaxPower(power);
2787 if(maxPower == 0)
2788 return;
2790 uint32 gain = damage * maxPower / 100;
2791 unitTarget->ModifyPower(power, gain);
2792 m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2795 void Spell::SendLoot(uint64 guid, LootType loottype)
2797 Player* player = (Player*)m_caster;
2798 if (!player)
2799 return;
2801 if (gameObjTarget)
2803 switch (gameObjTarget->GetGoType())
2805 case GAMEOBJECT_TYPE_DOOR:
2806 case GAMEOBJECT_TYPE_BUTTON:
2807 gameObjTarget->UseDoorOrButton();
2808 sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2809 return;
2811 case GAMEOBJECT_TYPE_QUESTGIVER:
2812 // start or end quest
2813 player->PrepareQuestMenu(guid);
2814 player->SendPreparedQuest(guid);
2815 return;
2817 case GAMEOBJECT_TYPE_SPELL_FOCUS:
2818 // triggering linked GO
2819 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2820 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2821 return;
2823 case GAMEOBJECT_TYPE_GOOBER:
2824 // goober_scripts can be triggered if the player don't have the quest
2825 if (gameObjTarget->GetGOInfo()->goober.eventId)
2827 sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2828 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2831 // cast goober spell
2832 if (gameObjTarget->GetGOInfo()->goober.questId)
2833 ///Quest require to be active for GO using
2834 if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2835 return;
2837 gameObjTarget->AddUniqueUse(player);
2838 gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2840 //TODO? Objective counting called without spell check but with quest objective check
2841 // if send spell id then this line will duplicate to spell casting call (double counting)
2842 // So we or have this line and not required in quest_template have reqSpellIdN
2843 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2844 player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2846 // triggering linked GO
2847 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2848 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2850 return;
2852 case GAMEOBJECT_TYPE_CHEST:
2853 // TODO: possible must be moved to loot release (in different from linked triggering)
2854 if (gameObjTarget->GetGOInfo()->chest.eventId)
2856 sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2857 sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2860 // triggering linked GO
2861 if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2862 gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2864 // Don't return, let loots been taken
2868 // Send loot
2869 player->SendLoot(guid, loottype);
2872 void Spell::EffectOpenLock(uint32 /*i*/)
2874 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2876 sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2877 return;
2880 Player* player = (Player*)m_caster;
2882 LootType loottype = LOOT_CORPSE;
2883 uint32 lockId = 0;
2884 uint64 guid = 0;
2886 // Get lockId
2887 if(gameObjTarget)
2889 GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2890 // Arathi Basin banner opening !
2891 if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2892 goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2894 //isAllowUseBattleGroundObject() already called in CanCast()
2895 // in battleground check
2896 if(BattleGround *bg = player->GetBattleGround())
2898 // check if it's correct bg
2899 if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2900 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2901 return;
2904 else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2906 //isAllowUseBattleGroundObject() already called in CanCast()
2907 // in battleground check
2908 if(BattleGround *bg = player->GetBattleGround())
2910 if(bg->GetTypeID() == BATTLEGROUND_EY)
2911 bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2912 return;
2915 lockId = gameObjTarget->GetLockId();
2916 guid = gameObjTarget->GetGUID();
2918 else if(itemTarget)
2920 lockId = itemTarget->GetProto()->LockID;
2921 guid = itemTarget->GetGUID();
2923 else
2925 sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2926 return;
2929 if(!lockId) // possible case for GO and maybe for items.
2931 SendLoot(guid, loottype);
2932 return;
2935 // Get LockInfo
2936 LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
2938 if (!lockInfo)
2940 sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2941 (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
2942 SendCastResult(SPELL_FAILED_BAD_TARGETS);
2943 return;
2946 // check key
2947 for(int i = 0; i < 8; ++i)
2949 // Type==1 This means lockInfo->Index[i] is an item
2950 if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
2952 SendLoot(guid, loottype);
2953 return;
2957 uint32 SkillId = 0;
2958 // Check and skill-up skill
2959 if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
2960 SkillId = m_spellInfo->EffectMiscValue[1];
2961 // pickpocketing spells
2962 else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
2963 SkillId = SKILL_LOCKPICKING;
2965 // skill bonus provided by casting spell (mostly item spells)
2966 uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
2968 uint32 reqSkillValue = lockInfo->Skill[0];
2970 if(lockInfo->Skill[1]) // required pick lock skill applying
2972 if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
2974 SendCastResult(SPELL_FAILED_FIZZLE);
2975 return;
2978 reqSkillValue = lockInfo->Skill[1];
2980 else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
2982 SendCastResult(SPELL_FAILED_BAD_TARGETS);
2983 return;
2986 if ( SkillId )
2988 loottype = LOOT_SKINNING;
2989 if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
2991 SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
2992 return;
2995 // update skill if really known
2996 uint32 SkillValue = player->GetPureSkillValue(SkillId);
2997 if(SkillValue) // non only item base skill
2999 if(gameObjTarget)
3001 // Allow one skill-up until respawned
3002 if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
3003 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
3004 gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
3006 else if(itemTarget)
3008 // Do one skill-up
3009 uint32 SkillValue = player->GetPureSkillValue(SkillId);
3010 player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
3015 SendLoot(guid, loottype);
3018 void Spell::EffectSummonChangeItem(uint32 i)
3020 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3021 return;
3023 Player *player = (Player*)m_caster;
3025 // applied only to using item
3026 if(!m_CastItem)
3027 return;
3029 // ... only to item in own inventory/bank/equip_slot
3030 if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3031 return;
3033 uint32 newitemid = m_spellInfo->EffectItemType[i];
3034 if(!newitemid)
3035 return;
3037 uint16 pos = m_CastItem->GetPos();
3039 Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3040 if( !pNewItem )
3041 return;
3043 for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3045 if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3046 pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3049 if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3051 double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3052 player->DurabilityLoss(pNewItem, loosePercent);
3055 if( player->IsInventoryPos( pos ) )
3057 ItemPosCountVec dest;
3058 uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3059 if( msg == EQUIP_ERR_OK )
3061 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3063 // prevent crash at access and unexpected charges counting with item update queue corrupt
3064 if(m_CastItem==m_targets.getItemTarget())
3065 m_targets.setItemTarget(NULL);
3067 m_CastItem = NULL;
3069 player->StoreItem( dest, pNewItem, true);
3070 return;
3073 else if( player->IsBankPos ( pos ) )
3075 ItemPosCountVec dest;
3076 uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3077 if( msg == EQUIP_ERR_OK )
3079 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3081 // prevent crash at access and unexpected charges counting with item update queue corrupt
3082 if(m_CastItem==m_targets.getItemTarget())
3083 m_targets.setItemTarget(NULL);
3085 m_CastItem = NULL;
3087 player->BankItem( dest, pNewItem, true);
3088 return;
3091 else if( player->IsEquipmentPos ( pos ) )
3093 uint16 dest;
3094 uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3095 if( msg == EQUIP_ERR_OK )
3097 player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3099 // prevent crash at access and unexpected charges counting with item update queue corrupt
3100 if(m_CastItem==m_targets.getItemTarget())
3101 m_targets.setItemTarget(NULL);
3103 m_CastItem = NULL;
3105 player->EquipItem( dest, pNewItem, true);
3106 player->AutoUnequipOffhandIfNeed();
3107 return;
3111 // fail
3112 delete pNewItem;
3115 void Spell::EffectOpenSecretSafe(uint32 i)
3117 EffectOpenLock(i); //no difference for now
3120 void Spell::EffectProficiency(uint32 /*i*/)
3122 if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3123 return;
3124 Player *p_target = (Player*)unitTarget;
3126 uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3127 if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3129 p_target->AddWeaponProficiency(subClassMask);
3130 p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3132 if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3134 p_target->AddArmorProficiency(subClassMask);
3135 p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3139 void Spell::EffectApplyAreaAura(uint32 i)
3141 if(!unitTarget)
3142 return;
3143 if(!unitTarget->isAlive())
3144 return;
3146 AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3147 unitTarget->AddAura(Aur);
3150 void Spell::EffectSummonType(uint32 i)
3152 switch(m_spellInfo->EffectMiscValueB[i])
3154 case SUMMON_TYPE_GUARDIAN:
3155 case SUMMON_TYPE_POSESSED:
3156 case SUMMON_TYPE_POSESSED2:
3157 EffectSummonGuardian(i);
3158 break;
3159 case SUMMON_TYPE_WILD:
3160 EffectSummonWild(i);
3161 break;
3162 case SUMMON_TYPE_DEMON:
3163 EffectSummonDemon(i);
3164 break;
3165 case SUMMON_TYPE_SUMMON:
3166 EffectSummon(i);
3167 break;
3168 case SUMMON_TYPE_CRITTER:
3169 case SUMMON_TYPE_CRITTER2:
3170 case SUMMON_TYPE_CRITTER3:
3171 EffectSummonCritter(i);
3172 break;
3173 case SUMMON_TYPE_TOTEM_SLOT1:
3174 case SUMMON_TYPE_TOTEM_SLOT2:
3175 case SUMMON_TYPE_TOTEM_SLOT3:
3176 case SUMMON_TYPE_TOTEM_SLOT4:
3177 case SUMMON_TYPE_TOTEM:
3178 EffectSummonTotem(i);
3179 break;
3180 case SUMMON_TYPE_UNKNOWN1:
3181 case SUMMON_TYPE_UNKNOWN2:
3182 case SUMMON_TYPE_UNKNOWN3:
3183 case SUMMON_TYPE_UNKNOWN4:
3184 case SUMMON_TYPE_UNKNOWN5:
3185 break;
3186 default:
3187 sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3188 break;
3192 void Spell::EffectSummon(uint32 i)
3194 if(m_caster->GetPetGUID())
3195 return;
3197 if(!unitTarget)
3198 return;
3199 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3200 if(!pet_entry)
3201 return;
3202 uint32 level = m_caster->getLevel();
3203 Pet* spawnCreature = new Pet(SUMMON_PET);
3205 if(spawnCreature->LoadPetFromDB(m_caster,pet_entry))
3207 // set timer for unsummon
3208 int32 duration = GetSpellDuration(m_spellInfo);
3209 if(duration > 0)
3210 spawnCreature->SetDuration(duration);
3212 return;
3215 Map *map = m_caster->GetMap();
3216 uint32 pet_number = objmgr.GeneratePetNumber();
3217 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number))
3219 sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3220 delete spawnCreature;
3221 return;
3224 // Summon in dest location
3225 float x,y,z;
3226 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3228 x = m_targets.m_destX;
3229 y = m_targets.m_destY;
3230 z = m_targets.m_destZ;
3232 else
3233 m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3235 spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3237 if(!spawnCreature->IsPositionValid())
3239 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3240 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3241 delete spawnCreature;
3242 return;
3245 // set timer for unsummon
3246 int32 duration = GetSpellDuration(m_spellInfo);
3247 if(duration > 0)
3248 spawnCreature->SetDuration(duration);
3250 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3251 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0);
3252 spawnCreature->setPowerType(POWER_MANA);
3253 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction());
3254 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
3255 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
3256 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
3257 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
3258 spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
3259 spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
3260 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3261 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3263 spawnCreature->InitStatsForLevel(level);
3265 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3267 spawnCreature->AIM_Initialize();
3268 spawnCreature->InitPetCreateSpells();
3269 spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3270 spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3272 std::string name = m_caster->GetName();
3273 name.append(petTypeSuffix[spawnCreature->getPetType()]);
3274 spawnCreature->SetName( name );
3276 map->Add((Creature*)spawnCreature);
3278 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3280 m_caster->SetPet(spawnCreature);
3281 spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3282 spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3283 ((Player*)m_caster)->PetSpellInitialize();
3287 void Spell::EffectLearnSpell(uint32 i)
3289 if(!unitTarget)
3290 return;
3292 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3294 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3295 EffectLearnPetSpell(i);
3297 return;
3300 Player *player = (Player*)unitTarget;
3302 uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
3303 player->learnSpell(spellToLearn);
3305 sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3308 void Spell::EffectDispel(uint32 i)
3310 if(!unitTarget)
3311 return;
3313 // Fill possible dispell list
3314 std::vector <Aura *> dispel_list;
3316 // Create dispel mask by dispel type
3317 uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3318 uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
3319 Unit::AuraMap const& auras = unitTarget->GetAuras();
3320 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3322 Aura *aur = (*itr).second;
3323 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3325 if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3327 bool positive = true;
3328 if (!aur->IsPositive())
3329 positive = false;
3330 else
3331 positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3333 // do not remove positive auras if friendly target
3334 // negative auras if non-friendly target
3335 if(positive == unitTarget->IsFriendlyTo(m_caster))
3336 continue;
3338 // Add aura to dispel list
3339 dispel_list.push_back(aur);
3342 // Ok if exist some buffs for dispel try dispel it
3343 if (!dispel_list.empty())
3345 std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3346 std::list < uint32 > fail_list; // spell_id
3347 int32 list_size = dispel_list.size();
3348 // Dispell N = damage buffs (or while exist buffs for dispel)
3349 for (int32 count=0; count < damage && list_size > 0; ++count)
3351 // Random select buff for dispel
3352 Aura *aur = dispel_list[urand(0, list_size-1)];
3354 SpellEntry const* spellInfo = aur->GetSpellProto();
3355 // Base dispel chance
3356 // TODO: possible chance depend from spell level??
3357 int32 miss_chance = 0;
3358 // Apply dispel mod from aura caster
3359 if (Unit *caster = aur->GetCaster())
3361 if ( Player* modOwner = caster->GetSpellModOwner() )
3362 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3364 // Try dispel
3365 if (roll_chance_i(miss_chance))
3366 fail_list.push_back(aur->GetId());
3367 else
3368 success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3369 // Remove buff from list for prevent doubles
3370 for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3372 Aura *dispeled = *j;
3373 if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3375 j = dispel_list.erase(j);
3376 --list_size;
3378 else
3379 ++j;
3382 // Send success log and really remove auras
3383 if (!success_list.empty())
3385 int32 count = success_list.size();
3386 WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3387 data.append(unitTarget->GetPackGUID()); // Victim GUID
3388 data.append(m_caster->GetPackGUID()); // Caster GUID
3389 data << uint32(m_spellInfo->Id); // Dispell spell id
3390 data << uint8(0); // not used
3391 data << uint32(count); // count
3392 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3394 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3395 data << uint32(spellInfo->Id); // Spell Id
3396 data << uint8(0); // 0 - dispeled !=0 cleansed
3397 unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3399 m_caster->SendMessageToSet(&data, true);
3401 // On succes dispel
3402 // Devour Magic
3403 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12)
3405 uint32 heal_spell = 0;
3406 switch (m_spellInfo->Id)
3408 case 19505: heal_spell = 19658; break;
3409 case 19731: heal_spell = 19732; break;
3410 case 19734: heal_spell = 19733; break;
3411 case 19736: heal_spell = 19735; break;
3412 case 27276: heal_spell = 27278; break;
3413 case 27277: heal_spell = 27279; break;
3414 default:
3415 sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3416 break;
3418 if (heal_spell)
3419 m_caster->CastSpell(m_caster, heal_spell, true);
3422 // Send fail log to client
3423 if (!fail_list.empty())
3425 // Failed to dispell
3426 WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3427 data << uint64(m_caster->GetGUID()); // Caster GUID
3428 data << uint64(unitTarget->GetGUID()); // Victim GUID
3429 data << uint32(m_spellInfo->Id); // Dispell spell id
3430 for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3431 data << uint32(*j); // Spell Id
3432 m_caster->SendMessageToSet(&data, true);
3437 void Spell::EffectDualWield(uint32 /*i*/)
3439 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
3440 ((Player*)unitTarget)->SetCanDualWield(true);
3443 void Spell::EffectPull(uint32 /*i*/)
3445 // TODO: create a proper pull towards distract spell center for distract
3446 sLog.outDebug("WORLD: Spell Effect DUMMY");
3449 void Spell::EffectDistract(uint32 /*i*/)
3451 // Check for possible target
3452 if (!unitTarget || unitTarget->isInCombat())
3453 return;
3455 // target must be OK to do this
3456 if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3457 return;
3459 float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3461 if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3463 // For players just turn them
3464 WorldPacket data;
3465 ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3466 ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3467 ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3469 else
3471 // Set creature Distracted, Stop it, And turn it
3472 unitTarget->SetOrientation(angle);
3473 unitTarget->StopMoving();
3474 unitTarget->GetMotionMaster()->MoveDistract(damage*1000);
3478 void Spell::EffectPickPocket(uint32 /*i*/)
3480 if( m_caster->GetTypeId() != TYPEID_PLAYER )
3481 return;
3483 // victim must be creature and attackable
3484 if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3485 return;
3487 // victim have to be alive and humanoid or undead
3488 if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3490 int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3492 if (chance > irand(0, 19))
3494 // Stealing successful
3495 //sLog.outDebug("Sending loot from pickpocket");
3496 ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3498 else
3500 // Reveal action + get attack
3501 m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3502 if (((Creature*)unitTarget)->AI())
3503 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3508 void Spell::EffectAddFarsight(uint32 i)
3510 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3511 int32 duration = GetSpellDuration(m_spellInfo);
3512 DynamicObject* dynObj = new DynamicObject;
3513 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))
3515 delete dynObj;
3516 return;
3518 dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3519 dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3520 m_caster->AddDynObject(dynObj);
3521 dynObj->GetMap()->Add(dynObj);
3522 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3523 ((Player*)m_caster)->SetFarSight(dynObj->GetGUID());
3526 void Spell::EffectSummonWild(uint32 i)
3528 uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3529 if(!creature_entry)
3530 return;
3532 uint32 level = m_caster->getLevel();
3534 // level of creature summoned using engineering item based at engineering skill level
3535 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3537 ItemPrototype const *proto = m_CastItem->GetProto();
3538 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3540 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3541 if(skill202)
3543 level = skill202/5;
3548 // select center of summon position
3549 float center_x = m_targets.m_destX;
3550 float center_y = m_targets.m_destY;
3551 float center_z = m_targets.m_destZ;
3553 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3555 int32 amount = damage > 0 ? damage : 1;
3557 for(int32 count = 0; count < amount; ++count)
3559 float px, py, pz;
3560 // If dest location if present
3561 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3563 // Summon 1 unit in dest location
3564 if (count == 0)
3566 px = m_targets.m_destX;
3567 py = m_targets.m_destY;
3568 pz = m_targets.m_destZ;
3570 // Summon in random point all other units if location present
3571 else
3572 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3574 // Summon if dest location not present near caster
3575 else
3576 m_caster->GetClosePoint(px,py,pz,3.0f);
3578 int32 duration = GetSpellDuration(m_spellInfo);
3580 TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3582 m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3586 void Spell::EffectSummonGuardian(uint32 i)
3588 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3589 if(!pet_entry)
3590 return;
3592 // Jewelery statue case (totem like)
3593 if(m_spellInfo->SpellIconID==2056)
3595 EffectSummonTotem(i);
3596 return;
3599 // set timer for unsummon
3600 int32 duration = GetSpellDuration(m_spellInfo);
3602 // Search old Guardian only for players (if casted spell not have duration or cooldown)
3603 // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3604 // so this code hack in fact
3605 if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3606 if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3607 return; // find old guardian, ignore summon
3609 // in another case summon new
3610 uint32 level = m_caster->getLevel();
3612 // level of pet summoned using engineering item based at engineering skill level
3613 if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3615 ItemPrototype const *proto = m_CastItem->GetProto();
3616 if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3618 uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3619 if(skill202)
3621 level = skill202/5;
3626 // select center of summon position
3627 float center_x = m_targets.m_destX;
3628 float center_y = m_targets.m_destY;
3629 float center_z = m_targets.m_destZ;
3631 float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3633 int32 amount = damage > 0 ? damage : 1;
3635 for(int32 count = 0; count < amount; ++count)
3637 Pet* spawnCreature = new Pet(GUARDIAN_PET);
3639 Map *map = m_caster->GetMap();
3640 uint32 pet_number = objmgr.GeneratePetNumber();
3641 if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number))
3643 sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3644 delete spawnCreature;
3645 return;
3648 float px, py, pz;
3649 // If dest location if present
3650 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3652 // Summon 1 unit in dest location
3653 if (count == 0)
3655 px = m_targets.m_destX;
3656 py = m_targets.m_destY;
3657 pz = m_targets.m_destZ;
3659 // Summon in random point all other units if location present
3660 else
3661 m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3663 // Summon if dest location not present near caster
3664 else
3665 m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3667 spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3669 if(!spawnCreature->IsPositionValid())
3671 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3672 spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3673 delete spawnCreature;
3674 return;
3677 if(duration > 0)
3678 spawnCreature->SetDuration(duration);
3680 spawnCreature->SetOwnerGUID(m_caster->GetGUID());
3681 spawnCreature->setPowerType(POWER_MANA);
3682 spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3683 spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3684 spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3685 spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3686 spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3687 spawnCreature->SetCreatorGUID(m_caster->GetGUID());
3688 spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3690 spawnCreature->InitStatsForLevel(level);
3691 spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3693 spawnCreature->AIM_Initialize();
3695 if(m_caster->GetTypeId()==TYPEID_PLAYER)
3696 ((Player*)m_caster)->AddGuardian(spawnCreature);
3698 map->Add((Creature*)spawnCreature);
3702 void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3704 if(!unitTarget)
3705 return;
3707 if(unitTarget->isInFlight())
3708 return;
3710 uint32 mapid = m_caster->GetMapId();
3711 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3713 float fx,fy,fz;
3714 m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3716 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3717 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
3718 else
3719 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3722 void Spell::EffectLearnSkill(uint32 i)
3724 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3725 return;
3727 if(damage < 0)
3728 return;
3730 uint32 skillid = m_spellInfo->EffectMiscValue[i];
3731 uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3732 ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3735 void Spell::EffectAddHonor(uint32 /*i*/)
3737 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3738 return;
3740 sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
3742 // TODO: find formula for honor reward based on player's level!
3744 // now fixed only for level 70 players:
3745 if (((Player*)unitTarget)->getLevel() == 70)
3746 ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
3749 void Spell::EffectTradeSkill(uint32 /*i*/)
3751 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3752 return;
3753 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
3754 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3755 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3758 void Spell::EffectEnchantItemPerm(uint32 i)
3760 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3761 return;
3762 if (!itemTarget)
3763 return;
3765 Player* p_caster = (Player*)m_caster;
3767 p_caster->UpdateCraftSkill(m_spellInfo->Id);
3769 if (m_spellInfo->EffectMiscValue[i])
3771 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3773 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3774 if(!pEnchant)
3775 return;
3777 // item can be in trade slot and have owner diff. from caster
3778 Player* item_owner = itemTarget->GetOwner();
3779 if(!item_owner)
3780 return;
3782 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3784 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3785 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3786 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3787 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3790 // remove old enchanting before applying new if equipped
3791 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3793 itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3795 // add new enchanting if equipped
3796 item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3800 void Spell::EffectEnchantItemTmp(uint32 i)
3802 if(m_caster->GetTypeId() != TYPEID_PLAYER)
3803 return;
3805 Player* p_caster = (Player*)m_caster;
3807 if(!itemTarget)
3808 return;
3810 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3812 // Shaman Rockbiter Weapon
3813 if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3815 int32 enchnting_damage = m_currentBasePoints[1]+1;
3817 // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3818 // with already applied percent bonus from Elemental Weapons talent
3819 // Note: damage calculated (correctly) with rounding int32(float(v)) but
3820 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
3821 switch(enchnting_damage)
3823 // Rank 1
3824 case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
3825 // Rank 2
3826 case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
3827 case 5: enchant_id = 3025; break; // 20%
3828 // Rank 3
3829 case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
3830 case 7: enchant_id = 3027; break; // 20%
3831 // Rank 4
3832 case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
3833 case 10: enchant_id = 503; break; // 14%
3834 case 11: enchant_id = 3031; break; // 20%
3835 // Rank 5
3836 case 15: enchant_id = 3035; break; // 0%
3837 case 16: enchant_id = 1663; break; // 7%
3838 case 17: enchant_id = 3033; break; // 14%
3839 case 18: enchant_id = 3034; break; // 20%
3840 // Rank 6
3841 case 28: enchant_id = 3038; break; // 0%
3842 case 29: enchant_id = 683; break; // 7%
3843 case 31: enchant_id = 3036; break; // 14%
3844 case 33: enchant_id = 3037; break; // 20%
3845 // Rank 7
3846 case 40: enchant_id = 3041; break; // 0%
3847 case 42: enchant_id = 1664; break; // 7%
3848 case 45: enchant_id = 3039; break; // 14%
3849 case 48: enchant_id = 3040; break; // 20%
3850 // Rank 8
3851 case 49: enchant_id = 3044; break; // 0%
3852 case 52: enchant_id = 2632; break; // 7%
3853 case 55: enchant_id = 3042; break; // 14%
3854 case 58: enchant_id = 3043; break; // 20%
3855 // Rank 9
3856 case 62: enchant_id = 2633; break; // 0%
3857 case 66: enchant_id = 3018; break; // 7%
3858 case 70: enchant_id = 3019; break; // 14%
3859 case 74: enchant_id = 3020; break; // 20%
3860 default:
3861 sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3862 return;
3866 if (!enchant_id)
3868 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3869 return;
3872 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3873 if(!pEnchant)
3875 sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3876 return;
3879 // select enchantment duration
3880 uint32 duration;
3882 // rogue family enchantments exception by duration
3883 if(m_spellInfo->Id==38615)
3884 duration = 1800; // 30 mins
3885 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3886 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3887 duration = 3600; // 1 hour
3888 // shaman family enchantments
3889 else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3890 duration = 1800; // 30 mins
3891 // other cases with this SpellVisual already selected
3892 else if(m_spellInfo->SpellVisual[0]==215)
3893 duration = 1800; // 30 mins
3894 // some fishing pole bonuses
3895 else if(m_spellInfo->SpellVisual[0]==563)
3896 duration = 600; // 10 mins
3897 // shaman rockbiter enchantments
3898 else if(m_spellInfo->SpellVisual[0]==0)
3899 duration = 1800; // 30 mins
3900 else if(m_spellInfo->Id==29702)
3901 duration = 300; // 5 mins
3902 else if(m_spellInfo->Id==37360)
3903 duration = 300; // 5 mins
3904 // default case
3905 else
3906 duration = 3600; // 1 hour
3908 // item can be in trade slot and have owner diff. from caster
3909 Player* item_owner = itemTarget->GetOwner();
3910 if(!item_owner)
3911 return;
3913 if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3915 sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3916 p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3917 itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3918 item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3921 // remove old enchanting before applying new if equipped
3922 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3924 itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3926 // add new enchanting if equipped
3927 item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3930 void Spell::EffectTameCreature(uint32 /*i*/)
3932 if(m_caster->GetPetGUID())
3933 return;
3935 if(!unitTarget)
3936 return;
3938 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3939 return;
3941 Creature* creatureTarget = (Creature*)unitTarget;
3943 if(creatureTarget->isPet())
3944 return;
3946 if(m_caster->getClass() != CLASS_HUNTER)
3947 return;
3949 // cast finish successfully
3950 //SendChannelUpdate(0);
3951 finish();
3953 Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
3955 // kill original creature
3956 creatureTarget->setDeathState(JUST_DIED);
3957 creatureTarget->RemoveCorpse();
3958 creatureTarget->SetHealth(0); // just for nice GM-mode view
3960 uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
3962 // prepare visual effect for levelup
3963 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
3965 // add to world
3966 pet->GetMap()->Add((Creature*)pet);
3968 // visual effect for levelup
3969 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
3971 // caster have pet now
3972 m_caster->SetPet(pet);
3974 if(m_caster->GetTypeId() == TYPEID_PLAYER)
3976 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3977 ((Player*)m_caster)->PetSpellInitialize();
3981 void Spell::EffectSummonPet(uint32 i)
3983 uint32 petentry = m_spellInfo->EffectMiscValue[i];
3985 Pet *OldSummon = m_caster->GetPet();
3987 // if pet requested type already exist
3988 if( OldSummon )
3990 if(petentry == 0 || OldSummon->GetEntry() == petentry)
3992 // pet in corpse state can't be summoned
3993 if( OldSummon->isDead() )
3994 return;
3996 OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
3997 OldSummon->SetMapId(m_caster->GetMapId());
3999 float px, py, pz;
4000 m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4002 OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4003 m_caster->GetMap()->Add((Creature*)OldSummon);
4005 if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4007 ((Player*)m_caster)->PetSpellInitialize();
4009 return;
4012 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4013 ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4014 else
4015 return;
4018 Pet* NewSummon = new Pet;
4020 // petentry==0 for hunter "call pet" (current pet summoned if any)
4021 if(NewSummon->LoadPetFromDB(m_caster,petentry))
4023 if(NewSummon->getPetType()==SUMMON_PET)
4025 // Remove Demonic Sacrifice auras (known pet)
4026 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4027 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4029 if((*itr)->GetModifier()->m_miscvalue==2228)
4031 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4032 itr = auraClassScripts.begin();
4034 else
4035 ++itr;
4039 return;
4042 // not error in case fail hunter call pet
4043 if(!petentry)
4045 delete NewSummon;
4046 return;
4049 CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4051 if(!cInfo)
4053 sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4054 delete NewSummon;
4055 return;
4058 Map *map = m_caster->GetMap();
4059 uint32 pet_number = objmgr.GeneratePetNumber();
4060 if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
4062 delete NewSummon;
4063 return;
4066 float px, py, pz;
4067 m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4069 NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4071 if(!NewSummon->IsPositionValid())
4073 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4074 NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4075 delete NewSummon;
4076 return;
4079 uint32 petlevel = m_caster->getLevel();
4080 NewSummon->setPetType(SUMMON_PET);
4082 uint32 faction = m_caster->getFaction();
4083 if(m_caster->GetTypeId() == TYPEID_UNIT)
4085 if ( ((Creature*)m_caster)->isTotem() )
4086 NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4087 else
4088 NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4091 NewSummon->SetOwnerGUID(m_caster->GetGUID());
4092 NewSummon->SetCreatorGUID(m_caster->GetGUID());
4093 NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0);
4094 NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4095 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
4096 NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
4097 NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
4098 NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
4099 NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
4100 NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4102 NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4103 // this enables pet details window (Shift+P)
4105 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4106 NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4108 NewSummon->InitStatsForLevel(petlevel);
4109 NewSummon->InitPetCreateSpells();
4111 if(NewSummon->getPetType()==SUMMON_PET)
4113 // Remove Demonic Sacrifice auras (new pet)
4114 Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4115 for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4117 if((*itr)->GetModifier()->m_miscvalue==2228)
4119 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4120 itr = auraClassScripts.begin();
4122 else
4123 ++itr;
4126 // generate new name for summon pet
4127 std::string new_name=objmgr.GeneratePetName(petentry);
4128 if(!new_name.empty())
4129 NewSummon->SetName(new_name);
4131 else if(NewSummon->getPetType()==HUNTER_PET)
4132 NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4134 NewSummon->AIM_Initialize();
4135 NewSummon->SetHealth(NewSummon->GetMaxHealth());
4136 NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4138 map->Add((Creature*)NewSummon);
4140 m_caster->SetPet(NewSummon);
4141 sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4143 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4145 NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4146 ((Player*)m_caster)->PetSpellInitialize();
4150 void Spell::EffectLearnPetSpell(uint32 i)
4152 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4153 return;
4155 Player *_player = (Player*)m_caster;
4157 Pet *pet = _player->GetPet();
4158 if(!pet)
4159 return;
4160 if(!pet->isAlive())
4161 return;
4163 SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4164 if(!learn_spellproto)
4165 return;
4167 pet->learnSpell(learn_spellproto->Id);
4169 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4170 _player->PetSpellInitialize();
4173 void Spell::EffectTaunt(uint32 /*i*/)
4175 // this effect use before aura Taunt apply for prevent taunt already attacking target
4176 // for spell as marked "non effective at already attacking target"
4177 if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4179 if(unitTarget->getVictim()==m_caster)
4181 SendCastResult(SPELL_FAILED_DONT_REPORT);
4182 return;
4186 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4187 if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4188 unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4191 void Spell::EffectWeaponDmg(uint32 i)
4193 if(!unitTarget)
4194 return;
4195 if(!unitTarget->isAlive())
4196 return;
4198 // multiple weapon dmg effect workaround
4199 // execute only the last weapon damage
4200 // and handle all effects at once
4201 for (int j = 0; j < 3; j++)
4203 switch(m_spellInfo->Effect[j])
4205 case SPELL_EFFECT_WEAPON_DAMAGE:
4206 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4207 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4208 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4209 if (j < i) // we must calculate only at last weapon effect
4210 return;
4211 break;
4215 // some spell specific modifiers
4216 bool customBonusDamagePercentMod = false;
4217 float bonusDamagePercentMod = 1.0f; // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4218 float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4219 float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
4220 bool normalized = false;
4222 int32 spell_bonus = 0; // bonus specific for spell
4223 switch(m_spellInfo->SpellFamilyName)
4225 case SPELLFAMILY_WARRIOR:
4227 // Whirlwind, single only spell with 2 weapon white damage apply if have
4228 if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4230 if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4231 spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4233 // Devastate bonus and sunder armor refresh
4234 else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
4236 customBonusDamagePercentMod = true;
4237 bonusDamagePercentMod = 0.0f; // only applied if auras found
4239 Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE);
4240 for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
4242 SpellEntry const *proto = (*itr)->GetSpellProto();
4243 if(proto->SpellVisual[0] == 406 && proto->SpellIconID == 565)
4245 int32 duration = GetSpellDuration(proto);
4246 (*itr)->SetAuraDuration(duration);
4247 (*itr)->SendAuraUpdate(false);
4248 bonusDamagePercentMod += 1.0f; // +100%
4252 break;
4254 case SPELLFAMILY_ROGUE:
4256 // Ambush
4257 if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4259 customBonusDamagePercentMod = true;
4260 bonusDamagePercentMod = 2.5f; // 250%
4262 // Mutilate (for each hand)
4263 else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4265 bool found = false;
4266 // fast check
4267 if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4268 found = true;
4269 // full aura scan
4270 else
4272 Unit::AuraMap const& auras = unitTarget->GetAuras();
4273 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4275 if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4277 found = true;
4278 break;
4283 if(found)
4284 totalDamagePercentMod *= 1.5f; // 150% if poisoned
4286 break;
4288 case SPELLFAMILY_PALADIN:
4290 // Seal of Command - receive benefit from Spell Damage and Healing
4291 if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4293 spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4294 spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4296 break;
4298 case SPELLFAMILY_SHAMAN:
4300 // Skyshatter Harness item set bonus
4301 // Stormstrike
4302 if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4304 Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4305 for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4307 // Stormstrike AP Buff
4308 if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4310 m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4311 break;
4318 int32 fixed_bonus = 0;
4319 for (int j = 0; j < 3; j++)
4321 switch(m_spellInfo->Effect[j])
4323 case SPELL_EFFECT_WEAPON_DAMAGE:
4324 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4325 fixed_bonus += CalculateDamage(j,unitTarget);
4326 break;
4327 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4328 fixed_bonus += CalculateDamage(j,unitTarget);
4329 normalized = true;
4330 break;
4331 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4332 weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4334 // applied only to prev.effects fixed damage
4335 if(customBonusDamagePercentMod)
4336 fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4337 else
4338 fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4339 break;
4340 default:
4341 break; // not weapon damage effect, just skip
4345 // non-weapon damage
4346 int32 bonus = spell_bonus + fixed_bonus;
4348 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4349 if(bonus)
4351 UnitMods unitMod;
4352 switch(m_attackType)
4354 default:
4355 case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4356 case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break;
4357 case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
4360 float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4361 bonus = int32(bonus*weapon_total_pct);
4364 // + weapon damage with applied weapon% dmg to base weapon damage in call
4365 bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4367 // total damage
4368 bonus = int32(bonus*totalDamagePercentMod);
4370 // prevent negative damage
4371 uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4373 const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
4375 uint32 hitInfo = 0;
4376 VictimState victimState = VICTIMSTATE_NORMAL;
4377 uint32 blocked_dmg = 0;
4378 uint32 absorbed_dmg = 0;
4379 uint32 resisted_dmg = 0;
4380 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
4382 m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell);
4384 if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK) // not send ranged miss/etc
4385 m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg);
4387 bool criticalhit = (hitInfo & HITINFO_CRITICALHIT);
4388 m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
4390 if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg))
4392 eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg);
4394 else
4396 cleanDamage.damage += eff_damage;
4397 eff_damage = 0;
4400 // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4401 m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true);
4403 // Hemorrhage
4404 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4406 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4407 ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4410 // Mangle (Cat): CP
4411 if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4413 if(m_caster->GetTypeId()==TYPEID_PLAYER)
4414 ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4417 // take ammo
4418 if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4420 Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4422 // wands don't have ammo
4423 if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4424 return;
4426 if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4428 if(pItem->GetMaxStackCount()==1)
4430 // decrease durability for non-stackable throw weapon
4431 ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4433 else
4435 // decrease items amount for stackable throw weapon
4436 uint32 count = 1;
4437 ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4440 else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4441 ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4445 void Spell::EffectThreat(uint32 /*i*/)
4447 if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4448 return;
4450 if(!unitTarget->CanHaveThreatList())
4451 return;
4453 unitTarget->AddThreat(m_caster, float(damage));
4456 void Spell::EffectHealMaxHealth(uint32 /*i*/)
4458 if(!unitTarget)
4459 return;
4460 if(!unitTarget->isAlive())
4461 return;
4463 uint32 heal = m_caster->GetMaxHealth();
4465 int32 gain = unitTarget->ModifyHealth(heal);
4466 unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
4468 m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal);
4471 void Spell::EffectInterruptCast(uint32 /*i*/)
4473 if(!unitTarget)
4474 return;
4475 if(!unitTarget->isAlive())
4476 return;
4478 // TODO: not all spells that used this effect apply cooldown at school spells
4479 // also exist case: apply cooldown to interrupted cast only and to all spells
4480 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4482 if (unitTarget->m_currentSpells[i])
4484 // check if we can interrupt spell
4485 if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4487 unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4488 unitTarget->InterruptSpell(i,false);
4494 void Spell::EffectSummonObjectWild(uint32 i)
4496 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4498 GameObject* pGameObj = new GameObject;
4500 WorldObject* target = focusObject;
4501 if( !target )
4502 target = m_caster;
4504 float x,y,z;
4505 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4507 x = m_targets.m_destX;
4508 y = m_targets.m_destY;
4509 z = m_targets.m_destZ;
4511 else
4512 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4514 Map *map = target->GetMap();
4516 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4517 x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4519 delete pGameObj;
4520 return;
4523 int32 duration = GetSpellDuration(m_spellInfo);
4524 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4525 pGameObj->SetSpellId(m_spellInfo->Id);
4527 if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4528 m_caster->AddGameObject(pGameObj);
4529 map->Add(pGameObj);
4531 if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS
4533 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4535 Player *pl = (Player*)m_caster;
4536 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4537 if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4539 uint32 team = ALLIANCE;
4541 if(pl->GetTeam() == team)
4542 team = HORDE;
4544 ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4549 if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY
4551 if(m_caster->GetTypeId() == TYPEID_PLAYER)
4553 BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4554 if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4556 ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4561 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4563 GameObject* linkedGO = new GameObject;
4564 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4565 x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4567 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4568 linkedGO->SetSpellId(m_spellInfo->Id);
4570 m_caster->AddGameObject(linkedGO);
4571 map->Add(linkedGO);
4573 else
4575 delete linkedGO;
4576 linkedGO = NULL;
4577 return;
4582 void Spell::EffectScriptEffect(uint32 effIndex)
4584 // TODO: we must implement hunter pet summon at login there (spell 6962)
4586 // by spell id
4587 switch(m_spellInfo->Id)
4589 // Bending Shinbone
4590 case 8856:
4592 if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4593 return;
4595 uint32 spell_id = 0;
4596 switch(urand(1,5))
4598 case 1: spell_id = 8854; break;
4599 default: spell_id = 8855; break;
4602 m_caster->CastSpell(m_caster,spell_id,true,NULL);
4603 return;
4606 // Healthstone creating spells
4607 case 6201:
4608 case 6202:
4609 case 5699:
4610 case 11729:
4611 case 11730:
4612 case 27230:
4614 uint32 itemtype;
4615 uint32 rank = 0;
4616 Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4617 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4619 if((*i)->GetId() == 18692)
4621 rank = 1;
4622 break;
4624 else if((*i)->GetId() == 18693)
4626 rank = 2;
4627 break;
4631 static uint32 const itypes[6][3] = {
4632 { 5512,19004,19005}, // Minor Healthstone
4633 { 5511,19006,19007}, // Lesser Healthstone
4634 { 5509,19008,19009}, // Healthstone
4635 { 5510,19010,19011}, // Greater Healthstone
4636 { 9421,19012,19013}, // Major Healthstone
4637 {22103,22104,22105} // Master Healthstone
4640 switch(m_spellInfo->Id)
4642 case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone
4643 case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone
4644 case 5699: itemtype=itypes[2][rank];break; // Healthstone
4645 case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
4646 case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
4647 case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
4648 default:
4649 return;
4651 DoCreateItem( effIndex, itemtype );
4652 return;
4654 // Brittle Armor - need remove one 24575 Brittle Armor aura
4655 case 24590:
4656 unitTarget->RemoveSingleAuraFromStack(24575, 0);
4657 unitTarget->RemoveSingleAuraFromStack(24575, 1);
4658 return;
4659 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4660 case 26465:
4661 unitTarget->RemoveSingleAuraFromStack(26464, 0);
4662 return;
4663 // Orb teleport spells
4664 case 25140:
4665 case 25143:
4666 case 25650:
4667 case 25652:
4668 case 29128:
4669 case 29129:
4670 case 35376:
4671 case 35727:
4673 if(!unitTarget)
4674 return;
4676 uint32 spellid;
4677 switch(m_spellInfo->Id)
4679 case 25140: spellid = 32571; break;
4680 case 25143: spellid = 32572; break;
4681 case 25650: spellid = 30140; break;
4682 case 25652: spellid = 30141; break;
4683 case 29128: spellid = 32568; break;
4684 case 29129: spellid = 32569; break;
4685 case 35376: spellid = 25649; break;
4686 case 35727: spellid = 35730; break;
4687 default:
4688 return;
4691 unitTarget->CastSpell(unitTarget,spellid,false);
4692 return;
4695 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4696 case 22539:
4697 case 22972:
4698 case 22975:
4699 case 22976:
4700 case 22977:
4701 case 22978:
4702 case 22979:
4703 case 22980:
4704 case 22981:
4705 case 22982:
4706 case 22983:
4707 case 22984:
4708 case 22985:
4710 if(!unitTarget || !unitTarget->isAlive())
4711 return;
4713 // Onyxia Scale Cloak
4714 if(unitTarget->GetDummyAura(22683))
4715 return;
4717 // Shadow Flame
4718 m_caster->CastSpell(unitTarget, 22682, true);
4719 return;
4721 break;
4723 // Summon Black Qiraji Battle Tank
4724 case 26656:
4726 if(!unitTarget)
4727 return;
4729 // Prevent stacking of mounts
4730 unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4732 // Two separate mounts depending on area id (allows use both in and out of specific instance)
4733 if (unitTarget->GetAreaId() == 3428)
4734 unitTarget->CastSpell(unitTarget, 25863, false);
4735 else
4736 unitTarget->CastSpell(unitTarget, 26655, false);
4737 break;
4739 // Piccolo of the Flaming Fire
4740 case 17512:
4742 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4743 return;
4744 unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4745 break;
4748 // Dreaming Glory
4749 case 28698:
4751 if(!unitTarget)
4752 return;
4753 unitTarget->CastSpell(unitTarget, 28694, true);
4754 break;
4757 // Netherbloom
4758 case 28702:
4760 if(!unitTarget)
4761 return;
4762 // 25% chance of casting a random buff
4763 if(roll_chance_i(75))
4764 return;
4766 // triggered spells are 28703 to 28707
4767 // Note: some sources say, that there was the possibility of
4768 // receiving a debuff. However, this seems to be removed by a patch.
4769 const uint32 spellid = 28703;
4771 // don't overwrite an existing aura
4772 for(uint8 i=0; i<5; i++)
4773 if(unitTarget->HasAura(spellid+i, 0))
4774 return;
4775 unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
4776 break;
4779 // Nightmare Vine
4780 case 28720:
4782 if(!unitTarget)
4783 return;
4784 // 25% chance of casting Nightmare Pollen
4785 if(roll_chance_i(75))
4786 return;
4787 unitTarget->CastSpell(unitTarget, 28721, true);
4788 break;
4791 // Mirren's Drinking Hat
4792 case 29830:
4794 uint32 item = 0;
4795 switch ( urand(1,6) )
4797 case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager
4798 case 4: case 5: item = 23585; break;// Stouthammer Lite
4799 case 6: item = 23586; break;// Aerie Peak Pale Ale
4801 if (item)
4802 DoCreateItem(effIndex,item);
4803 break;
4805 // Improved Sprint
4806 case 30918:
4808 // Removes snares and roots.
4809 uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4810 Unit::AuraMap& Auras = unitTarget->GetAuras();
4811 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4813 next = iter;
4814 ++next;
4815 Aura *aur = iter->second;
4816 if (!aur->IsPositive()) //only remove negative spells
4818 // check for mechanic mask
4819 if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4821 unitTarget->RemoveAurasDueToSpell(aur->GetId());
4822 if(Auras.empty())
4823 break;
4824 else
4825 next = Auras.begin();
4829 break;
4831 case 41126: // Flame Crash
4833 if(!unitTarget)
4834 return;
4836 unitTarget->CastSpell(unitTarget, 41131, true);
4837 break;
4839 case 44876: // Force Cast - Portal Effect: Sunwell Isle
4841 if(!unitTarget)
4842 return;
4844 unitTarget->CastSpell(unitTarget, 44870, true);
4845 break;
4848 // Goblin Weather Machine
4849 case 46203:
4851 if(!unitTarget)
4852 return;
4854 uint32 spellId;
4855 switch(rand()%4)
4857 case 0:
4858 spellId=46740;
4859 break;
4860 case 1:
4861 spellId=46739;
4862 break;
4863 case 2:
4864 spellId=46738;
4865 break;
4866 case 3:
4867 spellId=46736;
4868 break;
4870 unitTarget->CastSpell(unitTarget, spellId, true);
4871 break;
4873 //5,000 Gold
4874 case 46642:
4876 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4877 return;
4879 ((Player*)unitTarget)->ModifyMoney(50000000);
4881 break;
4885 if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
4887 switch(m_spellInfo->SpellFamilyFlags)
4889 // Judgement
4890 case 0x800000:
4892 if(!unitTarget || !unitTarget->isAlive())
4893 return;
4894 uint32 spellId2 = 0;
4896 // all seals have aura dummy
4897 Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4898 for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
4900 SpellEntry const *spellInfo = (*itr)->GetSpellProto();
4902 // search seal (all seals have judgement's aura dummy spell id in 2 effect
4903 if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
4904 continue;
4906 // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4907 spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
4909 if(spellId2 <= 1)
4910 continue;
4912 // found, remove seal
4913 m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4915 // Sanctified Judgement
4916 Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4917 for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
4919 if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
4921 int32 chance = (*i)->GetModifier()->m_amount;
4922 if ( roll_chance_i(chance) )
4924 int32 mana = spellInfo->manaCost;
4925 if ( Player* modOwner = m_caster->GetSpellModOwner() )
4926 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
4927 mana = int32(mana* 0.8f);
4928 m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
4930 break;
4934 break;
4937 m_caster->CastSpell(unitTarget,spellId2,true);
4938 return;
4943 // normal DB scripted effect
4944 if(!unitTarget)
4945 return;
4947 sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
4948 sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
4951 void Spell::EffectSanctuary(uint32 /*i*/)
4953 if(!unitTarget)
4954 return;
4955 //unitTarget->CombatStop();
4957 unitTarget->CombatStop();
4958 unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting
4959 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4960 if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
4962 ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4966 void Spell::EffectAddComboPoints(uint32 /*i*/)
4968 if(!unitTarget)
4969 return;
4971 if(m_caster->GetTypeId() != TYPEID_PLAYER)
4972 return;
4974 if(damage <= 0)
4975 return;
4977 ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
4980 void Spell::EffectDuel(uint32 i)
4982 if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
4983 return;
4985 Player *caster = (Player*)m_caster;
4986 Player *target = (Player*)unitTarget;
4988 // caster or target already have requested duel
4989 if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
4990 return;
4992 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
4993 // Don't have to check the target's map since you cannot challenge someone across maps
4994 uint32 mapid = caster->GetMapId();
4995 if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
4997 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
4998 return;
5001 AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5002 if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5004 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5005 return;
5008 AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5009 if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5011 SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
5012 return;
5015 //CREATE DUEL FLAG OBJECT
5016 GameObject* pGameObj = new GameObject;
5018 uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5020 Map *map = m_caster->GetMap();
5021 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5022 m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5023 m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5024 m_caster->GetPositionZ(),
5025 m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5027 delete pGameObj;
5028 return;
5031 pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5032 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5033 int32 duration = GetSpellDuration(m_spellInfo);
5034 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5035 pGameObj->SetSpellId(m_spellInfo->Id);
5037 m_caster->AddGameObject(pGameObj);
5038 map->Add(pGameObj);
5039 //END
5041 // Send request
5042 WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5043 data << pGameObj->GetGUID();
5044 data << caster->GetGUID();
5045 caster->GetSession()->SendPacket(&data);
5046 target->GetSession()->SendPacket(&data);
5048 // create duel-info
5049 DuelInfo *duel = new DuelInfo;
5050 duel->initiator = caster;
5051 duel->opponent = target;
5052 duel->startTime = 0;
5053 duel->startTimer = 0;
5054 caster->duel = duel;
5056 DuelInfo *duel2 = new DuelInfo;
5057 duel2->initiator = caster;
5058 duel2->opponent = caster;
5059 duel2->startTime = 0;
5060 duel2->startTimer = 0;
5061 target->duel = duel2;
5063 caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5064 target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5067 void Spell::EffectStuck(uint32 /*i*/)
5069 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5070 return;
5072 if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5073 return;
5075 Player* pTarget = (Player*)unitTarget;
5077 sLog.outDebug("Spell Effect: Stuck");
5078 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());
5080 if(pTarget->isInFlight())
5081 return;
5083 // homebind location is loaded always
5084 pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5086 // Stuck spell trigger Hearthstone cooldown
5087 SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5088 if(!spellInfo)
5089 return;
5090 Spell spell(pTarget,spellInfo,true,0);
5091 spell.SendSpellCooldown();
5094 void Spell::EffectSummonPlayer(uint32 /*i*/)
5096 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5097 return;
5099 // Evil Twin (ignore player summon, but hide this for summoner)
5100 if(unitTarget->GetDummyAura(23445))
5101 return;
5103 float x,y,z;
5104 m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5106 ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5108 WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5109 data << uint64(m_caster->GetGUID()); // summoner guid
5110 data << uint32(m_caster->GetZoneId()); // summoner zone
5111 data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs
5112 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5115 static ScriptInfo generateActivateCommand()
5117 ScriptInfo si;
5118 si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5119 return si;
5122 void Spell::EffectActivateObject(uint32 effect_idx)
5124 if(!gameObjTarget)
5125 return;
5127 static ScriptInfo activateCommand = generateActivateCommand();
5129 int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5131 sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5134 void Spell::EffectApplyGlyph(uint32 i)
5136 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5137 return;
5139 Player *player = (Player*)m_caster;
5141 // remove old glyph
5142 if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
5144 if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
5146 player->RemoveAurasDueToSpell(old_gp->SpellId);
5147 player->SetGlyph(m_glyphIndex, 0);
5151 // apply new one
5152 if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
5154 if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
5156 if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
5158 if(gp->TypeFlags != gs->TypeFlags)
5160 SendCastResult(SPELL_FAILED_INVALID_GLYPH);
5161 return; // glyph slot missmatch
5165 player->CastSpell(m_caster, gp->SpellId, true);
5166 player->SetGlyph(m_glyphIndex, glyph);
5167 if(m_CastItem)
5168 player->DestroyItemCount(m_CastItem->GetEntry(), 1, true);
5173 void Spell::EffectSummonTotem(uint32 i)
5175 uint8 slot = 0;
5176 switch(m_spellInfo->EffectMiscValueB[i])
5178 case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5179 case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5180 case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5181 case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5182 // Battle standard case
5183 case SUMMON_TYPE_TOTEM: slot = 254; break;
5184 // jewelery statue case, like totem without slot
5185 case SUMMON_TYPE_GUARDIAN: slot = 255; break;
5186 default: return;
5189 if(slot < MAX_TOTEM)
5191 uint64 guid = m_caster->m_TotemSlot[slot];
5192 if(guid != 0)
5194 Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5195 if(OldTotem && OldTotem->isTotem())
5196 ((Totem*)OldTotem)->UnSummon();
5200 uint32 team = 0;
5201 if (m_caster->GetTypeId()==TYPEID_PLAYER)
5202 team = ((Player*)m_caster)->GetTeam();
5204 Totem* pTotem = new Totem;
5206 if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
5208 delete pTotem;
5209 return;
5212 float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5214 float x,y,z;
5215 m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5217 // totem must be at same Z in case swimming caster and etc.
5218 if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5219 z = m_caster->GetPositionZ();
5221 pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5223 if(slot < MAX_TOTEM)
5224 m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5226 pTotem->SetOwner(m_caster->GetGUID());
5227 pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
5229 int32 duration=GetSpellDuration(m_spellInfo);
5230 if(Player* modOwner = m_caster->GetSpellModOwner())
5231 modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5232 pTotem->SetDuration(duration);
5234 if (damage) // if not spell info, DB values used
5236 pTotem->SetMaxHealth(damage);
5237 pTotem->SetHealth(damage);
5240 pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5241 pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5243 pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true);
5244 pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true);
5246 pTotem->Summon(m_caster);
5248 if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5250 WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5251 data << uint8(slot);
5252 data << uint64(pTotem->GetGUID());
5253 data << uint32(duration);
5254 data << uint32(m_spellInfo->Id);
5255 ((Player*)m_caster)->SendDirectMessage(&data);
5259 void Spell::EffectEnchantHeldItem(uint32 i)
5261 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5262 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5263 return;
5265 Player* item_owner = (Player*)unitTarget;
5266 Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5268 if(!item )
5269 return;
5271 // must be equipped
5272 if(!item ->IsEquipped())
5273 return;
5275 if (m_spellInfo->EffectMiscValue[i])
5277 uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5278 int32 duration = GetSpellDuration(m_spellInfo); //Try duration index first ..
5279 if(!duration)
5280 duration = m_currentBasePoints[i]+1; //Base points after ..
5281 if(!duration)
5282 duration = 10; //10 seconds for enchants which don't have listed duration
5284 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5285 if(!pEnchant)
5286 return;
5288 // Always go to temp enchantment slot
5289 EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5291 // Enchantment will not be applied if a different one already exists
5292 if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5293 return;
5295 // Apply the temporary enchantment
5296 item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5297 item_owner->ApplyEnchantment(item,slot,true);
5301 void Spell::EffectDisEnchant(uint32 /*i*/)
5303 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5304 return;
5306 Player* p_caster = (Player*)m_caster;
5307 if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5308 return;
5310 p_caster->UpdateCraftSkill(m_spellInfo->Id);
5312 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5314 // item will be removed at disenchanting end
5317 void Spell::EffectInebriate(uint32 /*i*/)
5319 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5320 return;
5322 Player *player = (Player*)unitTarget;
5323 uint16 currentDrunk = player->GetDrunkValue();
5324 uint16 drunkMod = damage * 256;
5325 if (currentDrunk + drunkMod > 0xFFFF)
5326 currentDrunk = 0xFFFF;
5327 else
5328 currentDrunk += drunkMod;
5329 player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5332 void Spell::EffectFeedPet(uint32 i)
5334 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5335 return;
5337 Player *_player = (Player*)m_caster;
5339 if(!itemTarget)
5340 return;
5342 Pet *pet = _player->GetPet();
5343 if(!pet)
5344 return;
5346 if(!pet->isAlive())
5347 return;
5349 int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel);
5350 if(benefit <= 0)
5351 return;
5353 uint32 count = 1;
5354 _player->DestroyItemCount(itemTarget,count,true);
5355 // TODO: fix crash when a spell has two effects, both pointed at the same item target
5357 m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5360 void Spell::EffectDismissPet(uint32 /*i*/)
5362 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5363 return;
5365 Pet* pet = m_caster->GetPet();
5367 // not let dismiss dead pet
5368 if(!pet||!pet->isAlive())
5369 return;
5371 ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5374 void Spell::EffectSummonObject(uint32 i)
5376 uint32 go_id = m_spellInfo->EffectMiscValue[i];
5378 uint8 slot = 0;
5379 switch(m_spellInfo->Effect[i])
5381 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5382 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5383 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5384 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5385 default: return;
5388 uint64 guid = m_caster->m_ObjectSlot[slot];
5389 if(guid != 0)
5391 GameObject* obj = NULL;
5392 if( m_caster )
5393 obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5395 if(obj) obj->Delete();
5396 m_caster->m_ObjectSlot[slot] = 0;
5399 GameObject* pGameObj = new GameObject;
5401 float rot2 = sin(m_caster->GetOrientation()/2);
5402 float rot3 = cos(m_caster->GetOrientation()/2);
5404 float x,y,z;
5405 // If dest location if present
5406 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5408 x = m_targets.m_destX;
5409 y = m_targets.m_destY;
5410 z = m_targets.m_destZ;
5412 // Summon in random point all other units if location present
5413 else
5414 m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5416 Map *map = m_caster->GetMap();
5417 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5419 delete pGameObj;
5420 return;
5423 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5424 int32 duration = GetSpellDuration(m_spellInfo);
5425 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5426 pGameObj->SetSpellId(m_spellInfo->Id);
5427 m_caster->AddGameObject(pGameObj);
5429 map->Add(pGameObj);
5430 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5431 data << pGameObj->GetGUID();
5432 m_caster->SendMessageToSet(&data,true);
5434 m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5437 void Spell::EffectResurrect(uint32 /*effIndex*/)
5439 if(!unitTarget)
5440 return;
5441 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5442 return;
5444 if(unitTarget->isAlive())
5445 return;
5446 if(!unitTarget->IsInWorld())
5447 return;
5449 switch (m_spellInfo->Id)
5451 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5452 case 8342:
5453 if (roll_chance_i(67))
5455 m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5456 return;
5458 break;
5459 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5460 case 22999:
5461 if (roll_chance_i(50))
5463 m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5464 return;
5466 break;
5467 default:
5468 break;
5471 Player* pTarget = ((Player*)unitTarget);
5473 if(pTarget->isRessurectRequested()) // already have one active request
5474 return;
5476 uint32 health = pTarget->GetMaxHealth() * damage / 100;
5477 uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5479 pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5480 SendResurrectRequest(pTarget);
5483 void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5485 if(!unitTarget || !unitTarget->isAlive())
5486 return;
5488 if( unitTarget->m_extraAttacks )
5489 return;
5491 unitTarget->m_extraAttacks = damage;
5494 void Spell::EffectParry(uint32 /*i*/)
5496 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
5498 ((Player*)unitTarget)->SetCanParry(true);
5502 void Spell::EffectBlock(uint32 /*i*/)
5504 if (unitTarget->GetTypeId() != TYPEID_PLAYER)
5505 return;
5507 ((Player*)unitTarget)->SetCanBlock(true);
5510 void Spell::EffectMomentMove(uint32 i)
5512 if(unitTarget->isInFlight())
5513 return;
5515 if( m_spellInfo->rangeIndex== 1) //self range
5517 uint32 mapid = m_caster->GetMapId();
5518 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5520 // before caster
5521 float fx,fy,fz;
5522 unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5523 float ox,oy,oz;
5524 unitTarget->GetPosition(ox,oy,oz);
5526 float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
5527 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5529 fx = fx2;
5530 fy = fy2;
5531 fz = fz2;
5532 unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5535 if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5536 ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5537 else
5538 m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5542 void Spell::EffectReputation(uint32 i)
5544 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5545 return;
5547 Player *_player = (Player*)unitTarget;
5549 int32 rep_change = m_currentBasePoints[i]+1; // field store reputation change -1
5551 uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5553 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5555 if(!factionEntry)
5556 return;
5558 _player->ModifyFactionReputation(factionEntry,rep_change);
5561 void Spell::EffectQuestComplete(uint32 i)
5563 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5564 return;
5566 Player *_player = (Player*)m_caster;
5568 uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5569 _player->AreaExploredOrEventHappens(quest_id);
5572 void Spell::EffectSelfResurrect(uint32 i)
5574 if(!unitTarget || unitTarget->isAlive())
5575 return;
5576 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5577 return;
5578 if(!unitTarget->IsInWorld())
5579 return;
5581 uint32 health = 0;
5582 uint32 mana = 0;
5584 // flat case
5585 if(damage < 0)
5587 health = uint32(-damage);
5588 mana = m_spellInfo->EffectMiscValue[i];
5590 // percent case
5591 else
5593 health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5594 if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5595 mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5598 Player *plr = ((Player*)unitTarget);
5599 plr->ResurrectPlayer(0.0f);
5601 plr->SetHealth( health );
5602 plr->SetPower(POWER_MANA, mana );
5603 plr->SetPower(POWER_RAGE, 0 );
5604 plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5606 plr->SpawnCorpseBones();
5608 plr->SaveToDB();
5611 void Spell::EffectSkinning(uint32 /*i*/)
5613 if(unitTarget->GetTypeId() != TYPEID_UNIT )
5614 return;
5615 if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5616 return;
5618 Creature* creature = (Creature*) unitTarget;
5619 int32 targetLevel = creature->getLevel();
5621 uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill();
5623 ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5624 creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5626 int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5628 int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5630 // Double chances for elites
5631 ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5634 void Spell::EffectCharge(uint32 /*i*/)
5636 if(!unitTarget || !m_caster)
5637 return;
5639 float x, y, z;
5640 unitTarget->GetContactPoint(m_caster, x, y, z);
5641 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5642 ((Creature *)unitTarget)->StopMoving();
5644 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5645 m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5647 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5648 m_caster->GetMap()->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5650 // not all charge effects used in negative spells
5651 if ( !IsPositiveSpell(m_spellInfo->Id))
5652 m_caster->Attack(unitTarget,true);
5655 void Spell::EffectSummonCritter(uint32 i)
5657 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5658 return;
5659 Player* player = (Player*)m_caster;
5661 uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5662 if(!pet_entry)
5663 return;
5665 Pet* old_critter = player->GetMiniPet();
5667 // for same pet just despawn
5668 if(old_critter && old_critter->GetEntry() == pet_entry)
5670 player->RemoveMiniPet();
5671 return;
5674 // despawn old pet before summon new
5675 if(old_critter)
5676 player->RemoveMiniPet();
5678 // summon new pet
5679 Pet* critter = new Pet(MINI_PET);
5681 Map *map = m_caster->GetMap();
5682 uint32 pet_number = objmgr.GeneratePetNumber();
5683 if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
5684 map, pet_entry, pet_number))
5686 sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5687 delete critter;
5688 return;
5691 float x,y,z;
5692 // If dest location if present
5693 if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5695 x = m_targets.m_destX;
5696 y = m_targets.m_destY;
5697 z = m_targets.m_destZ;
5699 // Summon if dest location not present near caster
5700 else
5701 m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5703 critter->Relocate(x,y,z,m_caster->GetOrientation());
5705 if(!critter->IsPositionValid())
5707 sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
5708 critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5709 delete critter;
5710 return;
5713 critter->SetOwnerGUID(m_caster->GetGUID());
5714 critter->SetCreatorGUID(m_caster->GetGUID());
5715 critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5716 critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5718 critter->AIM_Initialize();
5719 critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
5720 critter->SetMaxHealth(1);
5721 critter->SetHealth(1);
5722 critter->SetLevel(1);
5724 // set timer for unsummon
5725 int32 duration = GetSpellDuration(m_spellInfo);
5726 if(duration > 0)
5727 critter->SetDuration(duration);
5729 std::string name = player->GetName();
5730 name.append(petTypeSuffix[critter->getPetType()]);
5731 critter->SetName( name );
5732 player->SetMiniPet(critter);
5734 map->Add((Creature*)critter);
5737 void Spell::EffectKnockBack(uint32 i)
5739 if(!unitTarget || !m_caster)
5740 return;
5742 // Effect only works on players
5743 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5744 return;
5746 float vsin = sin(m_caster->GetAngle(unitTarget));
5747 float vcos = cos(m_caster->GetAngle(unitTarget));
5749 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5750 data.append(unitTarget->GetPackGUID());
5751 data << uint32(0); // Sequence
5752 data << float(vcos); // x direction
5753 data << float(vsin); // y direction
5754 data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed
5755 data << float(damage/-10); // Z Movement speed (vertical)
5757 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5760 void Spell::EffectSendTaxi(uint32 i)
5762 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5763 return;
5765 TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5766 if(!entry)
5767 return;
5769 std::vector<uint32> nodes;
5771 nodes.resize(2);
5772 nodes[0] = entry->from;
5773 nodes[1] = entry->to;
5775 uint32 mountid = 0;
5776 switch(m_spellInfo->Id)
5778 case 31606: //Stormcrow Amulet
5779 mountid = 17447;
5780 break;
5781 case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run
5782 case 45113: //Quest - Sunwell Daily - Ship Bombing Run
5783 case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return
5784 mountid = 22840;
5785 break;
5786 case 34905: //Stealth Flight
5787 mountid = 6851;
5788 break;
5791 ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
5795 void Spell::EffectPlayerPull(uint32 i)
5797 if(!unitTarget || !m_caster)
5798 return;
5800 // Effect only works on players
5801 if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5802 return;
5804 float vsin = sin(unitTarget->GetAngle(m_caster));
5805 float vcos = cos(unitTarget->GetAngle(m_caster));
5807 WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5808 data.append(unitTarget->GetPackGUID());
5809 data << uint32(0); // Sequence
5810 data << float(vcos); // x direction
5811 data << float(vsin); // y direction
5812 // Horizontal speed
5813 data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
5814 data << float(m_spellInfo->EffectMiscValue[i])/-10; // Z Movement speed
5816 ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5819 void Spell::EffectDispelMechanic(uint32 i)
5821 if(!unitTarget)
5822 return;
5824 uint32 mechanic = m_spellInfo->EffectMiscValue[i];
5826 Unit::AuraMap& Auras = unitTarget->GetAuras();
5827 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5829 next = iter;
5830 ++next;
5831 SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
5832 if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
5834 unitTarget->RemoveAurasDueToSpell(spell->Id);
5835 if(Auras.empty())
5836 break;
5837 else
5838 next = Auras.begin();
5841 return;
5844 void Spell::EffectSummonDeadPet(uint32 /*i*/)
5846 if(m_caster->GetTypeId() != TYPEID_PLAYER)
5847 return;
5848 Player *_player = (Player*)m_caster;
5849 Pet *pet = _player->GetPet();
5850 if(!pet)
5851 return;
5852 if(pet->isAlive())
5853 return;
5854 if(damage < 0)
5855 return;
5856 pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
5857 pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5858 pet->setDeathState( ALIVE );
5859 pet->clearUnitState(UNIT_STAT_ALL_STATE);
5860 pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
5862 pet->AIM_Initialize();
5864 _player->PetSpellInitialize();
5865 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5868 void Spell::EffectDestroyAllTotems(uint32 /*i*/)
5870 float mana = 0;
5871 for(int slot = 0; slot < MAX_TOTEM; ++slot)
5873 if(!m_caster->m_TotemSlot[slot])
5874 continue;
5876 Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
5877 if(totem && totem->isTotem())
5879 uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
5880 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
5881 if(spellInfo)
5882 mana += spellInfo->manaCost * damage / 100;
5883 ((Totem*)totem)->UnSummon();
5887 int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
5888 m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
5891 void Spell::EffectDurabilityDamage(uint32 i)
5893 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5894 return;
5896 int32 slot = m_spellInfo->EffectMiscValue[i];
5898 // FIXME: some spells effects have value -1/-2
5899 // Possibly its mean -1 all player equipped items and -2 all items
5900 if(slot < 0)
5902 ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
5903 return;
5906 // invalid slot value
5907 if(slot >= INVENTORY_SLOT_BAG_END)
5908 return;
5910 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5911 ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
5914 void Spell::EffectDurabilityDamagePCT(uint32 i)
5916 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5917 return;
5919 int32 slot = m_spellInfo->EffectMiscValue[i];
5921 // FIXME: some spells effects have value -1/-2
5922 // Possibly its mean -1 all player equipped items and -2 all items
5923 if(slot < 0)
5925 ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
5926 return;
5929 // invalid slot value
5930 if(slot >= INVENTORY_SLOT_BAG_END)
5931 return;
5933 if(damage <= 0)
5934 return;
5936 if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5937 ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
5940 void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
5942 if(!unitTarget)
5943 return;
5945 unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
5948 void Spell::EffectTransmitted(uint32 effIndex)
5950 uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
5952 GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
5954 if (!goinfo)
5956 sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
5957 return;
5960 float fx,fy,fz;
5962 if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5964 fx = m_targets.m_destX;
5965 fy = m_targets.m_destY;
5966 fz = m_targets.m_destZ;
5968 //FIXME: this can be better check for most objects but still hack
5969 else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
5971 float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
5972 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5974 else
5976 float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5977 float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5978 float dis = rand_norm() * (max_dis - min_dis) + min_dis;
5980 m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5983 Map *cMap = m_caster->GetMap();
5985 if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
5987 if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
5988 { // but this is not proper, we really need to ignore not materialized objects
5989 SendCastResult(SPELL_FAILED_NOT_HERE);
5990 SendChannelUpdate(0);
5991 return;
5994 // replace by water level in this case
5995 fz = cMap->GetWaterLevel(fx,fy);
5997 // if gameobject is summoning object, it should be spawned right on caster's position
5998 else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
6000 m_caster->GetPosition(fx,fy,fz);
6003 GameObject* pGameObj = new GameObject;
6005 if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6006 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6008 delete pGameObj;
6009 return;
6012 int32 duration = GetSpellDuration(m_spellInfo);
6014 switch(goinfo->type)
6016 case GAMEOBJECT_TYPE_FISHINGNODE:
6018 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6019 // Orientation3
6020 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 );
6021 // Orientation4
6022 pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 );
6023 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6025 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6026 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6027 int32 lastSec;
6028 switch(urand(0, 3))
6030 case 0: lastSec = 3; break;
6031 case 1: lastSec = 7; break;
6032 case 2: lastSec = 13; break;
6033 case 3: lastSec = 17; break;
6036 duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
6037 break;
6039 case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6041 if(m_caster->GetTypeId()==TYPEID_PLAYER)
6043 pGameObj->AddUniqueUse((Player*)m_caster);
6044 m_caster->AddGameObject(pGameObj); // will removed at spell cancel
6046 break;
6048 case GAMEOBJECT_TYPE_FISHINGHOLE:
6049 case GAMEOBJECT_TYPE_CHEST:
6050 default:
6052 break;
6056 pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6058 pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6060 pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6061 pGameObj->SetSpellId(m_spellInfo->Id);
6063 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6064 //m_caster->AddGameObject(pGameObj);
6065 //m_ObjToDel.push_back(pGameObj);
6067 cMap->Add(pGameObj);
6069 WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6070 data << uint64(pGameObj->GetGUID());
6071 m_caster->SendMessageToSet(&data,true);
6073 if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6075 GameObject* linkedGO = new GameObject;
6076 if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6077 fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6079 linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6080 linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6081 linkedGO->SetSpellId(m_spellInfo->Id);
6082 linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6084 linkedGO->GetMap()->Add(linkedGO);
6086 else
6088 delete linkedGO;
6089 linkedGO = NULL;
6090 return;
6095 void Spell::EffectProspecting(uint32 /*i*/)
6097 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6098 return;
6100 Player* p_caster = (Player*)m_caster;
6101 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6102 return;
6104 if(itemTarget->GetCount() < 5)
6105 return;
6107 if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6109 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6110 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6111 p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6114 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6117 void Spell::EffectMilling(uint32 /*i*/)
6119 if(m_caster->GetTypeId() != TYPEID_PLAYER)
6120 return;
6122 Player* p_caster = (Player*)m_caster;
6123 if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
6124 return;
6126 if(itemTarget->GetCount() < 5)
6127 return;
6129 if( sWorld.getConfig(CONFIG_SKILL_MILLING))
6131 uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
6132 uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6133 p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
6136 ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
6139 void Spell::EffectSkill(uint32 /*i*/)
6141 sLog.outDebug("WORLD: SkillEFFECT");
6144 void Spell::EffectSummonDemon(uint32 i)
6146 float px = m_targets.m_destX;
6147 float py = m_targets.m_destY;
6148 float pz = m_targets.m_destZ;
6150 Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6151 if (!Charmed)
6152 return;
6154 // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6155 Charmed->SetLevel(m_caster->getLevel());
6157 // TODO: Add damage/mana/hp according to level
6159 if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
6161 // Enslave demon effect, without mana cost and cooldown
6162 m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6164 // Inferno effect
6165 Charmed->CastSpell(Charmed, 22703, true, 0);
6169 /* There is currently no need for this effect. We handle it in BattleGround.cpp
6170 If we would handle the resurrection here, the spiritguide would instantly disappear as the
6171 player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6172 This is why we use a half sec delay between the visual effect and the resurrection itself */
6173 void Spell::EffectSpiritHeal(uint32 /*i*/)
6176 if(!unitTarget || unitTarget->isAlive())
6177 return;
6178 if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6179 return;
6180 if(!unitTarget->IsInWorld())
6181 return;
6183 //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6184 //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6185 ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6186 ((Player*)unitTarget)->SpawnCorpseBones();
6190 // remove insignia spell effect
6191 void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6193 sLog.outDebug("Effect: SkinPlayerCorpse");
6194 if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6195 return;
6197 ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6200 void Spell::EffectStealBeneficialBuff(uint32 i)
6202 sLog.outDebug("Effect: StealBeneficialBuff");
6204 if(!unitTarget || unitTarget==m_caster) // can't steal from self
6205 return;
6207 std::vector <Aura *> steal_list;
6208 // Create dispel mask by dispel type
6209 uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6210 Unit::AuraMap const& auras = unitTarget->GetAuras();
6211 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6213 Aura *aur = (*itr).second;
6214 if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6216 // Need check for passive? this
6217 if (aur->IsPositive() && !aur->IsPassive())
6218 steal_list.push_back(aur);
6221 // Ok if exist some buffs for dispel try dispel it
6222 if (!steal_list.empty())
6224 std::list < std::pair<uint32,uint64> > success_list;
6225 int32 list_size = steal_list.size();
6226 // Dispell N = damage buffs (or while exist buffs for dispel)
6227 for (int32 count=0; count < damage && list_size > 0; ++count)
6229 // Random select buff for dispel
6230 Aura *aur = steal_list[urand(0, list_size-1)];
6231 // Not use chance for steal
6232 // TODO possible need do it
6233 success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6235 // Remove buff from list for prevent doubles
6236 for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6238 Aura *stealed = *j;
6239 if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6241 j = steal_list.erase(j);
6242 --list_size;
6244 else
6245 ++j;
6248 // Really try steal and send log
6249 if (!success_list.empty())
6251 int32 count = success_list.size();
6252 WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6253 data.append(unitTarget->GetPackGUID()); // Victim GUID
6254 data.append(m_caster->GetPackGUID()); // Caster GUID
6255 data << uint32(m_spellInfo->Id); // Dispell spell id
6256 data << uint8(0); // not used
6257 data << uint32(count); // count
6258 for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6260 SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6261 data << uint32(spellInfo->Id); // Spell Id
6262 data << uint8(0); // 0 - steals !=0 transfers
6263 unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6265 m_caster->SendMessageToSet(&data, true);
6270 void Spell::EffectKillCredit(uint32 i)
6272 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6273 return;
6275 ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6278 void Spell::EffectQuestFail(uint32 i)
6280 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6281 return;
6283 ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);