2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
24 #include "UpdateMask.h"
26 #include "ObjectMgr.h"
29 #include "SkillExtraItems.h"
32 #include "DynamicObject.h"
33 #include "SpellAuras.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "SharedDefines.h"
40 #include "GameObject.h"
41 #include "GossipDef.h"
44 #include "CreatureAI.h"
45 #include "BattleGroundMgr.h"
46 #include "BattleGround.h"
47 #include "BattleGroundEY.h"
48 #include "BattleGroundWS.h"
49 #include "VMapFactory.h"
51 #include "SocialMgr.h"
53 #include "TemporarySummon.h"
54 #include "ScriptCalls.h"
55 #include "SkillDiscovery.h"
58 pEffect SpellEffects
[TOTAL_SPELL_EFFECTS
]=
60 &Spell::EffectNULL
, // 0
61 &Spell::EffectInstaKill
, // 1 SPELL_EFFECT_INSTAKILL
62 &Spell::EffectSchoolDMG
, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
63 &Spell::EffectDummy
, // 3 SPELL_EFFECT_DUMMY
64 &Spell::EffectUnused
, // 4 SPELL_EFFECT_PORTAL_TELEPORT unused
65 &Spell::EffectTeleportUnits
, // 5 SPELL_EFFECT_TELEPORT_UNITS
66 &Spell::EffectApplyAura
, // 6 SPELL_EFFECT_APPLY_AURA
67 &Spell::EffectEnvirinmentalDMG
, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
68 &Spell::EffectPowerDrain
, // 8 SPELL_EFFECT_POWER_DRAIN
69 &Spell::EffectHealthLeech
, // 9 SPELL_EFFECT_HEALTH_LEECH
70 &Spell::EffectHeal
, // 10 SPELL_EFFECT_HEAL
71 &Spell::EffectUnused
, // 11 SPELL_EFFECT_BIND
72 &Spell::EffectNULL
, // 12 SPELL_EFFECT_PORTAL
73 &Spell::EffectUnused
, // 13 SPELL_EFFECT_RITUAL_BASE unused
74 &Spell::EffectUnused
, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused
75 &Spell::EffectUnused
, // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL unused
76 &Spell::EffectQuestComplete
, // 16 SPELL_EFFECT_QUEST_COMPLETE
77 &Spell::EffectWeaponDmg
, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
78 &Spell::EffectResurrect
, // 18 SPELL_EFFECT_RESURRECT
79 &Spell::EffectAddExtraAttacks
, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
80 &Spell::EffectUnused
, // 20 SPELL_EFFECT_DODGE one spell: Dodge
81 &Spell::EffectUnused
, // 21 SPELL_EFFECT_EVADE one spell: Evade (DND)
82 &Spell::EffectParry
, // 22 SPELL_EFFECT_PARRY
83 &Spell::EffectBlock
, // 23 SPELL_EFFECT_BLOCK one spell: Block
84 &Spell::EffectCreateItem
, // 24 SPELL_EFFECT_CREATE_ITEM
85 &Spell::EffectUnused
, // 25 SPELL_EFFECT_WEAPON
86 &Spell::EffectUnused
, // 26 SPELL_EFFECT_DEFENSE one spell: Defense
87 &Spell::EffectPersistentAA
, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
88 &Spell::EffectSummonType
, // 28 SPELL_EFFECT_SUMMON
89 &Spell::EffectLeapForward
, // 29 SPELL_EFFECT_LEAP
90 &Spell::EffectEnergize
, // 30 SPELL_EFFECT_ENERGIZE
91 &Spell::EffectWeaponDmg
, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
92 &Spell::EffectTriggerMissileSpell
, // 32 SPELL_EFFECT_TRIGGER_MISSILE
93 &Spell::EffectOpenLock
, // 33 SPELL_EFFECT_OPEN_LOCK
94 &Spell::EffectSummonChangeItem
, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
95 &Spell::EffectApplyAreaAura
, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
96 &Spell::EffectLearnSpell
, // 36 SPELL_EFFECT_LEARN_SPELL
97 &Spell::EffectUnused
, // 37 SPELL_EFFECT_SPELL_DEFENSE one spell: SPELLDEFENSE (DND)
98 &Spell::EffectDispel
, // 38 SPELL_EFFECT_DISPEL
99 &Spell::EffectUnused
, // 39 SPELL_EFFECT_LANGUAGE
100 &Spell::EffectDualWield
, // 40 SPELL_EFFECT_DUAL_WIELD
101 &Spell::EffectUnused
, // 41 SPELL_EFFECT_JUMP
102 &Spell::EffectJump
, // 42 SPELL_EFFECT_JUMP2
103 &Spell::EffectTeleUnitsFaceCaster
, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
104 &Spell::EffectLearnSkill
, // 44 SPELL_EFFECT_SKILL_STEP
105 &Spell::EffectAddHonor
, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
106 &Spell::EffectNULL
, // 46 SPELL_EFFECT_SPAWN we must spawn pet there
107 &Spell::EffectTradeSkill
, // 47 SPELL_EFFECT_TRADE_SKILL
108 &Spell::EffectUnused
, // 48 SPELL_EFFECT_STEALTH one spell: Base Stealth
109 &Spell::EffectUnused
, // 49 SPELL_EFFECT_DETECT one spell: Detect
110 &Spell::EffectTransmitted
, // 50 SPELL_EFFECT_TRANS_DOOR
111 &Spell::EffectUnused
, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT unused
112 &Spell::EffectUnused
, // 52 SPELL_EFFECT_GUARANTEE_HIT one spell: zzOLDCritical Shot
113 &Spell::EffectEnchantItemPerm
, // 53 SPELL_EFFECT_ENCHANT_ITEM
114 &Spell::EffectEnchantItemTmp
, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
115 &Spell::EffectTameCreature
, // 55 SPELL_EFFECT_TAMECREATURE
116 &Spell::EffectSummonPet
, // 56 SPELL_EFFECT_SUMMON_PET
117 &Spell::EffectLearnPetSpell
, // 57 SPELL_EFFECT_LEARN_PET_SPELL
118 &Spell::EffectWeaponDmg
, // 58 SPELL_EFFECT_WEAPON_DAMAGE
119 &Spell::EffectCreateRandomItem
, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot
120 &Spell::EffectProficiency
, // 60 SPELL_EFFECT_PROFICIENCY
121 &Spell::EffectSendEvent
, // 61 SPELL_EFFECT_SEND_EVENT
122 &Spell::EffectPowerBurn
, // 62 SPELL_EFFECT_POWER_BURN
123 &Spell::EffectThreat
, // 63 SPELL_EFFECT_THREAT
124 &Spell::EffectTriggerSpell
, // 64 SPELL_EFFECT_TRIGGER_SPELL
125 &Spell::EffectApplyAreaAura
, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
126 &Spell::EffectUnused
, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
127 &Spell::EffectHealMaxHealth
, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
128 &Spell::EffectInterruptCast
, // 68 SPELL_EFFECT_INTERRUPT_CAST
129 &Spell::EffectDistract
, // 69 SPELL_EFFECT_DISTRACT
130 &Spell::EffectPull
, // 70 SPELL_EFFECT_PULL one spell: Distract Move
131 &Spell::EffectPickPocket
, // 71 SPELL_EFFECT_PICKPOCKET
132 &Spell::EffectAddFarsight
, // 72 SPELL_EFFECT_ADD_FARSIGHT
133 &Spell::EffectUnused
, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
134 &Spell::EffectApplyGlyph
, // 74 SPELL_EFFECT_APPLY_GLYPH
135 &Spell::EffectHealMechanical
, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
136 &Spell::EffectSummonObjectWild
, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
137 &Spell::EffectScriptEffect
, // 77 SPELL_EFFECT_SCRIPT_EFFECT
138 &Spell::EffectUnused
, // 78 SPELL_EFFECT_ATTACK
139 &Spell::EffectSanctuary
, // 79 SPELL_EFFECT_SANCTUARY
140 &Spell::EffectAddComboPoints
, // 80 SPELL_EFFECT_ADD_COMBO_POINTS
141 &Spell::EffectUnused
, // 81 SPELL_EFFECT_CREATE_HOUSE one spell: Create House (TEST)
142 &Spell::EffectNULL
, // 82 SPELL_EFFECT_BIND_SIGHT
143 &Spell::EffectDuel
, // 83 SPELL_EFFECT_DUEL
144 &Spell::EffectStuck
, // 84 SPELL_EFFECT_STUCK
145 &Spell::EffectSummonPlayer
, // 85 SPELL_EFFECT_SUMMON_PLAYER
146 &Spell::EffectActivateObject
, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
147 &Spell::EffectUnused
, // 87 SPELL_EFFECT_WMO_DAMAGE
148 &Spell::EffectUnused
, // 88 SPELL_EFFECT_WMO_REPAIR
149 &Spell::EffectUnused
, // 89 SPELL_EFFECT_WMO_CHANGE
150 &Spell::EffectKillCreditPersonal
, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
151 &Spell::EffectUnused
, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
152 &Spell::EffectEnchantHeldItem
, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
153 &Spell::EffectUnused
, // 93 SPELL_EFFECT_SUMMON_PHANTASM
154 &Spell::EffectSelfResurrect
, // 94 SPELL_EFFECT_SELF_RESURRECT
155 &Spell::EffectSkinning
, // 95 SPELL_EFFECT_SKINNING
156 &Spell::EffectCharge
, // 96 SPELL_EFFECT_CHARGE
157 &Spell::EffectUnused
, // 97 SPELL_EFFECT_97
158 &Spell::EffectKnockBack
, // 98 SPELL_EFFECT_KNOCK_BACK
159 &Spell::EffectDisEnchant
, // 99 SPELL_EFFECT_DISENCHANT
160 &Spell::EffectInebriate
, //100 SPELL_EFFECT_INEBRIATE
161 &Spell::EffectFeedPet
, //101 SPELL_EFFECT_FEED_PET
162 &Spell::EffectDismissPet
, //102 SPELL_EFFECT_DISMISS_PET
163 &Spell::EffectReputation
, //103 SPELL_EFFECT_REPUTATION
164 &Spell::EffectSummonObject
, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
165 &Spell::EffectSummonObject
, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
166 &Spell::EffectSummonObject
, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
167 &Spell::EffectSummonObject
, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
168 &Spell::EffectDispelMechanic
, //108 SPELL_EFFECT_DISPEL_MECHANIC
169 &Spell::EffectSummonDeadPet
, //109 SPELL_EFFECT_SUMMON_DEAD_PET
170 &Spell::EffectDestroyAllTotems
, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
171 &Spell::EffectDurabilityDamage
, //111 SPELL_EFFECT_DURABILITY_DAMAGE
172 &Spell::EffectUnused
, //112 SPELL_EFFECT_112
173 &Spell::EffectResurrectNew
, //113 SPELL_EFFECT_RESURRECT_NEW
174 &Spell::EffectTaunt
, //114 SPELL_EFFECT_ATTACK_ME
175 &Spell::EffectDurabilityDamagePCT
, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
176 &Spell::EffectSkinPlayerCorpse
, //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE one spell: Remove Insignia, bg usage, required special corpse flags...
177 &Spell::EffectSpiritHeal
, //117 SPELL_EFFECT_SPIRIT_HEAL one spell: Spirit Heal
178 &Spell::EffectSkill
, //118 SPELL_EFFECT_SKILL professions and more
179 &Spell::EffectApplyAreaAura
, //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
180 &Spell::EffectUnused
, //120 SPELL_EFFECT_TELEPORT_GRAVEYARD one spell: Graveyard Teleport Test
181 &Spell::EffectWeaponDmg
, //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
182 &Spell::EffectUnused
, //122 SPELL_EFFECT_122 unused
183 &Spell::EffectSendTaxi
, //123 SPELL_EFFECT_SEND_TAXI taxi/flight related (misc value is taxi path id)
184 &Spell::EffectPlayerPull
, //124 SPELL_EFFECT_PLAYER_PULL opposite of knockback effect (pulls player twoard caster)
185 &Spell::EffectModifyThreatPercent
, //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
186 &Spell::EffectStealBeneficialBuff
, //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF spell steal effect?
187 &Spell::EffectProspecting
, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
188 &Spell::EffectApplyAreaAura
, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
189 &Spell::EffectApplyAreaAura
, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
190 &Spell::EffectNULL
, //130 SPELL_EFFECT_REDIRECT_THREAT
191 &Spell::EffectUnused
, //131 SPELL_EFFECT_131 used in some test spells
192 &Spell::EffectPlayMusic
, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
193 &Spell::EffectUnlearnSpecialization
, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
194 &Spell::EffectKillCredit
, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
195 &Spell::EffectNULL
, //135 SPELL_EFFECT_CALL_PET
196 &Spell::EffectHealPct
, //136 SPELL_EFFECT_HEAL_PCT
197 &Spell::EffectEnergisePct
, //137 SPELL_EFFECT_ENERGIZE_PCT
198 &Spell::EffectLeapBack
, //138 SPELL_EFFECT_LEAP_BACK Leap back
199 &Spell::EffectUnused
, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
200 &Spell::EffectForceCast
, //140 SPELL_EFFECT_FORCE_CAST
201 &Spell::EffectNULL
, //141 SPELL_EFFECT_141 damage and reduce speed?
202 &Spell::EffectTriggerSpellWithValue
, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
203 &Spell::EffectApplyAreaAura
, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
204 &Spell::EffectNULL
, //144 SPELL_EFFECT_144 Spectral Blast
205 &Spell::EffectNULL
, //145 SPELL_EFFECT_145 Black Hole Effect
206 &Spell::EffectActivateRune
, //146 SPELL_EFFECT_ACTIVATE_RUNE
207 &Spell::EffectQuestFail
, //147 SPELL_EFFECT_QUEST_FAIL quest fail
208 &Spell::EffectUnused
, //148 SPELL_EFFECT_148 unused
209 &Spell::EffectCharge2
, //149 SPELL_EFFECT_CHARGE2 swoop
210 &Spell::EffectUnused
, //150 SPELL_EFFECT_150 unused
211 &Spell::EffectTriggerRitualOfSummoning
, //151 SPELL_EFFECT_TRIGGER_SPELL_2
212 &Spell::EffectNULL
, //152 SPELL_EFFECT_152 summon Refer-a-Friend
213 &Spell::EffectNULL
, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
214 &Spell::EffectNULL
, //154 unused
215 &Spell::EffectTitanGrip
, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
216 &Spell::EffectEnchantItemPrismatic
, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
217 &Spell::EffectCreateItem2
, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
218 &Spell::EffectMilling
, //158 SPELL_EFFECT_MILLING milling
219 &Spell::EffectRenamePet
, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
220 &Spell::EffectNULL
, //160 SPELL_EFFECT_160 unused
221 &Spell::EffectNULL
, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
222 &Spell::EffectNULL
, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
225 void Spell::EffectNULL(uint32
/*i*/)
227 sLog
.outDebug("WORLD: Spell Effect DUMMY");
230 void Spell::EffectUnused(uint32
/*i*/)
232 // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN MANGOS
235 void Spell::EffectResurrectNew(uint32 i
)
237 if(!unitTarget
|| unitTarget
->isAlive())
240 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
243 if(!unitTarget
->IsInWorld())
246 Player
* pTarget
= ((Player
*)unitTarget
);
248 if(pTarget
->isRessurectRequested()) // already have one active request
251 uint32 health
= damage
;
252 uint32 mana
= m_spellInfo
->EffectMiscValue
[i
];
253 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
254 SendResurrectRequest(pTarget
);
257 void Spell::EffectInstaKill(uint32
/*i*/)
259 if( !unitTarget
|| !unitTarget
->isAlive() )
263 if(m_spellInfo
->Id
==18788 && unitTarget
->GetTypeId()==TYPEID_UNIT
)
265 uint32 entry
= unitTarget
->GetEntry();
269 case 416: spellID
=18789; break; //imp
270 case 417: spellID
=18792; break; //fellhunter
271 case 1860: spellID
=18790; break; //void
272 case 1863: spellID
=18791; break; //succubus
273 case 17252: spellID
=35701; break; //fellguard
275 sLog
.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry
);
279 m_caster
->CastSpell(m_caster
, spellID
, true);
282 if(m_caster
== unitTarget
) // prevent interrupt message
285 m_caster
->DealDamage(unitTarget
, unitTarget
->GetHealth(), NULL
, DIRECT_DAMAGE
, SPELL_SCHOOL_MASK_NORMAL
, NULL
, false);
288 void Spell::EffectEnvirinmentalDMG(uint32 i
)
293 // Note: this hack with damage replace required until GO casting not implemented
294 // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
295 // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
296 damage
= m_spellInfo
->CalculateSimpleValue(i
);
298 m_caster
->CalcAbsorbResist(m_caster
, GetSpellSchoolMask(m_spellInfo
), SPELL_DIRECT_DAMAGE
, damage
, &absorb
, &resist
);
300 m_caster
->SendSpellNonMeleeDamageLog(m_caster
, m_spellInfo
->Id
, damage
, GetSpellSchoolMask(m_spellInfo
), absorb
, resist
, false, 0, false);
301 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
302 ((Player
*)m_caster
)->EnvironmentalDamage(DAMAGE_FIRE
, damage
);
305 void Spell::EffectSchoolDMG(uint32 effect_idx
)
307 if( unitTarget
&& unitTarget
->isAlive())
309 switch(m_spellInfo
->SpellFamilyName
)
311 case SPELLFAMILY_GENERIC
:
313 switch(m_spellInfo
->Id
) // better way to check unknown
315 // Meteor like spells (divided damage to targets)
316 case 24340: case 26558: case 28884: // Meteor
317 case 36837: case 38903: case 41276: // Meteor
318 case 26789: // Shard of the Fallen Star
319 case 31436: // Malevolent Cleave
320 case 35181: // Dive Bomb
321 case 40810: case 43267: case 43268: // Saber Lash
322 case 42384: // Brutal Swipe
323 case 45150: // Meteor Slash
324 case 64422: case 64688: // Sonic Screech
327 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
328 if(ihit
->effectMask
& (1<<effect_idx
))
331 damage
/= count
; // divide to all targets
334 // percent from health with min
335 case 25599: // Thundercrash
337 damage
= unitTarget
->GetHealth() / 2;
342 // Intercept (warrior spell trigger)
346 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.12f
);
352 damage
= unitTarget
->GetMaxHealth() / 2;
358 damage
= unitTarget
->GetMaxHealth() / 10;
361 // Hand of Rekoning (name not have typos ;) )
363 damage
+= uint32(0.5f
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
369 case SPELLFAMILY_MAGE
:
372 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x20000000))
374 m_caster
->CastSpell(m_caster
, 36032, true);
378 case SPELLFAMILY_WARRIOR
:
381 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x40000000000))
383 damage
= uint32(damage
* (m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)) / 100);
386 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000020000000000)) && m_spellInfo
->Category
==1209)
387 damage
+= int32(m_caster
->GetShieldBlockValue());
389 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x10000000000))
391 damage
= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
392 m_caster
->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH
, false);
394 // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
395 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000400))
396 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.207f
);
397 // Heroic Throw ${$m1+$AP*.50}
398 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000100000000))
399 damage
+= uint32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.5f
);
400 // Shockwave ${$m3/100*$AP}
401 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000800000000000))
403 int32 pct
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
405 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * pct
/ 100);
409 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000080))
411 damage
+=int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 12 / 100);
415 case SPELLFAMILY_WARLOCK
:
417 // Incinerate Rank 1 & 2
418 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00004000000000)) && m_spellInfo
->SpellIconID
==2128)
420 // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
421 // Check aura state for speed but aura state set not only for Immolate spell
422 if(unitTarget
->HasAuraState(AURA_STATE_CONFLAGRATE
))
424 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
425 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
428 if((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
429 ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x00000000000004)))
438 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0001000000000000))
441 switch(m_spellInfo
->Id
)
443 case 47897: m_caster
->CastSpell(unitTarget
, 47960, true); break;
444 case 61290: m_caster
->CastSpell(unitTarget
, 61291, true); break;
446 sLog
.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo
->Id
);
450 // Conflagrate - consumes Immolate or Shadowflame
451 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_CONFLAGRATE
)
453 Aura
const* aura
= NULL
; // found req. aura for damage calculation
455 Unit::AuraList
const &mPeriodic
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
456 for(Unit::AuraList::const_iterator i
= mPeriodic
.begin(); i
!= mPeriodic
.end(); ++i
)
458 // for caster applied auras only
459 if ((*i
)->GetSpellProto()->SpellFamilyName
!= SPELLFAMILY_WARLOCK
||
460 (*i
)->GetCasterGUID()!=m_caster
->GetGUID())
464 if ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000000004))
466 aura
= *i
; // it selected always if exist
471 if ((*i
)->GetSpellProto()->SpellFamilyFlags2
& 0x00000002)
472 aura
= *i
; // remember but wait possible Immolate as primary priority
475 // found Immolate or Shadowflame
478 int32 damagetick
= aura
->GetModifier()->m_amount
;
479 damage
+= damagetick
* 4;
481 // Glyph of Conflagrate
482 if (!m_caster
->HasAura(56235))
483 unitTarget
->RemoveAurasByCasterSpell(aura
->GetId(), m_caster
->GetGUID());
489 case SPELLFAMILY_PRIEST
:
491 // Shadow Word: Death - deals damage equal to damage done to caster
492 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000200000000))
493 m_caster
->CastCustomSpell(m_caster
, 32409, &damage
, 0, 0, true);
494 // Improved Mind Blast (Mind Blast in shadow form bonus)
495 else if (m_caster
->m_form
== FORM_SHADOW
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00002000)))
497 Unit::AuraList
const& ImprMindBlast
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
498 for(Unit::AuraList::const_iterator i
= ImprMindBlast
.begin(); i
!= ImprMindBlast
.end(); ++i
)
500 if ((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
501 ((*i
)->GetSpellProto()->SpellIconID
== 95))
503 int chance
= (*i
)->GetSpellProto()->CalculateSimpleValue(1);
504 if (roll_chance_i(chance
))
506 m_caster
->CastSpell(unitTarget
, 48301, true, 0);
513 case SPELLFAMILY_DRUID
:
516 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x000800000)) && m_spellInfo
->SpellVisual
[0]==6587)
518 // converts up to 30 points of energy into ($f1+$AP/410) additional damage
519 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
520 float multiple
= ap
/ 410 + m_spellInfo
->DmgMultiplier
[effect_idx
];
521 damage
+= int32(((Player
*)m_caster
)->GetComboPoints() * ap
* 7 / 100);
522 uint32 energy
= m_caster
->GetPower(POWER_ENERGY
);
523 uint32 used_energy
= energy
> 30 ? 30 : energy
;
524 damage
+= int32(used_energy
* multiple
);
525 m_caster
->SetPower(POWER_ENERGY
,energy
-used_energy
);
528 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000001000) && m_spellInfo
->Effect
[2]==SPELL_EFFECT_ADD_COMBO_POINTS
)
531 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
534 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0010000000000000))
536 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.08f
);
540 case SPELLFAMILY_ROGUE
:
543 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x800000000)))
545 // consume from stack dozes not more that have combo-points
546 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
549 // Lookup for Deadly poison (only attacker applied)
550 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
551 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
552 if( (*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_ROGUE
&&
553 ((*itr
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x10000)) &&
554 (*itr
)->GetCasterGUID()==m_caster
->GetGUID() )
559 // count consumed deadly poison doses at target
562 uint32 spellId
= poison
->GetId();
563 uint32 doses
= poison
->GetStackAmount();
566 for (int i
=0; i
< doses
; i
++)
567 unitTarget
->RemoveSingleSpellAurasFromStack(spellId
);
569 damage
+= int32(((Player
*)m_caster
)->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.09f
* doses
);
571 // Eviscerate and Envenom Bonus Damage (item set effect)
572 if(m_caster
->GetDummyAura(37169))
573 damage
+= ((Player
*)m_caster
)->GetComboPoints()*40;
577 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00020000)) && m_caster
->GetTypeId()==TYPEID_PLAYER
)
579 if(uint32 combo
= ((Player
*)m_caster
)->GetComboPoints())
581 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
582 damage
+= irand(int32(ap
* combo
* 0.03f
), int32(ap
* combo
* 0.07f
));
584 // Eviscerate and Envenom Bonus Damage (item set effect)
585 if(m_caster
->GetDummyAura(37169))
590 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000008))
592 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.21f
);
595 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000002000))
597 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.10f
);
600 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000010000000))
602 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.04f
);
606 case SPELLFAMILY_HUNTER
:
609 if (m_spellInfo
->SpellIconID
== 1578)
611 if (m_caster
->HasAura(57627)) // Charge 6 sec post-affect
615 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x000000002)) && m_spellInfo
->SpellVisual
[0]==342)
617 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
620 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0008000000000000))
622 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
625 else if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000800)) && m_spellInfo
->maxLevel
> 0)
627 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.15f
);
630 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x100000000))
632 int32 base
= irand((int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MINDAMAGE
),(int32
)m_caster
->GetWeaponDamageRange(RANGED_ATTACK
, MAXDAMAGE
));
633 damage
+= int32(float(base
)/m_caster
->GetAttackTime(RANGED_ATTACK
)*2800 + m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
635 // Explosive Trap Effect
636 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000004))
638 damage
+= int32(m_caster
->GetTotalAttackPowerValue(RANGED_ATTACK
)*0.1f
);
642 case SPELLFAMILY_PALADIN
:
644 // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target
645 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x800000000)) && m_spellInfo
->SpellIconID
==2292)
648 switch(m_spellInfo
->Id
)
650 case 53733: debuf_id
= 53742; break;// Judgement of Corruption -> Blood Corruption
651 case 31804: debuf_id
= 31803; break;// Judgement of Vengeance -> Holy Vengeance
655 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
656 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
657 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
658 damage
+=int32(ap
* 0.14f
) + int32(holy
* 22 / 100);
659 // Get stack of Holy Vengeance on the target added by caster
661 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE
);
662 for(Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
664 if( ((*itr
)->GetId() == debuf_id
) && (*itr
)->GetCasterGUID()==m_caster
->GetGUID())
666 stacks
= (*itr
)->GetStackAmount();
670 // + 10% for each application of Holy Vengeance on the target
672 damage
+= damage
* stacks
* 10 /100;
674 // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future
675 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000))
677 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
678 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
679 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
680 damage
+= int32(ap
* 0.07f
) + int32(holy
* 7 / 100);
682 // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix
683 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000008000000000))
685 float ap
= m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
);
686 int32 holy
= m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)) +
687 m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
);
688 damage
+= int32(ap
* 0.15f
) + int32(holy
* 15 / 100);
690 // Hammer of the Righteous
691 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0004000000000000))
693 // Add main hand dps * effect[2] amount
694 float average
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
)) / 2;
695 int32 count
= m_caster
->CalculateSpellDamage(m_spellInfo
, 2, m_spellInfo
->EffectBasePoints
[2], unitTarget
);
696 damage
+= count
* int32(average
* IN_MILISECONDS
) / m_caster
->GetAttackTime(BASE_ATTACK
);
698 // Shield of Righteousness
699 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0010000000000000))
701 damage
+=int32(m_caster
->GetShieldBlockValue());
704 else if (m_spellInfo
->Id
== 54158)
706 // [1 + 0.25 * SPH + 0.16 * AP]
707 damage
+= int32(m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) * 0.16f
);
718 void Spell::EffectDummy(uint32 i
)
720 if (!unitTarget
&& !gameObjTarget
&& !itemTarget
)
723 // selection by spell family
724 switch(m_spellInfo
->SpellFamilyName
)
726 case SPELLFAMILY_GENERIC
:
728 switch(m_spellInfo
->Id
)
730 case 8063: // Deviate Fish
732 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
738 case 1: spell_id
= 8064; break; // Sleepy
739 case 2: spell_id
= 8065; break; // Invigorate
740 case 3: spell_id
= 8066; break; // Shrink
741 case 4: spell_id
= 8067; break; // Party Time!
742 case 5: spell_id
= 8068; break; // Healthy Spirit
744 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
747 case 8213: // Savory Deviate Delight
749 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
756 case 1: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8219 : 8220); break;
758 case 2: spell_id
= (m_caster
->getGender() == GENDER_MALE
? 8221 : 8222); break;
760 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
763 case 8593: // Symbol of life (restore creature to life)
764 case 31225: // Shimmering Vessel (restore creature to life)
766 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
768 ((Creature
*)unitTarget
)->setDeathState(JUST_ALIVED
);
771 case 12162: // Deep wounds
772 case 12850: // (now good common check for this spells)
779 // DW should benefit of attack power, damage percent mods etc.
780 // TODO: check if using offhand damage is correct and if it should be divided by 2
781 if (m_caster
->haveOffhandWeapon() && m_caster
->getAttackTimer(BASE_ATTACK
) > m_caster
->getAttackTimer(OFF_ATTACK
))
782 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE
))/2;
784 damage
= (m_caster
->GetFloatValue(UNIT_FIELD_MINDAMAGE
) + m_caster
->GetFloatValue(UNIT_FIELD_MAXDAMAGE
))/2;
786 switch (m_spellInfo
->Id
)
788 case 12162: damage
*= 0.16f
; break; // Rank 1
789 case 12850: damage
*= 0.32f
; break; // Rank 2
790 case 12868: damage
*= 0.48f
; break; // Rank 3
792 sLog
.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo
->Id
);
796 // get remaining damage of old Deep Wound aura
797 Aura
* deepWound
= unitTarget
->GetAura(12721, 0);
800 int32 remainingTicks
= deepWound
->GetAuraDuration() / deepWound
->GetModifier()->periodictime
;
801 damage
+= remainingTicks
* deepWound
->GetModifier()->m_amount
;
804 // 1 tick/sec * 6 sec = 6 ticks
805 int32 deepWoundsDotBasePoints0
= int32(damage
/ 6);
806 m_caster
->CastCustomSpell(unitTarget
, 12721, &deepWoundsDotBasePoints0
, NULL
, NULL
, true, NULL
);
809 case 13120: // net-o-matic
816 uint32 roll
= urand(0, 99);
818 if (roll
< 2) // 2% for 30 sec self root (off-like chance unknown)
820 else if (roll
< 4) // 2% for 20 sec root, charge to target (off-like chance unknown)
825 m_caster
->CastSpell(unitTarget
,spell_id
,true,NULL
);
828 case 13567: // Dummy Trigger
830 // can be used for different aura triggering, so select by aura
831 if (!m_triggeredByAuraSpell
|| !unitTarget
)
834 switch(m_triggeredByAuraSpell
->Id
)
836 case 26467: // Persistent Shield
837 m_caster
->CastCustomSpell(unitTarget
, 26470, &damage
, NULL
, NULL
, true);
840 sLog
.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell
->Id
);
845 case 15998: // Capture Worg Pup
846 case 29435: // Capture Female Kaliri Hatchling
848 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
851 Creature
* creatureTarget
= (Creature
*)unitTarget
;
853 creatureTarget
->ForcedDespawn();
856 case 16589: // Noggenfogger Elixir
858 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
864 case 1: spell_id
= 16595; break;
865 case 2: spell_id
= 16593; break;
866 default:spell_id
= 16591; break;
869 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
872 case 17251: // Spirit Healer Res
874 if (!unitTarget
|| !m_originalCaster
)
877 if (m_originalCaster
->GetTypeId() == TYPEID_PLAYER
)
879 WorldPacket
data(SMSG_SPIRIT_HEALER_CONFIRM
, 8);
880 data
<< uint64(unitTarget
->GetGUID());
881 ((Player
*)m_originalCaster
)->GetSession()->SendPacket( &data
);
885 case 17271: // Test Fetid Skull
887 if (!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
890 uint32 spell_id
= roll_chance_i(50)
891 ? 17269 // Create Resonating Skull
892 : 17270; // Create Bone Dust
894 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
897 case 20577: // Cannibalize
899 m_caster
->CastSpell(m_caster
, 20578, false, NULL
);
901 case 23019: // Crystal Prison Dummy DND
903 if (!unitTarget
|| !unitTarget
->isAlive() || unitTarget
->GetTypeId() != TYPEID_UNIT
|| ((Creature
*)unitTarget
)->isPet())
906 Creature
* creatureTarget
= (Creature
*)unitTarget
;
907 if (creatureTarget
->isPet())
910 GameObject
* pGameObj
= new GameObject
;
912 Map
*map
= creatureTarget
->GetMap();
914 // create before death for get proper coordinates
915 if (!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), 179644, map
, m_caster
->GetPhaseMask(),
916 creatureTarget
->GetPositionX(), creatureTarget
->GetPositionY(), creatureTarget
->GetPositionZ(),
917 creatureTarget
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
) )
923 pGameObj
->SetRespawnTime(creatureTarget
->GetRespawnTime()-time(NULL
));
924 pGameObj
->SetOwnerGUID(m_caster
->GetGUID() );
925 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel() );
926 pGameObj
->SetSpellId(m_spellInfo
->Id
);
928 creatureTarget
->ForcedDespawn();
930 DEBUG_LOG("AddObject at SpellEfects.cpp EffectDummy");
935 case 23074: // Arcanite Dragonling
938 m_caster
->CastSpell(m_caster
, 19804, true, m_CastItem
);
940 case 23075: // Mithril Mechanical Dragonling
943 m_caster
->CastSpell(m_caster
, 12749, true, m_CastItem
);
945 case 23076: // Mechanical Dragonling
948 m_caster
->CastSpell(m_caster
, 4073, true, m_CastItem
);
950 case 23133: // Gnomish Battle Chicken
953 m_caster
->CastSpell(m_caster
, 13166, true, m_CastItem
);
955 case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
957 int32 r
= irand(0, 119);
958 if (r
< 20) // Transporter Malfunction - 1/6 polymorph
959 m_caster
->CastSpell(m_caster
, 23444, true);
960 else if (r
< 100) // Evil Twin - 4/6 evil twin
961 m_caster
->CastSpell(m_caster
, 23445, true);
962 else // Transporter Malfunction - 1/6 miss the target
963 m_caster
->CastSpell(m_caster
, 36902, true);
966 case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan
967 if (roll_chance_i(50)) // Gadgetzan Transporter - success
968 m_caster
->CastSpell(m_caster
, 23441, true);
969 else // Gadgetzan Transporter Failure - failure
970 m_caster
->CastSpell(m_caster
, 23446, true);
972 case 23645: // Hourglass Sand
973 m_caster
->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze
975 case 23725: // Gift of Life (warrior bwl trinket)
976 m_caster
->CastSpell(m_caster
, 23782, true);
977 m_caster
->CastSpell(m_caster
, 23783, true);
979 case 25860: // Reindeer Transformation
981 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
984 float flyspeed
= m_caster
->GetSpeedRate(MOVE_FLIGHT
);
985 float speed
= m_caster
->GetSpeedRate(MOVE_RUN
);
987 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
989 //5 different spells used depending on mounted speed and if mount can fly or not
990 if (flyspeed
>= 4.1f
)
992 m_caster
->CastSpell(m_caster
, 44827, true); //310% flying Reindeer
993 else if (flyspeed
>= 3.8f
)
995 m_caster
->CastSpell(m_caster
, 44825, true); //280% flying Reindeer
996 else if (flyspeed
>= 1.6f
)
998 m_caster
->CastSpell(m_caster
, 44824, true); //60% flying Reindeer
999 else if (speed
>= 2.0f
)
1001 m_caster
->CastSpell(m_caster
, 25859, true); //100% ground Reindeer
1004 m_caster
->CastSpell(m_caster
, 25858, true); //60% ground Reindeer
1008 case 26074: // Holiday Cheer
1009 // implemented at client side
1011 case 28006: // Arcane Cloaking
1013 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
1014 // Naxxramas Entry Flag Effect DND
1015 m_caster
->CastSpell(unitTarget
, 29294, true);
1018 case 29200: // Purify Helboar Meat
1020 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1023 uint32 spell_id
= roll_chance_i(50)
1024 ? 29277 // Summon Purified Helboar Meat
1025 : 29278; // Summon Toxic Helboar Meat
1027 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
1030 case 29858: // Soulshatter
1031 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
&& unitTarget
->IsHostileTo(m_caster
))
1032 m_caster
->CastSpell(unitTarget
,32835,true);
1034 case 30458: // Nigh Invulnerability
1037 if (roll_chance_i(86)) // Nigh-Invulnerability - success
1038 m_caster
->CastSpell(m_caster
, 30456, true, m_CastItem
);
1039 else // Complete Vulnerability - backfire in 14% casts
1040 m_caster
->CastSpell(m_caster
, 30457, true, m_CastItem
);
1042 case 30507: // Poultryizer
1045 if (roll_chance_i(80)) // Poultryized! - success
1046 m_caster
->CastSpell(unitTarget
, 30501, true, m_CastItem
);
1047 else // Poultryized! - backfire 20%
1048 m_caster
->CastSpell(unitTarget
, 30504, true, m_CastItem
);
1050 case 33060: // Make a Wish
1052 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1055 uint32 spell_id
= 0;
1059 case 1: spell_id
= 33053; break; // Mr Pinchy's Blessing
1060 case 2: spell_id
= 33057; break; // Summon Mighty Mr. Pinchy
1061 case 3: spell_id
= 33059; break; // Summon Furious Mr. Pinchy
1062 case 4: spell_id
= 33062; break; // Tiny Magical Crawdad
1063 case 5: spell_id
= 33064; break; // Mr. Pinchy's Gift
1066 m_caster
->CastSpell(m_caster
, spell_id
, true, NULL
);
1069 case 34665: //Administer Antidote
1071 if (!unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
1073 // Spell has scriptable target but for sure.
1074 if (unitTarget
->GetTypeId() != TYPEID_UNIT
)
1077 uint32 health
= unitTarget
->GetHealth();
1080 unitTarget
->GetPosition(x
, y
, z
);
1081 o
= unitTarget
->GetOrientation();
1082 ((Creature
*)unitTarget
)->ForcedDespawn();
1084 if (Creature
* summon
= m_caster
->SummonCreature(16992, x
, y
, z
, o
,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
,180000))
1086 summon
->SetHealth(health
);
1087 ((Player
*)m_caster
)->RewardPlayerAndGroupAtEvent(16992, summon
);
1090 summon
->AI()->AttackStart(m_caster
);
1094 case 35745: // Socrethar's Stone
1097 switch(m_caster
->GetAreaId())
1099 case 3900: spell_id
= 35743; break; // Socrethar Portal
1100 case 3742: spell_id
= 35744; break; // Socrethar Portal
1104 m_caster
->CastSpell(m_caster
, spell_id
, true);
1107 case 37674: // Chaos Blast
1112 int32 basepoints0
= 100;
1113 m_caster
->CastCustomSpell(unitTarget
, 37675, &basepoints0
, NULL
, NULL
, true);
1116 case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets)
1118 // selecting one from Bloodstained Fortune item
1120 switch(urand(1, 20))
1122 case 1: newitemid
= 32688; break;
1123 case 2: newitemid
= 32689; break;
1124 case 3: newitemid
= 32690; break;
1125 case 4: newitemid
= 32691; break;
1126 case 5: newitemid
= 32692; break;
1127 case 6: newitemid
= 32693; break;
1128 case 7: newitemid
= 32700; break;
1129 case 8: newitemid
= 32701; break;
1130 case 9: newitemid
= 32702; break;
1131 case 10: newitemid
= 32703; break;
1132 case 11: newitemid
= 32704; break;
1133 case 12: newitemid
= 32705; break;
1134 case 13: newitemid
= 32706; break;
1135 case 14: newitemid
= 32707; break;
1136 case 15: newitemid
= 32708; break;
1137 case 16: newitemid
= 32709; break;
1138 case 17: newitemid
= 32710; break;
1139 case 18: newitemid
= 32711; break;
1140 case 19: newitemid
= 32712; break;
1141 case 20: newitemid
= 32713; break;
1146 DoCreateItem(i
, newitemid
);
1149 // Demon Broiled Surprise
1150 /* FIX ME: Required for correct work implementing implicit target 7 (in pair (22,7))
1153 if (m_caster->GetTypeId() != TYPEID_PLAYER)
1156 ((Player*)m_caster)->CastSpell(unitTarget, 43753, true);
1160 case 44875: // Complete Raptor Capture
1162 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1165 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1167 creatureTarget
->ForcedDespawn();
1169 //cast spell Raptor Capture Credit
1170 m_caster
->CastSpell(m_caster
, 42337, true, NULL
);
1173 case 44997: // Converting Sentry
1175 //Converted Sentry Credit
1176 m_caster
->CastSpell(m_caster
, 45009, true);
1179 case 45030: // Impale Emissary
1181 // Emissary of Hate Credit
1182 m_caster
->CastSpell(m_caster
, 45088, true);
1185 case 49357: // Brewfest Mount Transformation
1186 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1189 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
1192 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
1194 // Ram for Alliance, Kodo for Horde
1195 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1197 if (m_caster
->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1199 m_caster
->CastSpell(m_caster
, 43900, true);
1202 m_caster
->CastSpell(m_caster
, 43899, true);
1206 if (((Player
*)m_caster
)->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1208 m_caster
->CastSpell(m_caster
, 49379, true);
1211 m_caster
->CastSpell(m_caster
, 49378, true);
1214 case 50243: // Teach Language
1216 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1219 // spell has a 1/3 chance to trigger one of the below
1220 if (roll_chance_i(66))
1222 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
1224 // 1000001 - gnomish binary
1225 m_caster
->CastSpell(m_caster
, 50242, true);
1229 // 01001000 - goblin binary
1230 m_caster
->CastSpell(m_caster
, 50246, true);
1235 case 51582: //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1237 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1240 if (BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround())
1241 bg
->EventPlayerDroppedFlag((Player
*)m_caster
);
1243 m_caster
->CastSpell(m_caster
, 30452, true, NULL
);
1246 case 51592: // Pickup Primordial Hatchling
1248 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
)
1251 Creature
* creatureTarget
= (Creature
*)unitTarget
;
1253 creatureTarget
->ForcedDespawn();
1257 case 52308: // Take Sputum Sample
1263 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
1264 uint32 reqAuraID
= m_spellInfo
->CalculateSimpleValue(1);
1266 if (m_caster
->HasAura(reqAuraID
,0))
1267 m_caster
->CastSpell(m_caster
, spellID
, true, NULL
);
1271 return; // additional data for dummy[0]
1275 case 52759: // Ancestral Awakening
1278 m_caster
->CastCustomSpell(unitTarget
, 52752, &damage
, NULL
, NULL
, true);
1280 case 52845: // Brewfest Mount Transformation (Faction Swap)
1281 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1284 if (!m_caster
->HasAuraType(SPELL_AURA_MOUNTED
))
1287 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
1289 // Ram for Horde, Kodo for Alliance
1290 if (((Player
*)m_caster
)->GetTeam() == HORDE
)
1292 if (m_caster
->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1293 // Swift Brewfest Ram, 100% Ram
1294 m_caster
->CastSpell(m_caster
, 43900, true);
1296 // Brewfest Ram, 60% Ram
1297 m_caster
->CastSpell(m_caster
, 43899, true);
1301 if (((Player
*)m_caster
)->GetSpeedRate(MOVE_RUN
) >= 2.0f
)
1302 // Great Brewfest Kodo, 100% Kodo
1303 m_caster
->CastSpell(m_caster
, 49379, true);
1305 // Brewfest Riding Kodo, 60% Kodo
1306 m_caster
->CastSpell(m_caster
, 49378, true);
1309 case 53341: // Rune of Cinderglacier
1310 case 53343: // Rune of Razorice
1312 // Runeforging Credit
1313 m_caster
->CastSpell(m_caster
, 54586, true);
1316 case 55004: // Nitro Boosts
1319 if (roll_chance_i(95)) // Nitro Boosts - success
1320 m_caster
->CastSpell(m_caster
, 54861, true, m_CastItem
);
1321 else // Knocked Up - backfire 5%
1322 m_caster
->CastSpell(m_caster
, 46014, true, m_CastItem
);
1324 case 58418: // Portal to Orgrimmar
1325 case 58420: // Portal to Stormwind
1326 return; // implemented in EffectScript[0]
1327 case 59640: // Underbelly Elixir
1329 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1332 uint32 spell_id
= 0;
1335 case 1: spell_id
= 59645; break;
1336 case 2: spell_id
= 59831; break;
1337 case 3: spell_id
= 59843; break;
1339 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
1342 case 60932: // Disengage (one from creature versions)
1345 m_caster
->CastSpell(unitTarget
,60934,true,NULL
);
1347 case 67019: // Flask of the North
1349 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1352 uint32 spell_id
= 0;
1353 switch(m_caster
->getClass())
1356 case CLASS_DEATH_KNIGHT
:
1357 spell_id
= 67018; // STR for Warriors, Death Knights
1361 spell_id
= 67017; // AP for Rogues, Hunters
1366 spell_id
= 67016; // SPD for Priests, Mages, Warlocks
1370 spell_id
= roll_chance_i(50) ? 67016 : 67017;
1375 // random (SPD, STR)
1376 spell_id
= roll_chance_i(50) ? 67016 : 67018;
1379 m_caster
->CastSpell(m_caster
, spell_id
, true);
1385 case SPELLFAMILY_MAGE
:
1386 switch(m_spellInfo
->Id
)
1388 case 11958: // Cold Snap
1390 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1393 // immediately finishes the cooldown on Frost spells
1394 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1395 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1397 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1399 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_MAGE
&&
1400 (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_FROST
) &&
1401 spellInfo
->Id
!= 11958 && GetSpellRecoveryTime(spellInfo
) > 0)
1403 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
, true);
1410 case 32826: // Polymorph Cast Visual
1412 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_UNIT
)
1414 //Polymorph Cast Visual Rank 1
1415 const uint32 spell_list
[6] = {
1416 32813, // Squirrel Form
1417 32816, // Giraffe Form
1418 32817, // Serpent Form
1419 32818, // Dragonhawk Form
1420 32819, // Worgen Form
1423 unitTarget
->CastSpell( unitTarget
, spell_list
[urand(0, 5)], true);
1429 case SPELLFAMILY_WARRIOR
:
1431 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x1)) && m_spellInfo
->SpellVisual
[0] == 867)
1433 int32 chargeBasePoints0
= damage
;
1434 m_caster
->CastCustomSpell(m_caster
, 34846, &chargeBasePoints0
, NULL
, NULL
, true);
1438 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x20000000))
1443 uint32 rage
= m_caster
->GetPower(POWER_RAGE
);
1445 // up to max 30 rage cost
1449 // Glyph of Execution bonus
1450 uint32 rage_modified
= rage
;
1452 if (Aura
*aura
= m_caster
->GetDummyAura(58367))
1453 rage_modified
+= aura
->GetModifier()->m_amount
*10;
1455 int32 basePoints0
= damage
+int32(rage_modified
* m_spellInfo
->DmgMultiplier
[i
] +
1456 m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
)*0.2f
);
1458 m_caster
->CastCustomSpell(unitTarget
, 20647, &basePoints0
, NULL
, NULL
, true, 0);
1461 if(m_caster
->HasAura(52437))
1463 Unit::AuraList
const& auras
= m_caster
->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL
);
1464 for (Unit::AuraList::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
1466 // Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
1467 if ((*itr
)->GetSpellProto()->SpellIconID
== 1989)
1469 // saved rage top stored in next affect
1470 uint32 lastrage
= (*itr
)->GetSpellProto()->CalculateSimpleValue(1)*10;
1478 m_caster
->SetPower(POWER_RAGE
,m_caster
->GetPower(POWER_RAGE
)-rage
);
1482 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000200000))
1486 m_damage
+=m_caster
->CalculateDamage(m_attackType
, false);
1491 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000004000000))
1493 m_damage
+= uint32(damage
* m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
) / 100);
1497 switch(m_spellInfo
->Id
)
1504 m_caster
->CastSpell(unitTarget
, 21887, true);// spell mod
1510 int32 healthModSpellBasePoints0
= int32(m_caster
->GetMaxHealth()*0.3);
1511 m_caster
->CastCustomSpell(m_caster
, 12976, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1517 m_caster
->CastCustomSpell(unitTarget
, 23885, &damage
, NULL
, NULL
, true, NULL
);
1522 case SPELLFAMILY_WARLOCK
:
1524 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000040000))
1526 // In 303 exist spirit depend
1527 uint32 spirit
= uint32(m_caster
->GetStat(STAT_SPIRIT
));
1528 switch (m_spellInfo
->Id
)
1530 case 1454: damage
+=spirit
; break;
1531 case 1455: damage
+=spirit
*15/10; break;
1532 case 1456: damage
+=spirit
*2; break;
1533 case 11687: damage
+=spirit
*25/10; break;
1537 case 57946: damage
+=spirit
*3; break;
1539 sLog
.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo
->Id
);
1542 // Think its not need (also need remove Life Tap from SpellDamageBonus or add new value)
1543 // damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE);
1544 if (unitTarget
&& (int32(unitTarget
->GetHealth()) > damage
))
1546 // Shouldn't Appear in Combat Log
1547 unitTarget
->ModifyHealth(-damage
);
1549 int32 mana
= damage
;
1550 // Improved Life Tap mod
1551 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1552 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1554 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 208)
1555 mana
= ((*itr
)->GetModifier()->m_amount
+ 100)* mana
/ 100;
1557 m_caster
->CastCustomSpell(unitTarget
, 31818, &mana
, NULL
, NULL
, true);
1560 int32 manaFeedVal
= 0;
1561 Unit::AuraList
const& mod
= m_caster
->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER
);
1562 for(Unit::AuraList::const_iterator itr
= mod
.begin(); itr
!= mod
.end(); ++itr
)
1564 if((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_WARLOCK
&& (*itr
)->GetSpellProto()->SpellIconID
== 1982)
1565 manaFeedVal
+= (*itr
)->GetModifier()->m_amount
;
1567 if (manaFeedVal
> 0)
1569 manaFeedVal
= manaFeedVal
* mana
/ 100;
1570 m_caster
->CastCustomSpell(m_caster
, 32553, &manaFeedVal
, NULL
, NULL
, true, NULL
);
1574 SendCastResult(SPELL_FAILED_FIZZLE
);
1578 case SPELLFAMILY_PRIEST
:
1580 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0080000000000000))
1587 switch(m_spellInfo
->Id
)
1589 case 47540: hurt
= 47758; heal
= 47757; break;
1590 case 53005: hurt
= 53001; heal
= 52986; break;
1591 case 53006: hurt
= 53002; heal
= 52987; break;
1592 case 53007: hurt
= 53003; heal
= 52988; break;
1594 sLog
.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo
->Id
);
1597 if (m_caster
->IsFriendlyTo(unitTarget
))
1598 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1600 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1604 case SPELLFAMILY_DRUID
:
1606 if (m_spellInfo
->SpellFamilyFlags2
& UI64LIT(0x00000100))
1608 //Shapeshifting into an animal form or mounting cancels the effect.
1609 if(m_caster
->GetCreatureType() == CREATURE_TYPE_BEAST
|| m_caster
->IsMounted())
1611 if(m_triggeredByAuraSpell
)
1612 m_caster
->RemoveAurasDueToSpell(m_triggeredByAuraSpell
->Id
);
1616 //Any effect which causes you to lose control of your character will supress the starfall effect.
1617 if (m_caster
->hasUnitState(UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
| UNIT_STAT_ROOT
| UNIT_STAT_CONFUSED
))
1620 switch(m_spellInfo
->Id
)
1622 case 50286: m_caster
->CastSpell(unitTarget
, 50288, true); return;
1623 case 53196: m_caster
->CastSpell(unitTarget
, 53191, true); return;
1624 case 53197: m_caster
->CastSpell(unitTarget
, 53194, true); return;
1625 case 53198: m_caster
->CastSpell(unitTarget
, 53195, true); return;
1627 sLog
.outError("Spell::EffectDummy: Unhandeled Starfall spell rank %u",m_spellInfo
->Id
);
1632 case SPELLFAMILY_ROGUE
:
1633 switch(m_spellInfo
->Id
)
1637 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1640 Player
*pCaster
= ((Player
*)m_caster
);
1642 Item
*item
= pCaster
->GetWeaponForAttack(OFF_ATTACK
);
1646 // all poison enchantments is temporary
1647 uint32 enchant_id
= item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
);
1651 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
1655 for (int s
=0;s
<3;s
++)
1657 if (pEnchant
->type
[s
]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL
)
1660 SpellEntry
const* combatEntry
= sSpellStore
.LookupEntry(pEnchant
->spellid
[s
]);
1661 if (!combatEntry
|| combatEntry
->Dispel
!= DISPEL_POISON
)
1664 m_caster
->CastSpell(unitTarget
, combatEntry
, true, item
);
1667 m_caster
->CastSpell(unitTarget
, 5940, true);
1670 case 14185: // Preparation
1672 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1675 //immediately finishes the cooldown on certain Rogue abilities
1676 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1677 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1679 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1681 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000024000000860)))
1682 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
,true);
1688 case 31231: // Cheat Death
1690 m_caster
->CastSpell(m_caster
, 45182, true);
1695 case SPELLFAMILY_HUNTER
:
1697 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x100000000))
1699 if (!unitTarget
|| !unitTarget
->isAlive())
1704 // check dazed affect
1705 Unit::AuraList
const& decSpeedList
= unitTarget
->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED
);
1706 for(Unit::AuraList::const_iterator iter
= decSpeedList
.begin(); iter
!= decSpeedList
.end(); ++iter
)
1708 if ((*iter
)->GetSpellProto()->SpellIconID
==15 && (*iter
)->GetSpellProto()->Dispel
==0)
1721 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000400000000000))
1723 Unit
* target
= unitTarget
;
1725 switch(m_spellInfo
->Id
)
1727 case 57635: spellid
= 57636; break; // one from creature cases
1728 case 61507: spellid
= 61508; break; // one from creature cases
1730 sLog
.outError("Spell %u not handled propertly in EffectDummy(Disengage)",m_spellInfo
->Id
);
1733 if (!target
|| !target
->isAlive())
1735 m_caster
->CastSpell(target
,spellid
,true,NULL
);
1738 switch(m_spellInfo
->Id
)
1740 case 23989: // Readiness talent
1742 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1745 //immediately finishes the cooldown for hunter abilities
1746 const SpellCooldowns
& cm
= ((Player
*)m_caster
)->GetSpellCooldownMap();
1747 for (SpellCooldowns::const_iterator itr
= cm
.begin(); itr
!= cm
.end();)
1749 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
1751 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_HUNTER
&& spellInfo
->Id
!= 23989 && GetSpellRecoveryTime(spellInfo
) > 0 )
1752 ((Player
*)m_caster
)->RemoveSpellCooldown((itr
++)->first
,true);
1758 case 37506: // Scatter Shot
1760 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1763 // break Auto Shot and autohit
1764 m_caster
->InterruptSpell(CURRENT_AUTOREPEAT_SPELL
);
1765 m_caster
->AttackStop();
1766 ((Player
*)m_caster
)->SendAttackSwingCancelAttack();
1774 int32 healthModSpellBasePoints0
= int32(unitTarget
->GetMaxHealth() * 0.3);
1775 unitTarget
->CastCustomSpell(unitTarget
, 53479, &healthModSpellBasePoints0
, NULL
, NULL
, true, NULL
);
1781 Pet
* pet
= m_caster
->GetPet();
1782 if (!pet
|| !unitTarget
)
1785 pet
->CastSpell(unitTarget
, m_spellInfo
->CalculateSimpleValue(i
), true);
1790 case SPELLFAMILY_PALADIN
:
1791 switch(m_spellInfo
->SpellIconID
)
1793 case 156: // Holy Shock
1801 switch(m_spellInfo
->Id
)
1803 case 20473: hurt
= 25912; heal
= 25914; break;
1804 case 20929: hurt
= 25911; heal
= 25913; break;
1805 case 20930: hurt
= 25902; heal
= 25903; break;
1806 case 27174: hurt
= 27176; heal
= 27175; break;
1807 case 33072: hurt
= 33073; heal
= 33074; break;
1808 case 48824: hurt
= 48822; heal
= 48820; break;
1809 case 48825: hurt
= 48823; heal
= 48821; break;
1811 sLog
.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo
->Id
);
1815 if (m_caster
->IsFriendlyTo(unitTarget
))
1816 m_caster
->CastSpell(unitTarget
, heal
, true, 0);
1818 m_caster
->CastSpell(unitTarget
, hurt
, true, 0);
1822 case 561: // Judgement of command
1827 uint32 spell_id
= m_currentBasePoints
[i
]+1;
1828 SpellEntry
const* spell_proto
= sSpellStore
.LookupEntry(spell_id
);
1832 m_caster
->CastSpell(unitTarget
, spell_proto
, true, NULL
);
1837 switch(m_spellInfo
->Id
)
1839 // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
1844 m_damage
+=int32(0.2f
*m_caster
->GetTotalAttackPowerValue(BASE_ATTACK
));
1847 case 31789: // Righteous Defense (step 1)
1849 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
1851 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1855 // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1856 Unit
* friendTarget
= !unitTarget
|| unitTarget
->IsFriendlyTo(m_caster
) ? unitTarget
: unitTarget
->getVictim();
1859 Player
* player
= friendTarget
->GetCharmerOrOwnerPlayerOrPlayerItself();
1860 if (!player
|| !player
->IsInSameRaidWith((Player
*)m_caster
))
1861 friendTarget
= NULL
;
1864 // non-standard cast requirement check
1865 if (!friendTarget
|| friendTarget
->getAttackers().empty())
1867 ((Player
*)m_caster
)->RemoveSpellCooldown(m_spellInfo
->Id
,true);
1868 SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT
);
1872 // Righteous Defense (step 2) (in old version 31980 dummy effect)
1873 // Clear targets for eff 1
1874 for(std::list
<TargetInfo
>::iterator ihit
= m_UniqueTargetInfo
.begin();ihit
!= m_UniqueTargetInfo
.end();++ihit
)
1875 ihit
->effectMask
&= ~(1<<1);
1877 // not empty (checked), copy
1878 Unit::AttackerSet attackers
= friendTarget
->getAttackers();
1880 // selected from list 3
1881 for(int i
= 0; i
< std::min(size_t(3),attackers
.size()); ++i
)
1883 Unit::AttackerSet::iterator aItr
= attackers
.begin();
1884 std::advance(aItr
, rand() % attackers
.size());
1885 AddUnitTarget((*aItr
), 1);
1886 attackers
.erase(aItr
);
1889 // now let next effect cast spell at each target.
1892 case 37877: // Blessing of Faith
1897 uint32 spell_id
= 0;
1898 switch(unitTarget
->getClass())
1900 case CLASS_DRUID
: spell_id
= 37878; break;
1901 case CLASS_PALADIN
: spell_id
= 37879; break;
1902 case CLASS_PRIEST
: spell_id
= 37880; break;
1903 case CLASS_SHAMAN
: spell_id
= 37881; break;
1904 default: return; // ignore for not healing classes
1907 m_caster
->CastSpell(m_caster
, spell_id
, true);
1912 case SPELLFAMILY_SHAMAN
:
1914 if ((m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000004000000)) && m_spellInfo
->SpellIconID
==1673)
1917 m_caster
->CastSpell(unitTarget
, 52025, true);
1920 // Healing Stream Totem
1921 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000002000))
1924 m_caster
->CastCustomSpell(unitTarget
, 52042, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1927 // Mana Spring Totem
1928 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000))
1930 if (!unitTarget
|| unitTarget
->getPowerType()!=POWER_MANA
)
1932 m_caster
->CastCustomSpell(unitTarget
, 52032, &damage
, 0, 0, true, 0, 0, m_originalCasterGUID
);
1935 if (m_spellInfo
->Id
== 39610) // Mana Tide Totem effect
1937 if (!unitTarget
|| unitTarget
->getPowerType() != POWER_MANA
)
1939 // Glyph of Mana Tide
1940 if (Unit
*owner
= m_caster
->GetOwner())
1941 if (Aura
*dummy
= owner
->GetDummyAura(55441))
1942 damage
+=dummy
->GetModifier()->m_amount
;
1943 // Regenerate 6% of Total Mana Every 3 secs
1944 int32 EffectBasePoints0
= unitTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
1945 m_caster
->CastCustomSpell(unitTarget
, 39609, &EffectBasePoints0
, NULL
, NULL
, true, NULL
, NULL
, m_originalCasterGUID
);
1949 if (m_spellInfo
->SpellFamilyFlags2
& 0x00000004)
1951 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
1953 Item
*item
= ((Player
*)m_caster
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_OFFHAND
);
1956 // Damage is increased if your off-hand weapon is enchanted with Flametongue.
1957 Unit::AuraList
const& auraDummy
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
1958 for(Unit::AuraList::const_iterator itr
= auraDummy
.begin(); itr
!= auraDummy
.end(); ++itr
)
1960 if ((*itr
)->GetSpellProto()->SpellFamilyName
==SPELLFAMILY_SHAMAN
&&
1961 ((*itr
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000200000)) &&
1962 (*itr
)->GetCastItemGUID() == item
->GetGUID())
1964 m_damage
+= m_damage
* damage
/ 100;
1972 case SPELLFAMILY_DEATHKNIGHT
:
1974 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x002000))
1976 if (m_caster
->IsFriendlyTo(unitTarget
))
1978 if (unitTarget
->GetCreatureType() != CREATURE_TYPE_UNDEAD
)
1981 int32 bp
= damage
* 1.5f
;
1982 m_caster
->CastCustomSpell(unitTarget
, 47633, &bp
, NULL
, NULL
, true);
1987 m_caster
->CastCustomSpell(unitTarget
, 47632, &bp
, NULL
, NULL
, true);
1992 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000100000000000))
1994 m_caster
->CastSpell(m_caster
, 51209, true);
1998 else if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000010))
2001 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
2002 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
2004 if (itr
->second
->GetSpellProto()->Dispel
== DISPEL_DISEASE
&&
2005 itr
->second
->GetCasterGUID() == m_caster
->GetGUID() &&
2006 IsSpellLastAuraEffect(itr
->second
->GetSpellProto(), itr
->second
->GetEffIndex()))
2015 int32 bp
= count
* m_caster
->GetMaxHealth() * m_spellInfo
->DmgMultiplier
[0] / 100;
2016 m_caster
->CastCustomSpell(m_caster
, 45470, &bp
, NULL
, NULL
, true);
2023 if (PetAura
const* petSpell
= sSpellMgr
.GetPetAura(m_spellInfo
->Id
, i
))
2025 m_caster
->AddPetAura(petSpell
);
2029 // Script based implementation. Must be used only for not good for implementation in core spell effects
2030 // So called only for not proccessed cases
2032 Script
->EffectDummyGameObj(m_caster
, m_spellInfo
->Id
, i
, gameObjTarget
);
2033 else if (unitTarget
&& unitTarget
->GetTypeId()==TYPEID_UNIT
)
2034 Script
->EffectDummyCreature(m_caster
, m_spellInfo
->Id
, i
, (Creature
*)unitTarget
);
2035 else if (itemTarget
)
2036 Script
->EffectDummyItem(m_caster
, m_spellInfo
->Id
, i
, itemTarget
);
2039 void Spell::EffectTriggerSpellWithValue(uint32 i
)
2041 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
2044 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2048 sLog
.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2053 m_caster
->CastCustomSpell(unitTarget
,triggered_spell_id
,&bp
,&bp
,&bp
,true,NULL
,NULL
,m_originalCasterGUID
);
2056 void Spell::EffectTriggerRitualOfSummoning(uint32 i
)
2058 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
2059 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2063 sLog
.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2069 m_caster
->CastSpell(unitTarget
,spellInfo
,false);
2072 void Spell::EffectForceCast(uint32 i
)
2077 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[i
];
2080 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2084 sLog
.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2088 unitTarget
->CastSpell(unitTarget
, spellInfo
, true, NULL
, NULL
, m_originalCasterGUID
);
2091 void Spell::EffectTriggerSpell(uint32 effIndex
)
2093 // only unit case known
2096 if(gameObjTarget
|| itemTarget
)
2097 sLog
.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo
->Id
);
2101 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effIndex
];
2104 switch(triggered_spell_id
)
2106 // Vanish (not exist)
2109 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
2110 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
2111 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
2113 // if this spell is given to NPC it must handle rest by it's own AI
2114 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2117 // get highest rank of the Stealth spell
2119 const PlayerSpellMap
& sp_list
= ((Player
*)unitTarget
)->GetSpellMap();
2120 for (PlayerSpellMap::const_iterator itr
= sp_list
.begin(); itr
!= sp_list
.end(); ++itr
)
2122 // only highest rank is shown in spell book, so simply check if shown in spell book
2123 if (!itr
->second
->active
|| itr
->second
->disabled
|| itr
->second
->state
== PLAYERSPELL_REMOVED
)
2126 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
2130 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_STEALTH
)
2132 spellId
= spellInfo
->Id
;
2137 // no Stealth spell found
2141 // reset cooldown on it if needed
2142 if (((Player
*)unitTarget
)->HasSpellCooldown(spellId
))
2143 ((Player
*)unitTarget
)->RemoveSpellCooldown(spellId
);
2145 m_caster
->CastSpell(unitTarget
, spellId
, true);
2149 case 23770: // Sayge's Dark Fortune of *
2150 // not exist, common cooldown can be implemented in scripts if need.
2152 // Brittle Armor - (need add max stack of 24575 Brittle Armor)
2156 SpellEntry
const* spell
= sSpellStore
.LookupEntry(24575);
2160 for (int j
=0; j
< spell
->StackAmount
; ++j
)
2161 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2164 // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
2168 SpellEntry
const* spell
= sSpellStore
.LookupEntry(26464);
2172 for (int j
=0; j
< spell
->StackAmount
; ++j
)
2173 m_caster
->CastSpell(unitTarget
, spell
->Id
, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2176 // Righteous Defense
2179 m_caster
->CastSpell(unitTarget
, 31790, true, m_CastItem
, NULL
, m_originalCasterGUID
);
2185 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
2186 for(Unit::AuraMap::iterator iter
= Auras
.begin(); iter
!= Auras
.end(); ++iter
)
2188 // remove all harmful spells on you...
2189 if( // ignore positive and passive auras
2190 !iter
->second
->IsPositive() && !iter
->second
->IsPassive() &&
2191 // ignore physical auras
2192 (GetSpellSchoolMask(iter
->second
->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL
)==0 )
2194 m_caster
->RemoveAurasDueToSpell(iter
->second
->GetSpellProto()->Id
);
2195 iter
= Auras
.begin();
2200 // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
2203 if (Unit
*pet
= unitTarget
->GetPet())
2204 pet
->CastSpell(pet
, 28305, true);
2210 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2213 sLog
.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo
->Id
,triggered_spell_id
);
2217 // select formal caster for triggered spell
2218 Unit
* caster
= m_caster
;
2220 // some triggered spells require specific equipment
2221 if (spellInfo
->EquippedItemClass
>=0 && m_caster
->GetTypeId()==TYPEID_PLAYER
)
2223 // main hand weapon required
2224 if (spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_MAIN_HAND
)
2226 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(BASE_ATTACK
, true, false);
2228 // skip spell if no weapon in slot or broken
2232 // skip spell if weapon not fit to triggered spell
2233 if (!item
->IsFitToSpellRequirements(spellInfo
))
2237 // offhand hand weapon required
2238 if (spellInfo
->AttributesEx3
& SPELL_ATTR_EX3_REQ_OFFHAND
)
2240 Item
* item
= ((Player
*)m_caster
)->GetWeaponForAttack(OFF_ATTACK
, true, false);
2242 // skip spell if no weapon in slot or broken
2246 // skip spell if weapon not fit to triggered spell
2247 if (!item
->IsFitToSpellRequirements(spellInfo
))
2253 // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
2254 // so this just for speedup places in else
2255 caster
= IsSpellWithCasterSourceTargetsOnly(spellInfo
) ? unitTarget
: m_caster
;
2258 caster
->CastSpell(unitTarget
,spellInfo
,true,NULL
,NULL
,m_originalCasterGUID
);
2261 void Spell::EffectTriggerMissileSpell(uint32 effect_idx
)
2263 uint32 triggered_spell_id
= m_spellInfo
->EffectTriggerSpell
[effect_idx
];
2266 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( triggered_spell_id
);
2270 sLog
.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u",
2271 m_spellInfo
->Id
,effect_idx
,triggered_spell_id
);
2276 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo
->Id
);
2278 m_caster
->CastSpell(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, spellInfo
, true, m_CastItem
, 0, m_originalCasterGUID
);
2281 void Spell::EffectJump(uint32 i
)
2283 if(m_caster
->isInFlight())
2286 // Init dest coordinates
2288 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
2290 x
= m_targets
.m_destX
;
2291 y
= m_targets
.m_destY
;
2292 z
= m_targets
.m_destZ
;
2294 if(m_spellInfo
->EffectImplicitTargetA
[i
] == TARGET_BEHIND_VICTIM
)
2296 // explicit cast data from client or server-side cast
2297 // some spell at client send caster
2298 Unit
* pTarget
= NULL
;
2299 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=m_caster
)
2300 pTarget
= m_targets
.getUnitTarget();
2301 else if(unitTarget
->getVictim())
2302 pTarget
= m_caster
->getVictim();
2303 else if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
2304 pTarget
= ObjectAccessor::GetUnit(*m_caster
, ((Player
*)m_caster
)->GetSelection());
2306 o
= pTarget
? pTarget
->GetOrientation() : m_caster
->GetOrientation();
2309 o
= m_caster
->GetOrientation();
2313 unitTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2314 o
= m_caster
->GetOrientation();
2316 else if(gameObjTarget
)
2318 gameObjTarget
->GetContactPoint(m_caster
,x
,y
,z
,CONTACT_DISTANCE
);
2319 o
= m_caster
->GetOrientation();
2323 sLog
.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo
->Id
);
2327 m_caster
->NearTeleportTo(x
, y
, z
, o
, true);
2330 void Spell::EffectTeleportUnits(uint32 i
)
2332 if(!unitTarget
|| unitTarget
->isInFlight())
2335 switch (m_spellInfo
->EffectImplicitTargetB
[i
])
2337 case TARGET_INNKEEPER_COORDINATES
:
2339 // Only players can teleport to innkeeper
2340 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2343 ((Player
*)unitTarget
)->TeleportToHomebind(unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
2346 case TARGET_AREAEFFECT_INSTANT
: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
2347 case TARGET_TABLE_X_Y_Z_COORDINATES
:
2349 SpellTargetPosition
const* st
= sSpellMgr
.GetSpellTargetPosition(m_spellInfo
->Id
);
2352 sLog
.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo
->Id
);
2356 if(st
->target_mapId
==unitTarget
->GetMapId())
2357 unitTarget
->NearTeleportTo(st
->target_X
,st
->target_Y
,st
->target_Z
,st
->target_Orientation
,unitTarget
==m_caster
);
2358 else if(unitTarget
->GetTypeId()==TYPEID_PLAYER
)
2359 ((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);
2362 case TARGET_BEHIND_VICTIM
:
2364 Unit
*pTarget
= NULL
;
2366 // explicit cast data from client or server-side cast
2367 // some spell at client send caster
2368 if(m_targets
.getUnitTarget() && m_targets
.getUnitTarget()!=unitTarget
)
2369 pTarget
= m_targets
.getUnitTarget();
2370 else if(unitTarget
->getVictim())
2371 pTarget
= unitTarget
->getVictim();
2372 else if(unitTarget
->GetTypeId() == TYPEID_PLAYER
)
2373 pTarget
= ObjectAccessor::GetUnit(*unitTarget
, ((Player
*)unitTarget
)->GetSelection());
2375 // Init dest coordinates
2376 float x
= m_targets
.m_destX
;
2377 float y
= m_targets
.m_destY
;
2378 float z
= m_targets
.m_destZ
;
2379 float orientation
= pTarget
? pTarget
->GetOrientation() : unitTarget
->GetOrientation();
2380 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2385 // If not exist data for dest location - return
2386 if(!(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
))
2388 sLog
.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u", i
, m_spellInfo
->EffectImplicitTargetB
[i
], m_spellInfo
->Id
);
2391 // Init dest coordinates
2392 float x
= m_targets
.m_destX
;
2393 float y
= m_targets
.m_destY
;
2394 float z
= m_targets
.m_destZ
;
2395 float orientation
= unitTarget
->GetOrientation();
2397 unitTarget
->NearTeleportTo(x
,y
,z
,orientation
,unitTarget
==m_caster
);
2402 // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
2403 switch ( m_spellInfo
->Id
)
2405 // Dimensional Ripper - Everlook
2408 int32 r
= irand(0, 119);
2409 if ( r
>= 70 ) // 7/12 success
2411 if ( r
< 100 ) // 4/12 evil twin
2412 m_caster
->CastSpell(m_caster
, 23445, true);
2414 m_caster
->CastSpell(m_caster
, 23449, true);
2418 // Ultrasafe Transporter: Toshley's Station
2421 if ( roll_chance_i(50) ) // 50% success
2423 int32 rand_eff
= urand(1, 7);
2427 // soul split - evil
2428 m_caster
->CastSpell(m_caster
, 36900, true);
2431 // soul split - good
2432 m_caster
->CastSpell(m_caster
, 36901, true);
2435 // Increase the size
2436 m_caster
->CastSpell(m_caster
, 36895, true);
2439 // Decrease the size
2440 m_caster
->CastSpell(m_caster
, 36893, true);
2445 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2446 m_caster
->CastSpell(m_caster
, 36897, true);
2448 m_caster
->CastSpell(m_caster
, 36899, true);
2453 m_caster
->CastSpell(m_caster
, 36940, true);
2457 m_caster
->CastSpell(m_caster
, 23445, true);
2463 // Dimensional Ripper - Area 52
2466 if ( roll_chance_i(50) ) // 50% success
2468 int32 rand_eff
= urand(1, 4);
2472 // soul split - evil
2473 m_caster
->CastSpell(m_caster
, 36900, true);
2476 // soul split - good
2477 m_caster
->CastSpell(m_caster
, 36901, true);
2480 // Increase the size
2481 m_caster
->CastSpell(m_caster
, 36895, true);
2486 if (((Player
*)m_caster
)->GetTeam() == ALLIANCE
)
2487 m_caster
->CastSpell(m_caster
, 36897, true);
2489 m_caster
->CastSpell(m_caster
, 36899, true);
2499 void Spell::EffectApplyAura(uint32 i
)
2504 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2505 if ( (!unitTarget
->isAlive() && !(IsDeathOnlySpell(m_spellInfo
) || IsDeathPersistentSpell(m_spellInfo
))) &&
2506 (unitTarget
->GetTypeId() != TYPEID_PLAYER
|| !((Player
*)unitTarget
)->GetSession()->PlayerLoading()) )
2509 Unit
* caster
= m_originalCaster
? m_originalCaster
: m_caster
;
2513 sLog
.outDebug("Spell: Aura is: %u", m_spellInfo
->EffectApplyAuraName
[i
]);
2515 Aura
* Aur
= CreateAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, caster
, m_CastItem
);
2517 // Now Reduce spell duration using data received at spell hit
2518 int32 duration
= Aur
->GetAuraMaxDuration();
2519 int32 limitduration
= GetDiminishingReturnsLimitDuration(m_diminishGroup
,m_spellInfo
);
2520 unitTarget
->ApplyDiminishingToDuration(m_diminishGroup
, duration
, m_caster
, m_diminishLevel
,limitduration
);
2521 Aur
->setDiminishGroup(m_diminishGroup
);
2523 // if Aura removed and deleted, do not continue.
2524 if(duration
== 0 && !(Aur
->IsPermanent()))
2530 if(duration
!= Aur
->GetAuraMaxDuration())
2532 Aur
->SetAuraMaxDuration(duration
);
2533 Aur
->SetAuraDuration(duration
);
2536 unitTarget
->AddAura(Aur
);
2539 void Spell::EffectUnlearnSpecialization( uint32 i
)
2541 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2544 Player
*_player
= (Player
*)unitTarget
;
2545 uint32 spellToUnlearn
= m_spellInfo
->EffectTriggerSpell
[i
];
2547 _player
->removeSpell(spellToUnlearn
);
2549 sLog
.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player
->GetGUIDLow(), spellToUnlearn
, m_caster
->GetGUIDLow() );
2552 void Spell::EffectPowerDrain(uint32 i
)
2554 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2557 Powers drain_power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2561 if(!unitTarget
->isAlive())
2563 if(unitTarget
->getPowerType() != drain_power
)
2568 uint32 curPower
= unitTarget
->GetPower(drain_power
);
2570 //add spell damage bonus
2571 damage
=m_caster
->SpellDamageBonus(unitTarget
,m_spellInfo
,uint32(damage
),SPELL_DIRECT_DAMAGE
);
2573 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2574 uint32 power
= damage
;
2575 if (drain_power
== POWER_MANA
)
2576 power
-= unitTarget
->GetSpellCritDamageReduction(power
);
2579 if(curPower
< power
)
2580 new_damage
= curPower
;
2584 unitTarget
->ModifyPower(drain_power
,-new_damage
);
2586 // Don`t restore from self drain
2587 if(drain_power
== POWER_MANA
&& m_caster
!= unitTarget
)
2589 float manaMultiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2590 if(manaMultiplier
==0)
2593 if(Player
*modOwner
= m_caster
->GetSpellModOwner())
2594 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, manaMultiplier
);
2596 int32 gain
= int32(new_damage
* manaMultiplier
);
2598 m_caster
->EnergizeBySpell(m_caster
, m_spellInfo
->Id
, gain
, POWER_MANA
);
2602 void Spell::EffectSendEvent(uint32 EffectIndex
)
2605 we do not handle a flag dropping or clicking on flag in battleground by sendevent system
2607 sLog
.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo
->EffectMiscValue
[EffectIndex
], m_spellInfo
->Id
);
2608 m_caster
->GetMap()->ScriptsStart(sEventScripts
, m_spellInfo
->EffectMiscValue
[EffectIndex
], m_caster
, focusObject
);
2611 void Spell::EffectPowerBurn(uint32 i
)
2613 if (m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2616 Powers powertype
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
2620 if (!unitTarget
->isAlive())
2622 if (unitTarget
->getPowerType()!=powertype
)
2627 // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
2628 if (m_spellInfo
->ManaCostPercentage
)
2630 uint32 maxdamage
= m_caster
->GetMaxPower(powertype
) * damage
* 2 / 100;
2631 damage
= unitTarget
->GetMaxPower(powertype
) * damage
/ 100;
2632 if(damage
> maxdamage
) damage
= maxdamage
;
2635 int32 curPower
= int32(unitTarget
->GetPower(powertype
));
2637 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2638 uint32 power
= damage
;
2639 if (powertype
== POWER_MANA
)
2640 power
-= unitTarget
->GetSpellCritDamageReduction(power
);
2642 int32 new_damage
= (curPower
< power
) ? curPower
: power
;
2644 unitTarget
->ModifyPower(powertype
, -new_damage
);
2645 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2647 if (Player
*modOwner
= m_caster
->GetSpellModOwner())
2648 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2650 new_damage
= int32(new_damage
* multiplier
);
2651 m_damage
+= new_damage
;
2654 void Spell::EffectHeal( uint32
/*i*/ )
2656 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2658 // Try to get original caster
2659 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2661 // Skip if m_originalCaster not available
2665 int32 addhealth
= damage
;
2667 // Vessel of the Naaru (Vial of the Sunwell trinket)
2668 if (m_spellInfo
->Id
== 45064)
2670 // Amount of heal - depends from stacked Holy Energy
2671 int damageAmount
= 0;
2672 Unit::AuraList
const& mDummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
2673 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin(); i
!= mDummyAuras
.end(); ++i
)
2674 if ((*i
)->GetId() == 45062)
2675 damageAmount
+=(*i
)->GetModifier()->m_amount
;
2677 m_caster
->RemoveAurasDueToSpell(45062);
2679 addhealth
+= damageAmount
;
2681 // Death Pact (percent heal)
2682 else if (m_spellInfo
->Id
==48743)
2683 addhealth
= addhealth
* unitTarget
->GetMaxHealth() / 100;
2684 // Swiftmend - consumes Regrowth or Rejuvenation
2685 else if (m_spellInfo
->TargetAuraState
== AURA_STATE_SWIFTMEND
&& unitTarget
->HasAuraState(AURA_STATE_SWIFTMEND
))
2687 Unit::AuraList
const& RejorRegr
= unitTarget
->GetAurasByType(SPELL_AURA_PERIODIC_HEAL
);
2688 // find most short by duration
2689 Aura
*targetAura
= NULL
;
2690 for(Unit::AuraList::const_iterator i
= RejorRegr
.begin(); i
!= RejorRegr
.end(); ++i
)
2692 if ((*i
)->GetSpellProto()->SpellFamilyName
== SPELLFAMILY_DRUID
&&
2693 // Regrowth or Rejuvenation 0x40 | 0x10
2694 ((*i
)->GetSpellProto()->SpellFamilyFlags
& UI64LIT(0x0000000000000050)))
2696 if (!targetAura
|| (*i
)->GetAuraDuration() < targetAura
->GetAuraDuration())
2703 sLog
.outError("Target (GUID: %u TypeId: %u) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget
->GetGUIDLow(), unitTarget
->GetTypeId());
2709 if(targetAura
->GetSpellProto()->EffectApplyAuraName
[idx
] == SPELL_AURA_PERIODIC_HEAL
)
2714 int32 tickheal
= caster
->SpellHealingBonus(unitTarget
, targetAura
->GetSpellProto(), targetAura
->GetModifier()->m_amount
, DOT
);
2715 int32 tickcount
= GetSpellDuration(targetAura
->GetSpellProto()) / targetAura
->GetSpellProto()->EffectAmplitude
[idx
];
2717 // Glyph of Swiftmend
2718 if (!caster
->HasAura(54824))
2719 unitTarget
->RemoveAurasDueToSpell(targetAura
->GetId());
2721 addhealth
+= tickheal
* tickcount
;
2724 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, addhealth
, HEAL
);
2726 m_healing
+=addhealth
;
2730 void Spell::EffectHealPct( uint32
/*i*/ )
2732 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2734 // Try to get original caster
2735 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2737 // Skip if m_originalCaster not available
2741 uint32 addhealth
= unitTarget
->GetMaxHealth() * damage
/ 100;
2742 if (Player
* modOwner
= m_caster
->GetSpellModOwner())
2743 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DAMAGE
, addhealth
, this);
2745 int32 gain
= caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
2746 unitTarget
->getHostileRefManager().threatAssist(m_caster
, float(gain
) * 0.5f
, m_spellInfo
);
2750 void Spell::EffectHealMechanical( uint32
/*i*/ )
2752 // Mechanic creature type should be correctly checked by targetCreatureType field
2753 if (unitTarget
&& unitTarget
->isAlive() && damage
>= 0)
2755 // Try to get original caster
2756 Unit
*caster
= m_originalCasterGUID
? m_originalCaster
: m_caster
;
2758 // Skip if m_originalCaster not available
2762 uint32 addhealth
= caster
->SpellHealingBonus(unitTarget
, m_spellInfo
, uint32(damage
), HEAL
);
2763 caster
->DealHeal(unitTarget
, addhealth
, m_spellInfo
);
2767 void Spell::EffectHealthLeech(uint32 i
)
2771 if (!unitTarget
->isAlive())
2777 sLog
.outDebug("HealthLeech :%i", damage
);
2779 uint32 curHealth
= unitTarget
->GetHealth();
2780 damage
= m_caster
->SpellNonMeleeDamageLog(unitTarget
, m_spellInfo
->Id
, damage
);
2781 if (curHealth
< damage
)
2784 float multiplier
= m_spellInfo
->EffectMultipleValue
[i
];
2786 if (Player
*modOwner
= m_caster
->GetSpellModOwner())
2787 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_MULTIPLE_VALUE
, multiplier
);
2789 uint32 heal
= uint32(damage
*multiplier
);
2790 if (m_caster
->isAlive())
2792 heal
= m_caster
->SpellHealingBonus(m_caster
, m_spellInfo
, heal
, HEAL
);
2793 m_caster
->DealHeal(m_caster
, heal
, m_spellInfo
);
2797 void Spell::DoCreateItem(uint32 i
, uint32 itemtype
)
2799 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
2802 Player
* player
= (Player
*)unitTarget
;
2804 uint32 newitemid
= itemtype
;
2805 ItemPrototype
const *pProto
= ObjectMgr::GetItemPrototype( newitemid
);
2808 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2812 // bg reward have some special in code work
2814 switch(m_spellInfo
->Id
)
2816 case SPELL_AV_MARK_WINNER
:
2817 case SPELL_AV_MARK_LOSER
:
2818 bgType
= BATTLEGROUND_AV
;
2820 case SPELL_WS_MARK_WINNER
:
2821 case SPELL_WS_MARK_LOSER
:
2822 bgType
= BATTLEGROUND_WS
;
2824 case SPELL_AB_MARK_WINNER
:
2825 case SPELL_AB_MARK_LOSER
:
2826 bgType
= BATTLEGROUND_AB
;
2834 // TODO: maybe all this can be replaced by using correct calculated `damage` value
2835 if(pProto
->Class
!= ITEM_CLASS_CONSUMABLE
|| m_spellInfo
->SpellFamilyName
!= SPELLFAMILY_MAGE
)
2837 int32 basePoints
= m_currentBasePoints
[i
];
2838 int32 randomPoints
= m_spellInfo
->EffectDieSides
[i
];
2840 num_to_add
= basePoints
+ irand(1, randomPoints
);
2842 num_to_add
= basePoints
+ 1;
2844 else if (pProto
->MaxCount
== 1)
2846 else if(player
->getLevel() >= m_spellInfo
->spellLevel
)
2848 int32 basePoints
= m_currentBasePoints
[i
];
2849 float pointPerLevel
= m_spellInfo
->EffectRealPointsPerLevel
[i
];
2850 num_to_add
= basePoints
+ 1 + uint32((player
->getLevel() - m_spellInfo
->spellLevel
)*pointPerLevel
);
2857 if (num_to_add
> pProto
->GetMaxStackSize())
2858 num_to_add
= pProto
->GetMaxStackSize();
2860 // init items_count to 1, since 1 item will be created regardless of specialization
2862 // the chance to create additional items
2863 float additionalCreateChance
=0.0f
;
2864 // the maximum number of created additional items
2865 uint8 additionalMaxNum
=0;
2866 // get the chance and maximum number for creating extra items
2867 if ( canCreateExtraItems(player
, m_spellInfo
->Id
, additionalCreateChance
, additionalMaxNum
) )
2869 // roll with this chance till we roll not to create or we create the max num
2870 while ( roll_chance_f(additionalCreateChance
) && items_count
<=additionalMaxNum
)
2874 // really will be created more items
2875 num_to_add
*= items_count
;
2877 // can the player store the new item?
2878 ItemPosCountVec dest
;
2879 uint32 no_space
= 0;
2880 uint8 msg
= player
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, newitemid
, num_to_add
, &no_space
);
2881 if( msg
!= EQUIP_ERR_OK
)
2883 // convert to possible store amount
2884 if( msg
== EQUIP_ERR_INVENTORY_FULL
|| msg
== EQUIP_ERR_CANT_CARRY_MORE_OF_THIS
)
2885 num_to_add
-= no_space
;
2888 // if not created by another reason from full inventory or unique items amount limitation
2889 player
->SendEquipError( msg
, NULL
, NULL
);
2896 // create the new item and store it
2897 Item
* pItem
= player
->StoreNewItem( dest
, newitemid
, true, Item::GenerateItemRandomPropertyId(newitemid
));
2899 // was it successful? return error if not
2902 player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
2906 // set the "Crafted by ..." property of the item
2907 if( pItem
->GetProto()->Class
!= ITEM_CLASS_CONSUMABLE
&& pItem
->GetProto()->Class
!= ITEM_CLASS_QUEST
)
2908 pItem
->SetUInt32Value(ITEM_FIELD_CREATOR
, player
->GetGUIDLow());
2910 // send info to the client
2912 player
->SendNewItem(pItem
, num_to_add
, true, bgType
== 0);
2914 // we succeeded in creating at least one item, so a levelup is possible
2916 player
->UpdateCraftSkill(m_spellInfo
->Id
);
2919 // for battleground marks send by mail if not add all expected
2920 if(no_space
> 0 && bgType
)
2922 if(BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BattleGroundTypeId(bgType
)))
2923 bg
->SendRewardMarkByMail(player
, newitemid
, no_space
);
2927 void Spell::EffectCreateItem(uint32 i
)
2929 DoCreateItem(i
,m_spellInfo
->EffectItemType
[i
]);
2932 void Spell::EffectCreateItem2(uint32 i
)
2934 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2936 Player
* player
= (Player
*)m_caster
;
2938 uint32 item_id
= m_spellInfo
->EffectItemType
[i
];
2940 DoCreateItem(i
, item_id
);
2942 // special case: fake item replaced by generate using spell_loot_template
2943 if (IsLootCraftingSpell(m_spellInfo
))
2945 if (!player
->HasItemCount(item_id
, 1))
2950 player
->DestroyItemCount(item_id
, count
, true);
2952 // create some random items
2953 player
->AutoStoreLoot(m_spellInfo
->Id
, LootTemplates_Spell
);
2957 void Spell::EffectCreateRandomItem(uint32 i
)
2959 if (m_caster
->GetTypeId()!=TYPEID_PLAYER
)
2961 Player
* player
= (Player
*)m_caster
;
2963 // create some random items
2964 player
->AutoStoreLoot(m_spellInfo
->Id
, LootTemplates_Spell
);
2967 void Spell::EffectPersistentAA(uint32 i
)
2969 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
2971 if (Player
* modOwner
= m_caster
->GetSpellModOwner())
2972 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_RADIUS
, radius
);
2974 int32 duration
= GetSpellDuration(m_spellInfo
);
2975 DynamicObject
* dynObj
= new DynamicObject
;
2976 if (!dynObj
->Create(m_caster
->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT
), m_caster
, m_spellInfo
->Id
, i
, m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, duration
, radius
))
2981 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
2982 dynObj
->SetUInt32Value(GAMEOBJECT_DISPLAYID
, 368003);
2983 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x01eeeeee);
2984 m_caster
->AddDynObject(dynObj
);
2985 m_caster
->GetMap()->Add(dynObj
);
2988 void Spell::EffectEnergize(uint32 i
)
2992 if(!unitTarget
->isAlive())
2995 if(m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
2998 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
3000 // Some level depends spells
3001 int level_multiplier
= 0;
3003 switch (m_spellInfo
->Id
)
3005 case 9512: // Restore Energy
3006 level_diff
= m_caster
->getLevel() - 40;
3007 level_multiplier
= 2;
3009 case 24571: // Blood Fury
3010 level_diff
= m_caster
->getLevel() - 60;
3011 level_multiplier
= 10;
3013 case 24532: // Burst of Energy
3014 level_diff
= m_caster
->getLevel() - 60;
3015 level_multiplier
= 4;
3017 case 31930: // Judgements of the Wise
3018 case 63375: // Improved Stormstrike
3019 damage
= damage
* unitTarget
->GetCreateMana() / 100;
3026 damage
-= level_multiplier
* level_diff
;
3031 if(unitTarget
->GetMaxPower(power
) == 0)
3034 m_caster
->EnergizeBySpell(unitTarget
, m_spellInfo
->Id
, damage
, power
);
3036 // Mad Alchemist's Potion
3037 if (m_spellInfo
->Id
== 45051)
3039 // find elixirs on target
3040 uint32 elixir_mask
= 0;
3041 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
3042 for(Unit::AuraMap::iterator itr
= Auras
.begin(); itr
!= Auras
.end(); ++itr
)
3044 uint32 spell_id
= itr
->second
->GetId();
3045 if(uint32 mask
= sSpellMgr
.GetSpellElixirMask(spell_id
))
3046 elixir_mask
|= mask
;
3049 // get available elixir mask any not active type from battle/guardian (and flask if no any)
3050 elixir_mask
= (elixir_mask
& ELIXIR_FLASK_MASK
) ^ ELIXIR_FLASK_MASK
;
3052 // get all available elixirs by mask and spell level
3053 std::vector
<uint32
> elixirs
;
3054 SpellElixirMap
const& m_spellElixirs
= sSpellMgr
.GetSpellElixirMap();
3055 for(SpellElixirMap::const_iterator itr
= m_spellElixirs
.begin(); itr
!= m_spellElixirs
.end(); ++itr
)
3057 if (itr
->second
& elixir_mask
)
3059 if (itr
->second
& (ELIXIR_UNSTABLE_MASK
| ELIXIR_SHATTRATH_MASK
))
3062 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(itr
->first
);
3063 if (spellInfo
&& (spellInfo
->spellLevel
< m_spellInfo
->spellLevel
|| spellInfo
->spellLevel
> unitTarget
->getLevel()))
3066 elixirs
.push_back(itr
->first
);
3070 if (!elixirs
.empty())
3072 // cast random elixir on target
3073 uint32 rand_spell
= urand(0,elixirs
.size()-1);
3074 m_caster
->CastSpell(unitTarget
,elixirs
[rand_spell
],true,m_CastItem
);
3079 void Spell::EffectEnergisePct(uint32 i
)
3083 if (!unitTarget
->isAlive())
3086 if (m_spellInfo
->EffectMiscValue
[i
] < 0 || m_spellInfo
->EffectMiscValue
[i
] >= MAX_POWERS
)
3089 Powers power
= Powers(m_spellInfo
->EffectMiscValue
[i
]);
3091 uint32 maxPower
= unitTarget
->GetMaxPower(power
);
3095 uint32 gain
= damage
* maxPower
/ 100;
3096 m_caster
->EnergizeBySpell(unitTarget
, m_spellInfo
->Id
, gain
, power
);
3099 void Spell::SendLoot(uint64 guid
, LootType loottype
)
3101 Player
* player
= (Player
*)m_caster
;
3107 if (Script
->GOHello(player
, gameObjTarget
))
3110 switch (gameObjTarget
->GetGoType())
3112 case GAMEOBJECT_TYPE_DOOR
:
3113 case GAMEOBJECT_TYPE_BUTTON
:
3114 gameObjTarget
->UseDoorOrButton();
3115 player
->GetMap()->ScriptsStart(sGameObjectScripts
, gameObjTarget
->GetDBTableGUIDLow(), player
, gameObjTarget
);
3118 case GAMEOBJECT_TYPE_QUESTGIVER
:
3119 // start or end quest
3120 player
->PrepareQuestMenu(guid
);
3121 player
->SendPreparedQuest(guid
);
3124 case GAMEOBJECT_TYPE_SPELL_FOCUS
:
3125 // triggering linked GO
3126 if (uint32 trapEntry
= gameObjTarget
->GetGOInfo()->spellFocus
.linkedTrapId
)
3127 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
3130 case GAMEOBJECT_TYPE_GOOBER
:
3131 // goober_scripts can be triggered if the player don't have the quest
3132 if (gameObjTarget
->GetGOInfo()->goober
.eventId
)
3134 sLog
.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->goober
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
3135 player
->GetMap()->ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->goober
.eventId
, player
, gameObjTarget
);
3138 // cast goober spell
3139 if (gameObjTarget
->GetGOInfo()->goober
.questId
)
3140 ///Quest require to be active for GO using
3141 if (player
->GetQuestStatus(gameObjTarget
->GetGOInfo()->goober
.questId
) != QUEST_STATUS_INCOMPLETE
)
3144 gameObjTarget
->AddUniqueUse(player
);
3145 gameObjTarget
->SetLootState(GO_JUST_DEACTIVATED
);
3147 //TODO? Objective counting called without spell check but with quest objective check
3148 // if send spell id then this line will duplicate to spell casting call (double counting)
3149 // So we or have this line and not required in quest_template have reqSpellIdN
3150 // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
3151 player
->CastedCreatureOrGO(gameObjTarget
->GetEntry(), gameObjTarget
->GetGUID(), 0);
3153 // triggering linked GO
3154 if (uint32 trapEntry
= gameObjTarget
->GetGOInfo()->goober
.linkedTrapId
)
3155 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
3159 case GAMEOBJECT_TYPE_CHEST
:
3160 // TODO: possible must be moved to loot release (in different from linked triggering)
3161 if (gameObjTarget
->GetGOInfo()->chest
.eventId
)
3163 sLog
.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget
->GetGOInfo()->chest
.eventId
,gameObjTarget
->GetDBTableGUIDLow());
3164 player
->GetMap()->ScriptsStart(sEventScripts
, gameObjTarget
->GetGOInfo()->chest
.eventId
, player
, gameObjTarget
);
3167 // triggering linked GO
3168 if (uint32 trapEntry
= gameObjTarget
->GetGOInfo()->chest
.linkedTrapId
)
3169 gameObjTarget
->TriggeringLinkedGameObject(trapEntry
,m_caster
);
3171 // Don't return, let loots been taken
3178 player
->SendLoot(guid
, loottype
);
3181 void Spell::EffectOpenLock(uint32 effIndex
)
3183 if (!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
3185 sLog
.outDebug( "WORLD: Open Lock - No Player Caster!");
3189 Player
* player
= (Player
*)m_caster
;
3197 GameObjectInfo
const* goInfo
= gameObjTarget
->GetGOInfo();
3198 // Arathi Basin banner opening !
3199 if (goInfo
->type
== GAMEOBJECT_TYPE_BUTTON
&& goInfo
->button
.noDamageImmune
||
3200 goInfo
->type
== GAMEOBJECT_TYPE_GOOBER
&& goInfo
->goober
.losOK
)
3202 //CanUseBattleGroundObject() already called in CheckCast()
3203 // in battleground check
3204 if (BattleGround
*bg
= player
->GetBattleGround())
3206 // check if it's correct bg
3207 if (bg
->GetTypeID() == BATTLEGROUND_AB
|| bg
->GetTypeID() == BATTLEGROUND_AV
)
3208 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
3212 else if (goInfo
->type
== GAMEOBJECT_TYPE_FLAGSTAND
)
3214 //CanUseBattleGroundObject() already called in CheckCast()
3215 // in battleground check
3216 if (BattleGround
*bg
= player
->GetBattleGround())
3218 if (bg
->GetTypeID() == BATTLEGROUND_EY
)
3219 bg
->EventPlayerClickedOnFlag(player
, gameObjTarget
);
3223 lockId
= goInfo
->GetLockId();
3224 guid
= gameObjTarget
->GetGUID();
3226 else if (itemTarget
)
3228 lockId
= itemTarget
->GetProto()->LockID
;
3229 guid
= itemTarget
->GetGUID();
3233 sLog
.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
3237 SkillType skillId
= SKILL_NONE
;
3238 int32 reqSkillValue
= 0;
3241 SpellCastResult res
= CanOpenLock(effIndex
, lockId
, skillId
, reqSkillValue
, skillValue
);
3242 if (res
!= SPELL_CAST_OK
)
3244 SendCastResult(res
);
3248 SendLoot(guid
, LOOT_SKINNING
);
3250 // not allow use skill grow at item base open
3251 if (!m_CastItem
&& skillId
!= SKILL_NONE
)
3253 // update skill if really known
3254 if (uint32 pureSkillValue
= player
->GetPureSkillValue(skillId
))
3258 // Allow one skill-up until respawned
3259 if (!gameObjTarget
->IsInSkillupList(player
->GetGUIDLow()) &&
3260 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
))
3261 gameObjTarget
->AddToSkillupList(player
->GetGUIDLow());
3263 else if (itemTarget
)
3266 player
->UpdateGatherSkill(skillId
, pureSkillValue
, reqSkillValue
);
3272 void Spell::EffectSummonChangeItem(uint32 i
)
3274 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3277 Player
*player
= (Player
*)m_caster
;
3279 // applied only to using item
3283 // ... only to item in own inventory/bank/equip_slot
3284 if (m_CastItem
->GetOwnerGUID()!=player
->GetGUID())
3287 uint32 newitemid
= m_spellInfo
->EffectItemType
[i
];
3291 uint16 pos
= m_CastItem
->GetPos();
3293 Item
*pNewItem
= Item::CreateItem( newitemid
, 1, player
);
3297 for(uint8 j
= PERM_ENCHANTMENT_SLOT
; j
<=TEMP_ENCHANTMENT_SLOT
; ++j
)
3299 if (m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)))
3300 pNewItem
->SetEnchantment(EnchantmentSlot(j
), m_CastItem
->GetEnchantmentId(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentDuration(EnchantmentSlot(j
)), m_CastItem
->GetEnchantmentCharges(EnchantmentSlot(j
)));
3303 if (m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) < m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
))
3305 double loosePercent
= 1 - m_CastItem
->GetUInt32Value(ITEM_FIELD_DURABILITY
) / double(m_CastItem
->GetUInt32Value(ITEM_FIELD_MAXDURABILITY
));
3306 player
->DurabilityLoss(pNewItem
, loosePercent
);
3309 if (player
->IsInventoryPos(pos
))
3311 ItemPosCountVec dest
;
3312 uint8 msg
= player
->CanStoreItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3313 if (msg
== EQUIP_ERR_OK
)
3315 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3317 // prevent crash at access and unexpected charges counting with item update queue corrupt
3318 if (m_CastItem
==m_targets
.getItemTarget())
3319 m_targets
.setItemTarget(NULL
);
3323 player
->StoreItem( dest
, pNewItem
, true);
3327 else if (player
->IsBankPos (pos
))
3329 ItemPosCountVec dest
;
3330 uint8 msg
= player
->CanBankItem( m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3331 if (msg
== EQUIP_ERR_OK
)
3333 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3335 // prevent crash at access and unexpected charges counting with item update queue corrupt
3336 if (m_CastItem
==m_targets
.getItemTarget())
3337 m_targets
.setItemTarget(NULL
);
3341 player
->BankItem( dest
, pNewItem
, true);
3345 else if (player
->IsEquipmentPos (pos
))
3348 uint8 msg
= player
->CanEquipItem( m_CastItem
->GetSlot(), dest
, pNewItem
, true );
3349 if (msg
== EQUIP_ERR_OK
)
3351 player
->DestroyItem(m_CastItem
->GetBagSlot(), m_CastItem
->GetSlot(), true);
3353 // prevent crash at access and unexpected charges counting with item update queue corrupt
3354 if (m_CastItem
==m_targets
.getItemTarget())
3355 m_targets
.setItemTarget(NULL
);
3359 player
->EquipItem( dest
, pNewItem
, true);
3360 player
->AutoUnequipOffhandIfNeed();
3369 void Spell::EffectProficiency(uint32
/*i*/)
3371 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3373 Player
*p_target
= (Player
*)unitTarget
;
3375 uint32 subClassMask
= m_spellInfo
->EquippedItemSubClassMask
;
3376 if (m_spellInfo
->EquippedItemClass
== ITEM_CLASS_WEAPON
&& !(p_target
->GetWeaponProficiency() & subClassMask
))
3378 p_target
->AddWeaponProficiency(subClassMask
);
3379 p_target
->SendProficiency(ITEM_CLASS_WEAPON
, p_target
->GetWeaponProficiency());
3381 if (m_spellInfo
->EquippedItemClass
== ITEM_CLASS_ARMOR
&& !(p_target
->GetArmorProficiency() & subClassMask
))
3383 p_target
->AddArmorProficiency(subClassMask
);
3384 p_target
->SendProficiency(ITEM_CLASS_ARMOR
, p_target
->GetArmorProficiency());
3388 void Spell::EffectApplyAreaAura(uint32 i
)
3392 if (!unitTarget
->isAlive())
3395 AreaAura
* Aur
= new AreaAura(m_spellInfo
, i
, &m_currentBasePoints
[i
], unitTarget
, m_caster
, m_CastItem
);
3396 unitTarget
->AddAura(Aur
);
3399 void Spell::EffectSummonType(uint32 i
)
3401 uint32 prop_id
= m_spellInfo
->EffectMiscValueB
[i
];
3402 SummonPropertiesEntry
const *summon_prop
= sSummonPropertiesStore
.LookupEntry(prop_id
);
3405 sLog
.outError("EffectSummonType: Unhandled summon type %u", prop_id
);
3409 switch(summon_prop
->Group
)
3411 // faction handled later on, or loaded from template
3412 case SUMMON_PROP_GROUP_WILD
:
3413 case SUMMON_PROP_GROUP_FRIENDLY
:
3415 switch(summon_prop
->Type
)
3417 case SUMMON_PROP_TYPE_OTHER
:
3419 // those are classical totems - effectbasepoints is their hp and not summon ammount!
3420 //SUMMON_TYPE_TOTEM = 121: 23035, battlestands
3421 //SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
3422 if(prop_id
== 121 || prop_id
== 647)
3423 EffectSummonTotem(i
);
3425 EffectSummonWild(i
, summon_prop
->FactionId
);
3428 case SUMMON_PROP_TYPE_SUMMON
:
3429 case SUMMON_PROP_TYPE_GUARDIAN
:
3430 case SUMMON_PROP_TYPE_ARMY
:
3431 case SUMMON_PROP_TYPE_DK
:
3432 case SUMMON_PROP_TYPE_CONSTRUCT
:
3434 // JC golems - 32804, etc -- fits much better totem AI
3435 if(m_spellInfo
->SpellIconID
== 2056)
3436 EffectSummonTotem(i
);
3437 if(prop_id
== 832) // scrapbot
3438 EffectSummonWild(i
, summon_prop
->FactionId
);
3440 EffectSummonGuardian(i
, summon_prop
->FactionId
);
3443 case SUMMON_PROP_TYPE_TOTEM
:
3444 EffectSummonTotem(i
, summon_prop
->Slot
);
3446 case SUMMON_PROP_TYPE_CRITTER
:
3447 EffectSummonCritter(i
, summon_prop
->FactionId
);
3449 case SUMMON_PROP_TYPE_PHASING
:
3450 case SUMMON_PROP_TYPE_LIGHTWELL
:
3451 case SUMMON_PROP_TYPE_REPAIR_BOT
:
3452 EffectSummonWild(i
, summon_prop
->FactionId
);
3454 case SUMMON_PROP_TYPE_SIEGE_VEH
:
3455 case SUMMON_PROP_TYPE_DRAKE_VEH
:
3457 // EffectSummonVehicle(i);
3460 sLog
.outError("EffectSummonType: Unhandled summon type %u", summon_prop
->Type
);
3465 case SUMMON_PROP_GROUP_PETS
:
3467 // FIXME : multiple summons - not yet supported as pet
3468 //1562 - force of nature - sid 33831
3469 //1161 - feral spirit - sid 51533
3470 if(prop_id
== 1562) // 3 uncontrolable instead of one controllable :/
3471 EffectSummonGuardian(i
, summon_prop
->FactionId
);
3476 case SUMMON_PROP_GROUP_CONTROLLABLE
:
3479 // maybe wrong - but thats the handler currently used for those
3480 EffectSummonGuardian(i
, summon_prop
->FactionId
);
3483 case SUMMON_PROP_GROUP_VEHICLE
:
3486 // EffectSummonVehicle(i);
3490 sLog
.outError("EffectSummonType: Unhandled summon group type %u", summon_prop
->Group
);
3495 void Spell::EffectSummon(uint32 i
)
3497 if (m_caster
->GetPetGUID())
3502 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3505 uint32 level
= m_caster
->getLevel();
3506 Pet
* spawnCreature
= new Pet(SUMMON_PET
);
3508 int32 duration
= GetSpellDuration(m_spellInfo
);
3509 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
3510 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
3512 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& spawnCreature
->LoadPetFromDB((Player
*)m_caster
,pet_entry
))
3514 // Summon in dest location
3516 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3518 x
= m_targets
.m_destX
;
3519 y
= m_targets
.m_destY
;
3520 z
= m_targets
.m_destZ
;
3521 spawnCreature
->Relocate(m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, -m_caster
->GetOrientation());
3524 // set timer for unsummon
3526 spawnCreature
->SetDuration(duration
);
3531 Map
*map
= m_caster
->GetMap();
3532 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
3533 if (!spawnCreature
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
3534 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3536 sLog
.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo
->EffectMiscValue
[i
]);
3537 delete spawnCreature
;
3541 // Summon in dest location
3543 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3545 x
= m_targets
.m_destX
;
3546 y
= m_targets
.m_destY
;
3547 z
= m_targets
.m_destZ
;
3550 m_caster
->GetClosePoint(x
, y
, z
, spawnCreature
->GetObjectSize());
3552 spawnCreature
->Relocate(x
, y
, z
, -m_caster
->GetOrientation());
3554 if (!spawnCreature
->IsPositionValid())
3556 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
3557 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3558 delete spawnCreature
;
3562 // set timer for unsummon
3564 spawnCreature
->SetDuration(duration
);
3566 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3567 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, UNIT_NPC_FLAG_NONE
);
3568 spawnCreature
->setPowerType(POWER_MANA
);
3569 spawnCreature
->setFaction(m_caster
->getFaction());
3570 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3571 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
3572 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3573 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3574 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
3575 spawnCreature
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
3576 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3577 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3579 spawnCreature
->InitStatsForLevel(level
, m_caster
);
3581 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3583 spawnCreature
->AIM_Initialize();
3584 spawnCreature
->InitPetCreateSpells();
3585 spawnCreature
->InitLevelupSpellsForLevel();
3586 spawnCreature
->SetHealth(spawnCreature
->GetMaxHealth());
3587 spawnCreature
->SetPower(POWER_MANA
, spawnCreature
->GetMaxPower(POWER_MANA
));
3589 std::string name
= m_caster
->GetName();
3590 name
.append(petTypeSuffix
[spawnCreature
->getPetType()]);
3591 spawnCreature
->SetName( name
);
3593 map
->Add((Creature
*)spawnCreature
);
3595 m_caster
->SetPet(spawnCreature
);
3597 if (m_caster
->GetTypeId() == TYPEID_PLAYER
)
3599 spawnCreature
->GetCharmInfo()->SetReactState( REACT_DEFENSIVE
);
3600 spawnCreature
->SavePetToDB(PET_SAVE_AS_CURRENT
);
3601 ((Player
*)m_caster
)->PetSpellInitialize();
3605 void Spell::EffectLearnSpell(uint32 i
)
3610 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
3612 if (m_caster
->GetTypeId() == TYPEID_PLAYER
)
3613 EffectLearnPetSpell(i
);
3618 Player
*player
= (Player
*)unitTarget
;
3620 uint32 spellToLearn
= ((m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN
) || (m_spellInfo
->Id
==SPELL_ID_GENERIC_LEARN_PET
)) ? damage
: m_spellInfo
->EffectTriggerSpell
[i
];
3621 player
->learnSpell(spellToLearn
,false);
3623 sLog
.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player
->GetGUIDLow(), spellToLearn
, m_caster
->GetGUIDLow() );
3626 void Spell::EffectDispel(uint32 i
)
3631 // Fill possible dispell list
3632 std::vector
<Aura
*> dispel_list
;
3634 // Create dispel mask by dispel type
3635 uint32 dispel_type
= m_spellInfo
->EffectMiscValue
[i
];
3636 uint32 dispelMask
= GetDispellMask( DispelType(dispel_type
) );
3637 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
3638 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
3640 Aura
*aur
= (*itr
).second
;
3641 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
3643 if(aur
->GetSpellProto()->Dispel
== DISPEL_MAGIC
)
3645 bool positive
= true;
3646 if (!aur
->IsPositive())
3649 positive
= (aur
->GetSpellProto()->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)==0;
3651 // do not remove positive auras if friendly target
3652 // negative auras if non-friendly target
3653 if (positive
== unitTarget
->IsFriendlyTo(m_caster
))
3656 // Add aura to dispel list (all stack cases)
3657 for(int k
= 0; k
< aur
->GetStackAmount(); ++k
)
3658 dispel_list
.push_back(aur
);
3661 // Ok if exist some buffs for dispel try dispel it
3662 if (!dispel_list
.empty())
3664 std::list
< std::pair
<uint32
,uint64
> > success_list
;// (spell_id,casterGuid)
3665 std::list
< uint32
> fail_list
; // spell_id
3667 // some spells have effect value = 0 and all from its by meaning expect 1
3671 // Dispell N = damage buffs (or while exist buffs for dispel)
3672 for (int32 count
=0; count
< damage
&& !dispel_list
.empty(); ++count
)
3674 // Random select buff for dispel
3675 std::vector
<Aura
*>::iterator dispel_itr
= dispel_list
.begin();
3676 std::advance(dispel_itr
,urand(0, dispel_list
.size()-1));
3678 Aura
*aur
= *dispel_itr
;
3680 // remove entry from dispel_list
3681 dispel_list
.erase(dispel_itr
);
3683 SpellEntry
const* spellInfo
= aur
->GetSpellProto();
3684 // Base dispel chance
3685 // TODO: possible chance depend from spell level??
3686 int32 miss_chance
= 0;
3687 // Apply dispel mod from aura caster
3688 if (Unit
*caster
= aur
->GetCaster())
3690 if ( Player
* modOwner
= caster
->GetSpellModOwner() )
3691 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_RESIST_DISPEL_CHANCE
, miss_chance
, this);
3694 if (roll_chance_i(miss_chance
))
3695 fail_list
.push_back(spellInfo
->Id
);
3697 success_list
.push_back(std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
3699 // Send success log and really remove auras
3700 if (!success_list
.empty())
3702 int32 count
= success_list
.size();
3703 WorldPacket
data(SMSG_SPELLDISPELLOG
, 8+8+4+1+4+count
*5);
3704 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
3705 data
.append(m_caster
->GetPackGUID()); // Caster GUID
3706 data
<< uint32(m_spellInfo
->Id
); // Dispel spell id
3707 data
<< uint8(0); // not used
3708 data
<< uint32(count
); // count
3709 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
3711 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
3712 data
<< uint32(spellInfo
->Id
); // Spell Id
3713 data
<< uint8(0); // 0 - dispeled !=0 cleansed
3714 unitTarget
->RemoveSingleAuraDueToSpellByDispel(spellInfo
->Id
, j
->second
, m_caster
);
3716 m_caster
->SendMessageToSet(&data
, true);
3718 // On success dispel
3720 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&& m_spellInfo
->Category
== SPELLCATEGORY_DEVOUR_MAGIC
)
3722 int32 heal_amount
= m_spellInfo
->CalculateSimpleValue(1);
3723 m_caster
->CastCustomSpell(m_caster
, 19658, &heal_amount
, NULL
, NULL
, true);
3726 // Send fail log to client
3727 if (!fail_list
.empty())
3729 // Failed to dispell
3730 WorldPacket
data(SMSG_DISPEL_FAILED
, 8+8+4+4*fail_list
.size());
3731 data
<< uint64(m_caster
->GetGUID()); // Caster GUID
3732 data
<< uint64(unitTarget
->GetGUID()); // Victim GUID
3733 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
3734 for (std::list
< uint32
>::iterator j
= fail_list
.begin(); j
!= fail_list
.end(); ++j
)
3735 data
<< uint32(*j
); // Spell Id
3736 m_caster
->SendMessageToSet(&data
, true);
3741 void Spell::EffectDualWield(uint32
/*i*/)
3743 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3744 ((Player
*)unitTarget
)->SetCanDualWield(true);
3747 void Spell::EffectPull(uint32
/*i*/)
3749 // TODO: create a proper pull towards distract spell center for distract
3750 sLog
.outDebug("WORLD: Spell Effect DUMMY");
3753 void Spell::EffectDistract(uint32
/*i*/)
3755 // Check for possible target
3756 if (!unitTarget
|| unitTarget
->isInCombat())
3759 // target must be OK to do this
3760 if( unitTarget
->hasUnitState(UNIT_STAT_CONFUSED
| UNIT_STAT_STUNNED
| UNIT_STAT_FLEEING
) )
3763 float angle
= unitTarget
->GetAngle(m_targets
.m_destX
, m_targets
.m_destY
);
3765 if ( unitTarget
->GetTypeId() == TYPEID_PLAYER
)
3767 // For players just turn them
3769 ((Player
*)unitTarget
)->BuildTeleportAckMsg(&data
, unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
);
3770 ((Player
*)unitTarget
)->GetSession()->SendPacket( &data
);
3771 ((Player
*)unitTarget
)->SetPosition(unitTarget
->GetPositionX(), unitTarget
->GetPositionY(), unitTarget
->GetPositionZ(), angle
, false);
3775 // Set creature Distracted, Stop it, And turn it
3776 unitTarget
->SetOrientation(angle
);
3777 unitTarget
->StopMoving();
3778 unitTarget
->GetMotionMaster()->MoveDistract(damage
* IN_MILISECONDS
);
3782 void Spell::EffectPickPocket(uint32
/*i*/)
3784 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
3787 // victim must be creature and attackable
3788 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
|| m_caster
->IsFriendlyTo(unitTarget
))
3791 // victim have to be alive and humanoid or undead
3792 if (unitTarget
->isAlive() && (unitTarget
->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD
) != 0)
3794 int32 chance
= 10 + int32(m_caster
->getLevel()) - int32(unitTarget
->getLevel());
3796 if (chance
> irand(0, 19))
3798 // Stealing successful
3799 //sLog.outDebug("Sending loot from pickpocket");
3800 ((Player
*)m_caster
)->SendLoot(unitTarget
->GetGUID(),LOOT_PICKPOCKETING
);
3804 // Reveal action + get attack
3805 m_caster
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH
);
3806 if (((Creature
*)unitTarget
)->AI())
3807 ((Creature
*)unitTarget
)->AI()->AttackedBy(m_caster
);
3812 void Spell::EffectAddFarsight(uint32 i
)
3814 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
3817 int32 duration
= GetSpellDuration(m_spellInfo
);
3818 DynamicObject
* dynObj
= new DynamicObject
;
3820 // set radius to 0: spell not expected to work as persistent aura
3821 if(!dynObj
->Create(m_caster
->GetMap()->GenerateLocalLowGuid(HIGHGUID_DYNAMICOBJECT
), m_caster
, m_spellInfo
->Id
, i
, m_targets
.m_destX
, m_targets
.m_destY
, m_targets
.m_destZ
, duration
, 0))
3826 dynObj
->SetUInt32Value(OBJECT_FIELD_TYPE
, 65);
3827 dynObj
->SetUInt32Value(DYNAMICOBJECT_BYTES
, 0x80000002);
3828 m_caster
->AddDynObject(dynObj
);
3829 m_caster
->GetMap()->Add(dynObj
);
3830 ((Player
*)m_caster
)->SetFarSightGUID(dynObj
->GetGUID());
3833 void Spell::EffectSummonWild(uint32 i
, uint32 forceFaction
)
3835 uint32 creature_entry
= m_spellInfo
->EffectMiscValue
[i
];
3836 if (!creature_entry
)
3839 uint32 level
= m_caster
->getLevel();
3841 // level of creature summoned using engineering item based at engineering skill level
3842 if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& m_CastItem
)
3844 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3845 if (proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3847 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3853 // select center of summon position
3854 float center_x
= m_targets
.m_destX
;
3855 float center_y
= m_targets
.m_destY
;
3856 float center_z
= m_targets
.m_destZ
;
3858 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3859 int32 duration
= GetSpellDuration(m_spellInfo
);
3860 TempSummonType summonType
= (duration
== 0) ? TEMPSUMMON_DEAD_DESPAWN
: TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
;
3862 int32 amount
= damage
> 0 ? damage
: 1;
3864 for(int32 count
= 0; count
< amount
; ++count
)
3867 // If dest location if present
3868 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3870 // Summon 1 unit in dest location
3873 px
= m_targets
.m_destX
;
3874 py
= m_targets
.m_destY
;
3875 pz
= m_targets
.m_destZ
;
3877 // Summon in random point all other units if location present
3879 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
3881 // Summon if dest location not present near caster
3883 m_caster
->GetClosePoint(px
, py
, pz
, 3.0f
);
3885 if(Creature
*summon
= m_caster
->SummonCreature(creature_entry
, px
, py
, pz
, m_caster
->GetOrientation(), summonType
, duration
))
3887 summon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3888 summon
->SetCreatorGUID(m_caster
->GetGUID());
3891 summon
->setFaction(forceFaction
);
3896 void Spell::EffectSummonGuardian(uint32 i
, uint32 forceFaction
)
3898 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
3902 // in another case summon new
3903 uint32 level
= m_caster
->getLevel();
3905 // level of pet summoned using engineering item based at engineering skill level
3906 if (m_caster
->GetTypeId() == TYPEID_PLAYER
&& m_CastItem
)
3908 ItemPrototype
const *proto
= m_CastItem
->GetProto();
3909 if (proto
&& proto
->RequiredSkill
== SKILL_ENGINERING
)
3911 uint16 skill202
= ((Player
*)m_caster
)->GetSkillValue(SKILL_ENGINERING
);
3914 level
= skill202
/ 5;
3919 // select center of summon position
3920 float center_x
= m_targets
.m_destX
;
3921 float center_y
= m_targets
.m_destY
;
3922 float center_z
= m_targets
.m_destZ
;
3924 float radius
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
3925 int32 duration
= GetSpellDuration(m_spellInfo
);
3926 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
3927 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
3929 int32 amount
= damage
> 0 ? damage
: 1;
3931 for(int32 count
= 0; count
< amount
; ++count
)
3933 Pet
* spawnCreature
= new Pet(GUARDIAN_PET
);
3935 Map
*map
= m_caster
->GetMap();
3936 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
3937 if (!spawnCreature
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
,m_caster
->GetPhaseMask(),
3938 m_spellInfo
->EffectMiscValue
[i
], pet_number
))
3940 sLog
.outError("no such creature entry %u", m_spellInfo
->EffectMiscValue
[i
]);
3941 delete spawnCreature
;
3946 // If dest location if present
3947 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
3949 // Summon 1 unit in dest location
3952 px
= m_targets
.m_destX
;
3953 py
= m_targets
.m_destY
;
3954 pz
= m_targets
.m_destZ
;
3956 // Summon in random point all other units if location present
3958 m_caster
->GetRandomPoint(center_x
, center_y
, center_z
, radius
, px
, py
, pz
);
3960 // Summon if dest location not present near caster
3962 m_caster
->GetClosePoint(px
, py
, pz
,spawnCreature
->GetObjectSize());
3964 spawnCreature
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
3966 if (!spawnCreature
->IsPositionValid())
3968 sLog
.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)",
3969 spawnCreature
->GetGUIDLow(), spawnCreature
->GetEntry(), spawnCreature
->GetPositionX(), spawnCreature
->GetPositionY());
3970 delete spawnCreature
;
3975 spawnCreature
->SetDuration(duration
);
3977 spawnCreature
->SetOwnerGUID(m_caster
->GetGUID());
3978 spawnCreature
->setPowerType(POWER_MANA
);
3979 spawnCreature
->SetUInt32Value(UNIT_NPC_FLAGS
, spawnCreature
->GetCreatureInfo()->npcflag
);
3980 spawnCreature
->setFaction(forceFaction
? forceFaction
: m_caster
->getFaction());
3981 spawnCreature
->SetUInt32Value(UNIT_FIELD_FLAGS
, 0);
3982 spawnCreature
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
3983 spawnCreature
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, 0);
3984 spawnCreature
->SetCreatorGUID(m_caster
->GetGUID());
3985 spawnCreature
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
3987 spawnCreature
->InitStatsForLevel(level
, m_caster
);
3988 spawnCreature
->GetCharmInfo()->SetPetNumber(pet_number
, false);
3990 spawnCreature
->AIM_Initialize();
3992 m_caster
->AddGuardian(spawnCreature
);
3994 map
->Add((Creature
*)spawnCreature
);
3998 void Spell::EffectTeleUnitsFaceCaster(uint32 i
)
4003 if (unitTarget
->isInFlight())
4006 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
4009 m_caster
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
4011 unitTarget
->NearTeleportTo(fx
, fy
, fz
, -m_caster
->GetOrientation(), unitTarget
==m_caster
);
4014 void Spell::EffectLearnSkill(uint32 i
)
4016 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4022 uint32 skillid
= m_spellInfo
->EffectMiscValue
[i
];
4023 uint16 skillval
= ((Player
*)unitTarget
)->GetPureSkillValue(skillid
);
4024 ((Player
*)unitTarget
)->SetSkill(skillid
, skillval
? skillval
: 1, damage
* 75);
4027 void Spell::EffectAddHonor(uint32
/*i*/)
4029 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4032 // not scale value for item based reward (/10 value expected)
4035 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
/ 10);
4036 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo
->Id
, damage
/10, m_CastItem
->GetEntry(),((Player
*)unitTarget
)->GetGUIDLow());
4040 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
4043 uint32 honor_reward
= MaNGOS::Honor::hk_honor_at_level(unitTarget
->getLevel(), damage
);
4044 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, honor_reward
);
4045 sLog
.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo
->Id
, honor_reward
, ((Player
*)unitTarget
)->GetGUIDLow());
4049 //maybe we have correct honor_gain in damage already
4050 ((Player
*)unitTarget
)->RewardHonor(NULL
, 1, damage
);
4051 sLog
.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo
->Id
, damage
, ((Player
*)unitTarget
)->GetGUIDLow());
4055 void Spell::EffectTradeSkill(uint32
/*i*/)
4057 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4059 // uint32 skillid = m_spellInfo->EffectMiscValue[i];
4060 // uint16 skillmax = ((Player*)unitTarget)->(skillid);
4061 // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
4064 void Spell::EffectEnchantItemPerm(uint32 effect_idx
)
4066 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4071 Player
* p_caster
= (Player
*)m_caster
;
4073 // not grow at item use at item case
4074 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
4076 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
4080 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4084 // item can be in trade slot and have owner diff. from caster
4085 Player
* item_owner
= itemTarget
->GetOwner();
4089 if (item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
4091 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4092 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
4093 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
4094 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
4097 // remove old enchanting before applying new if equipped
4098 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,false);
4100 itemTarget
->SetEnchantment(PERM_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
4102 // add new enchanting if equipped
4103 item_owner
->ApplyEnchantment(itemTarget
,PERM_ENCHANTMENT_SLOT
,true);
4106 void Spell::EffectEnchantItemPrismatic(uint32 effect_idx
)
4108 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4113 Player
* p_caster
= (Player
*)m_caster
;
4115 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[effect_idx
];
4119 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4123 // support only enchantings with add socket in this slot
4125 bool add_socket
= false;
4126 for(int i
= 0; i
< 3; ++i
)
4128 if (pEnchant
->type
[i
]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
)
4136 sLog
.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (%u), not suppoted yet.",
4137 m_spellInfo
->Id
,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET
);
4142 // item can be in trade slot and have owner diff. from caster
4143 Player
* item_owner
= itemTarget
->GetOwner();
4147 if (item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
4149 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
4150 p_caster
->GetName(),p_caster
->GetSession()->GetAccountId(),
4151 itemTarget
->GetProto()->Name1
,itemTarget
->GetEntry(),
4152 item_owner
->GetName(),item_owner
->GetSession()->GetAccountId());
4155 // remove old enchanting before applying new if equipped
4156 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,false);
4158 itemTarget
->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT
, enchant_id
, 0, 0);
4160 // add new enchanting if equipped
4161 item_owner
->ApplyEnchantment(itemTarget
,PRISMATIC_ENCHANTMENT_SLOT
,true);
4164 void Spell::EffectEnchantItemTmp(uint32 i
)
4166 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
4169 Player
* p_caster
= (Player
*)m_caster
;
4171 // Rockbiter Weapon apply to both weapon
4172 if (m_spellInfo
->SpellFamilyName
== SPELLFAMILY_SHAMAN
&& m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000400000))
4174 uint32 spell_id
= 0;
4176 // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
4177 // Note: damage calculated (correctly) with rounding int32(float(v)) but
4178 // RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
4182 case 2: spell_id
= 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
4184 case 4: spell_id
= 36753; break; // 0% [ 7% == 4, 14% == 4]
4185 case 5: spell_id
= 36751; break; // 20%
4187 case 6: spell_id
= 36754; break; // 0% [ 7% == 6, 14% == 6]
4188 case 7: spell_id
= 36755; break; // 20%
4190 case 9: spell_id
= 36761; break; // 0% [ 7% == 6]
4191 case 10: spell_id
= 36758; break; // 14%
4192 case 11: spell_id
= 36760; break; // 20%
4194 sLog
.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage
);
4199 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spell_id
);
4202 sLog
.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id
);
4206 for(int j
= BASE_ATTACK
; j
<= OFF_ATTACK
; ++j
)
4208 if (Item
* item
= p_caster
->GetWeaponForAttack(WeaponAttackType(j
)))
4210 if (item
->IsFitToSpellRequirements(m_spellInfo
))
4212 Spell
*spell
= new Spell(m_caster
, spellInfo
, true);
4213 SpellCastTargets targets
;
4214 targets
.setItemTarget( item
);
4215 spell
->prepare(&targets
);
4225 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
4229 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo
->Id
,i
);
4233 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
4236 sLog
.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo
->Id
,i
,enchant_id
);
4240 // select enchantment duration
4243 // rogue family enchantments exception by duration
4244 if(m_spellInfo
->Id
== 38615)
4245 duration
= 1800; // 30 mins
4246 // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
4247 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
)
4248 duration
= 3600; // 1 hour
4249 // shaman family enchantments
4250 else if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_SHAMAN
)
4251 duration
= 1800; // 30 mins
4252 // other cases with this SpellVisual already selected
4253 else if(m_spellInfo
->SpellVisual
[0] == 215)
4254 duration
= 1800; // 30 mins
4255 // some fishing pole bonuses
4256 else if(m_spellInfo
->SpellVisual
[0] == 563)
4257 duration
= 600; // 10 mins
4258 // shaman rockbiter enchantments
4259 else if(m_spellInfo
->SpellVisual
[0] == 0)
4260 duration
= 1800; // 30 mins
4261 else if(m_spellInfo
->Id
== 29702)
4262 duration
= 300; // 5 mins
4263 else if(m_spellInfo
->Id
== 37360)
4264 duration
= 300; // 5 mins
4267 duration
= 3600; // 1 hour
4269 // item can be in trade slot and have owner diff. from caster
4270 Player
* item_owner
= itemTarget
->GetOwner();
4274 if(item_owner
!=p_caster
&& p_caster
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_GM_LOG_TRADE
) )
4276 sLog
.outCommand(p_caster
->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
4277 p_caster
->GetName(), p_caster
->GetSession()->GetAccountId(),
4278 itemTarget
->GetProto()->Name1
, itemTarget
->GetEntry(),
4279 item_owner
->GetName(), item_owner
->GetSession()->GetAccountId());
4282 // remove old enchanting before applying new if equipped
4283 item_owner
->ApplyEnchantment(itemTarget
,TEMP_ENCHANTMENT_SLOT
, false);
4285 itemTarget
->SetEnchantment(TEMP_ENCHANTMENT_SLOT
, enchant_id
, duration
* 1000, 0);
4287 // add new enchanting if equipped
4288 item_owner
->ApplyEnchantment(itemTarget
, TEMP_ENCHANTMENT_SLOT
, true);
4291 void Spell::EffectTameCreature(uint32
/*i*/)
4293 // Caster must be player, checked in Spell::CheckCast
4294 // Spell can be triggered, we need to check original caster prior to caster
4295 Player
* plr
= (Player
*)(m_originalCaster
? m_originalCaster
: m_caster
);
4297 Creature
* creatureTarget
= (Creature
*)unitTarget
;
4299 // cast finish successfully
4300 //SendChannelUpdate(0);
4303 Pet
* pet
= plr
->CreateTamedPetFrom(creatureTarget
, m_spellInfo
->Id
);
4304 if(!pet
) // in versy specific state like near world end/etc.
4307 // "kill" original creature
4308 creatureTarget
->ForcedDespawn();
4310 uint32 level
= (creatureTarget
->getLevel() < (plr
->getLevel() - 5)) ? (plr
->getLevel() - 5) : creatureTarget
->getLevel();
4312 // prepare visual effect for levelup
4313 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
- 1);
4316 pet
->GetMap()->Add((Creature
*)pet
);
4318 // visual effect for levelup
4319 pet
->SetUInt32Value(UNIT_FIELD_LEVEL
, level
);
4321 // caster have pet now
4324 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4325 plr
->PetSpellInitialize();
4328 void Spell::EffectSummonPet(uint32 i
)
4330 uint32 petentry
= m_spellInfo
->EffectMiscValue
[i
];
4332 Pet
*OldSummon
= m_caster
->GetPet();
4334 // if pet requested type already exist
4337 if(petentry
== 0 || OldSummon
->GetEntry() == petentry
)
4339 // pet in corpse state can't be summoned
4340 if( OldSummon
->isDead() )
4343 OldSummon
->GetMap()->Remove((Creature
*)OldSummon
,false);
4346 m_caster
->GetClosePoint(px
, py
, pz
, OldSummon
->GetObjectSize());
4348 OldSummon
->Relocate(px
, py
, pz
, OldSummon
->GetOrientation());
4349 m_caster
->GetMap()->Add((Creature
*)OldSummon
);
4351 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& OldSummon
->isControlled() )
4353 ((Player
*)m_caster
)->PetSpellInitialize();
4358 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4359 ((Player
*)m_caster
)->RemovePet(OldSummon
,(OldSummon
->getPetType()==HUNTER_PET
? PET_SAVE_AS_DELETED
: PET_SAVE_NOT_IN_SLOT
),false);
4364 Pet
* NewSummon
= new Pet
;
4366 // petentry==0 for hunter "call pet" (current pet summoned if any)
4367 if(m_caster
->GetTypeId() == TYPEID_PLAYER
&& NewSummon
->LoadPetFromDB((Player
*)m_caster
,petentry
))
4369 if(NewSummon
->getPetType()==SUMMON_PET
)
4371 // Remove Demonic Sacrifice auras (known pet)
4372 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4373 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4375 if((*itr
)->GetModifier()->m_miscvalue
== 2228)
4377 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4378 itr
= auraClassScripts
.begin();
4388 // not error in case fail hunter call pet
4395 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(petentry
);
4399 sLog
.outError("EffectSummonPet: creature entry %u not found.",petentry
);
4404 Map
*map
= m_caster
->GetMap();
4405 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
4406 if(!NewSummon
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
4407 petentry
, pet_number
))
4414 m_caster
->GetClosePoint(px
, py
, pz
, NewSummon
->GetObjectSize());
4416 NewSummon
->Relocate(px
, py
, pz
, m_caster
->GetOrientation());
4418 if(!NewSummon
->IsPositionValid())
4420 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
4421 NewSummon
->GetGUIDLow(), NewSummon
->GetEntry(), NewSummon
->GetPositionX(), NewSummon
->GetPositionY());
4426 uint32 petlevel
= m_caster
->getLevel();
4427 NewSummon
->setPetType(SUMMON_PET
);
4429 uint32 faction
= m_caster
->getFaction();
4430 if(m_caster
->GetTypeId() == TYPEID_UNIT
)
4432 if ( ((Creature
*)m_caster
)->isTotem() )
4433 NewSummon
->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE
);
4435 NewSummon
->GetCharmInfo()->SetReactState(REACT_DEFENSIVE
);
4438 NewSummon
->SetOwnerGUID(m_caster
->GetGUID());
4439 NewSummon
->SetCreatorGUID(m_caster
->GetGUID());
4440 NewSummon
->SetUInt32Value(UNIT_NPC_FLAGS
, UNIT_NPC_FLAG_NONE
);
4441 NewSummon
->setFaction(faction
);
4442 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_0
, 2048);
4443 NewSummon
->SetUInt32Value(UNIT_FIELD_BYTES_1
, 0);
4444 NewSummon
->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP
, time(NULL
));
4445 NewSummon
->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE
, 0);
4446 NewSummon
->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP
, 1000);
4447 NewSummon
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
4449 NewSummon
->GetCharmInfo()->SetPetNumber(pet_number
, true);
4450 // this enables pet details window (Shift+P)
4452 // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4453 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4454 NewSummon
->SetUInt32Value(UNIT_FIELD_FLAGS
,UNIT_FLAG_PVP_ATTACKABLE
);
4456 if(m_caster
->IsPvP())
4457 NewSummon
->SetPvP(true);
4459 NewSummon
->InitStatsForLevel(petlevel
, m_caster
);
4460 NewSummon
->InitPetCreateSpells();
4461 NewSummon
->InitLevelupSpellsForLevel();
4462 NewSummon
->InitTalentForLevel();
4464 if(NewSummon
->getPetType()==SUMMON_PET
)
4466 // Remove Demonic Sacrifice auras (new pet)
4467 Unit::AuraList
const& auraClassScripts
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4468 for(Unit::AuraList::const_iterator itr
= auraClassScripts
.begin();itr
!=auraClassScripts
.end();)
4470 if((*itr
)->GetModifier()->m_miscvalue
==2228)
4472 m_caster
->RemoveAurasDueToSpell((*itr
)->GetId());
4473 itr
= auraClassScripts
.begin();
4479 // generate new name for summon pet
4480 std::string new_name
=sObjectMgr
.GeneratePetName(petentry
);
4481 if(!new_name
.empty())
4482 NewSummon
->SetName(new_name
);
4484 else if(NewSummon
->getPetType()==HUNTER_PET
)
4485 NewSummon
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_NOT_ALLOWED
);
4487 NewSummon
->AIM_Initialize();
4488 NewSummon
->SetHealth(NewSummon
->GetMaxHealth());
4489 NewSummon
->SetPower(POWER_MANA
, NewSummon
->GetMaxPower(POWER_MANA
));
4491 map
->Add((Creature
*)NewSummon
);
4493 m_caster
->SetPet(NewSummon
);
4494 sLog
.outDebug("New Pet has guid %u", NewSummon
->GetGUIDLow());
4496 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
4498 NewSummon
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4499 ((Player
*)m_caster
)->PetSpellInitialize();
4503 void Spell::EffectLearnPetSpell(uint32 i
)
4505 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
4508 Player
*_player
= (Player
*)m_caster
;
4510 Pet
*pet
= _player
->GetPet();
4516 SpellEntry
const *learn_spellproto
= sSpellStore
.LookupEntry(m_spellInfo
->EffectTriggerSpell
[i
]);
4517 if(!learn_spellproto
)
4520 pet
->learnSpell(learn_spellproto
->Id
);
4522 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
4523 _player
->PetSpellInitialize();
4526 void Spell::EffectTaunt(uint32
/*i*/)
4531 // this effect use before aura Taunt apply for prevent taunt already attacking target
4532 // for spell as marked "non effective at already attacking target"
4533 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
4535 if (unitTarget
->getVictim()==m_caster
)
4537 SendCastResult(SPELL_FAILED_DONT_REPORT
);
4542 // Also use this effect to set the taunter's threat to the taunted creature's highest value
4543 if (unitTarget
->CanHaveThreatList() && unitTarget
->getThreatManager().getCurrentVictim())
4544 unitTarget
->getThreatManager().addThreat(m_caster
,unitTarget
->getThreatManager().getCurrentVictim()->getThreat());
4547 void Spell::EffectWeaponDmg(uint32 i
)
4551 if(!unitTarget
->isAlive())
4554 // multiple weapon dmg effect workaround
4555 // execute only the last weapon damage
4556 // and handle all effects at once
4557 for (int j
= 0; j
< 3; ++j
)
4559 switch(m_spellInfo
->Effect
[j
])
4561 case SPELL_EFFECT_WEAPON_DAMAGE
:
4562 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4563 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4564 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4565 if (j
< i
) // we must calculate only at last weapon effect
4571 // some spell specific modifiers
4572 bool spellBonusNeedWeaponDamagePercentMod
= false; // if set applied weapon damage percent mode to spell bonus
4574 float weaponDamagePercentMod
= 1.0f
; // applied to weapon damage and to fixed effect damage bonus
4575 float totalDamagePercentMod
= 1.0f
; // applied to final bonus+weapon damage
4576 bool normalized
= false;
4578 int32 spell_bonus
= 0; // bonus specific for spell
4579 switch(m_spellInfo
->SpellFamilyName
)
4581 case SPELLFAMILY_WARRIOR
:
4583 // Devastate bonus and sunder armor refresh
4584 if(m_spellInfo
->SpellVisual
[0] == 12295 && m_spellInfo
->SpellIconID
== 1508)
4587 // Need refresh all Sunder Armor auras from this caster
4588 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
4589 SpellEntry
const *spellInfo
;
4590 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
4592 spellInfo
= (*itr
).second
->GetSpellProto();
4593 if( spellInfo
->SpellFamilyName
== SPELLFAMILY_WARRIOR
&&
4594 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000004000)) &&
4595 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
4597 (*itr
).second
->RefreshAura();
4598 stack
= (*itr
).second
->GetStackAmount();
4603 spell_bonus
+= stack
* CalculateDamage(2, unitTarget
);
4604 if (!stack
|| stack
< spellInfo
->StackAmount
)
4605 // Devastate causing Sunder Armor Effect
4606 // and no need to cast over max stack amount
4607 m_caster
->CastSpell(unitTarget
, 58567, true);
4611 case SPELLFAMILY_ROGUE
:
4613 // Mutilate (for each hand)
4614 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x600000000))
4618 if(unitTarget
->HasAuraState(AURA_STATE_DEADLY_POISON
))
4623 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4624 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4626 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_POISON
)
4635 totalDamagePercentMod
*= 1.2f
; // 120% if poisoned
4638 else if (m_caster
->GetTypeId()==TYPEID_PLAYER
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0004000000000000)))
4640 Item
* weapon
= ((Player
*)m_caster
)->GetWeaponForAttack(m_attackType
,true,true);
4641 if (weapon
&& weapon
->GetProto()->SubClass
== ITEM_SUBCLASS_WEAPON_DAGGER
)
4642 totalDamagePercentMod
*= 1.5f
; // 150% to daggers
4646 case SPELLFAMILY_PALADIN
:
4648 // Seal of Command - receive benefit from Spell Damage and Healing
4649 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x00000002000000))
4651 spellBonusNeedWeaponDamagePercentMod
= true;// apply weaponDamagePercentMod to spell_bonus (and then to all bonus, fixes and weapon already have applied)
4652 spell_bonus
+= int32(0.23f
*m_caster
->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo
)));
4653 spell_bonus
+= int32(0.29f
*m_caster
->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo
), unitTarget
));
4657 case SPELLFAMILY_SHAMAN
:
4659 // Skyshatter Harness item set bonus
4661 if(m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x001000000000))
4663 Unit::AuraList
const& m_OverrideClassScript
= m_caster
->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
);
4664 for(Unit::AuraList::const_iterator citr
= m_OverrideClassScript
.begin(); citr
!= m_OverrideClassScript
.end(); ++citr
)
4666 // Stormstrike AP Buff
4667 if ( (*citr
)->GetModifier()->m_miscvalue
== 5634 )
4669 m_caster
->CastSpell(m_caster
, 38430, true, NULL
, *citr
);
4676 case SPELLFAMILY_DEATHKNIGHT
:
4678 // Blood Strike, Heart Strike, Obliterate
4679 // Blood-Caked Strike, Scourge Strike
4680 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0002000001400000) ||
4681 m_spellInfo
->SpellIconID
== 1736 || m_spellInfo
->SpellIconID
== 3143)
4684 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
4685 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!=auras
.end(); ++itr
)
4687 if(itr
->second
->GetSpellProto()->Dispel
== DISPEL_DISEASE
&&
4688 itr
->second
->GetCasterGUID() == m_caster
->GetGUID() &&
4689 IsSpellLastAuraEffect(itr
->second
->GetSpellProto(), itr
->second
->GetEffIndex()))
4695 // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus
4696 float bonus
= count
* CalculateDamage(m_spellInfo
->SpellIconID
== 1736 ? 0 : 2, unitTarget
) / 100.0f
;
4697 // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2
4698 if (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0002000000400000) ||
4699 m_spellInfo
->SpellIconID
== 1736)
4702 totalDamagePercentMod
*= 1.0f
+ bonus
;
4705 // Glyph of Blood Strike
4706 if( m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000400000) &&
4707 m_caster
->HasAura(59332) &&
4708 unitTarget
->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED
))
4710 totalDamagePercentMod
*= 1.2f
; // 120% if snared
4712 // Glyph of Death Strike
4713 if( m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000010) &&
4714 m_caster
->HasAura(59336))
4716 int32 rp
= m_caster
->GetPower(POWER_RUNIC_POWER
) / 10;
4719 totalDamagePercentMod
*= 1.0f
+ rp
/ 100.0f
;
4721 // Glyph of Plague Strike
4722 if( m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000001) &&
4723 m_caster
->HasAura(58657) )
4725 totalDamagePercentMod
*= 1.2f
;
4731 int32 fixed_bonus
= 0;
4732 for (int j
= 0; j
< 3; ++j
)
4734 switch(m_spellInfo
->Effect
[j
])
4736 case SPELL_EFFECT_WEAPON_DAMAGE
:
4737 case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
:
4738 fixed_bonus
+= CalculateDamage(j
, unitTarget
);
4740 case SPELL_EFFECT_NORMALIZED_WEAPON_DMG
:
4741 fixed_bonus
+= CalculateDamage(j
, unitTarget
);
4744 case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
:
4745 weaponDamagePercentMod
*= float(CalculateDamage(j
, unitTarget
)) / 100.0f
;
4747 // applied only to prev.effects fixed damage
4748 fixed_bonus
= int32(fixed_bonus
*weaponDamagePercentMod
);
4751 break; // not weapon damage effect, just skip
4755 // apply weaponDamagePercentMod to spell bonus also
4756 if(spellBonusNeedWeaponDamagePercentMod
)
4757 spell_bonus
= int32(spell_bonus
*weaponDamagePercentMod
);
4759 // non-weapon damage
4760 int32 bonus
= spell_bonus
+ fixed_bonus
;
4762 // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4766 switch(m_attackType
)
4769 case BASE_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_MAINHAND
; break;
4770 case OFF_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_OFFHAND
; break;
4771 case RANGED_ATTACK
: unitMod
= UNIT_MOD_DAMAGE_RANGED
; break;
4774 float weapon_total_pct
= m_caster
->GetModifierValue(unitMod
, TOTAL_PCT
);
4775 bonus
= int32(bonus
*weapon_total_pct
);
4778 // + weapon damage with applied weapon% dmg to base weapon damage in call
4779 bonus
+= int32(m_caster
->CalculateDamage(m_attackType
, normalized
)*weaponDamagePercentMod
);
4782 bonus
= int32(bonus
*totalDamagePercentMod
);
4784 // prevent negative damage
4785 m_damage
+= uint32(bonus
> 0 ? bonus
: 0);
4788 if (m_spellInfo
->SpellFamilyName
==SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& UI64LIT(0x2000000)))
4790 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4791 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4794 else if (m_spellInfo
->SpellFamilyName
==SPELLFAMILY_DRUID
&& (m_spellInfo
->SpellFamilyFlags
==UI64LIT(0x0000040000000000)))
4796 if(m_caster
->GetTypeId()==TYPEID_PLAYER
)
4797 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, 1);
4799 else if(m_spellInfo
->SpellFamilyName
==SPELLFAMILY_PALADIN
)
4801 // Judgement of Blood/of the Martyr backlash damage (33%)
4802 if(m_spellInfo
->SpellFamilyFlags
& 0x0000000800000000LL
&& m_spellInfo
->SpellIconID
==153)
4804 int32 damagePoint
= m_damage
* 33 / 100;
4805 if(m_spellInfo
->Id
== 31898)
4806 m_caster
->CastCustomSpell(m_caster
, 32220, &damagePoint
, NULL
, NULL
, true);
4808 m_caster
->CastCustomSpell(m_caster
, 53725, &damagePoint
, NULL
, NULL
, true);
4813 if(m_attackType
== RANGED_ATTACK
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4815 Item
*pItem
= ((Player
*)m_caster
)->GetWeaponForAttack(RANGED_ATTACK
, true, false);
4817 // wands don't have ammo
4818 if (!pItem
|| pItem
->GetProto()->SubClass
== ITEM_SUBCLASS_WEAPON_WAND
)
4821 if (pItem
->GetProto()->InventoryType
== INVTYPE_THROWN
)
4823 if(pItem
->GetMaxStackCount()==1)
4825 // decrease durability for non-stackable throw weapon
4826 ((Player
*)m_caster
)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED
);
4830 // decrease items amount for stackable throw weapon
4832 ((Player
*)m_caster
)->DestroyItemCount( pItem
, count
, true);
4835 else if(uint32 ammo
= ((Player
*)m_caster
)->GetUInt32Value(PLAYER_AMMO_ID
))
4836 ((Player
*)m_caster
)->DestroyItemCount(ammo
, 1, true);
4840 void Spell::EffectThreat(uint32
/*i*/)
4842 if(!unitTarget
|| !unitTarget
->isAlive() || !m_caster
->isAlive())
4845 if(!unitTarget
->CanHaveThreatList())
4848 unitTarget
->AddThreat(m_caster
, float(damage
), false, GetSpellSchoolMask(m_spellInfo
), m_spellInfo
);
4851 void Spell::EffectHealMaxHealth(uint32
/*i*/)
4855 if(!unitTarget
->isAlive())
4858 uint32 heal
= m_caster
->GetMaxHealth();
4863 void Spell::EffectInterruptCast(uint32
/*i*/)
4867 if(!unitTarget
->isAlive())
4870 // TODO: not all spells that used this effect apply cooldown at school spells
4871 // also exist case: apply cooldown to interrupted cast only and to all spells
4872 for (uint32 i
= CURRENT_FIRST_NON_MELEE_SPELL
; i
< CURRENT_MAX_SPELL
; ++i
)
4874 if (Spell
* spell
= unitTarget
->GetCurrentSpell(CurrentSpellTypes(i
)))
4876 SpellEntry
const* curSpellInfo
= spell
->m_spellInfo
;
4877 // check if we can interrupt spell
4878 if ((curSpellInfo
->InterruptFlags
& SPELL_INTERRUPT_FLAG_INTERRUPT
) && curSpellInfo
->PreventionType
== SPELL_PREVENTION_TYPE_SILENCE
)
4880 unitTarget
->ProhibitSpellScholl(GetSpellSchoolMask(curSpellInfo
), GetSpellDuration(m_spellInfo
));
4881 unitTarget
->InterruptSpell(CurrentSpellTypes(i
),false);
4887 void Spell::EffectSummonObjectWild(uint32 i
)
4889 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
4891 GameObject
* pGameObj
= new GameObject
;
4893 WorldObject
* target
= focusObject
;
4898 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
4900 x
= m_targets
.m_destX
;
4901 y
= m_targets
.m_destY
;
4902 z
= m_targets
.m_destZ
;
4905 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
4907 Map
*map
= target
->GetMap();
4909 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
, map
,
4910 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
4916 int32 duration
= GetSpellDuration(m_spellInfo
);
4918 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4919 pGameObj
->SetSpellId(m_spellInfo
->Id
);
4921 // Wild object not have owner and check clickable by players
4924 if(pGameObj
->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
4926 Player
*pl
= (Player
*)m_caster
;
4927 BattleGround
* bg
= ((Player
*)m_caster
)->GetBattleGround();
4929 switch(pGameObj
->GetMapId())
4933 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_WS
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4935 uint32 team
= ALLIANCE
;
4937 if(pl
->GetTeam() == team
)
4940 ((BattleGroundWS
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID(),team
);
4946 if(bg
&& bg
->GetTypeID()==BATTLEGROUND_EY
&& bg
->GetStatus() == STATUS_IN_PROGRESS
)
4948 ((BattleGroundEY
*)bg
)->SetDroppedFlagGUID(pGameObj
->GetGUID());
4955 if(uint32 linkedEntry
= pGameObj
->GetGOInfo()->GetLinkedGameObjectEntry())
4957 GameObject
* linkedGO
= new GameObject
;
4958 if(linkedGO
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, map
,
4959 m_caster
->GetPhaseMask(), x
, y
, z
, target
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
4961 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
4962 linkedGO
->SetSpellId(m_spellInfo
->Id
);
4964 // Wild object not have owner and check clickable by players
4976 void Spell::EffectScriptEffect(uint32 effIndex
)
4978 // TODO: we must implement hunter pet summon at login there (spell 6962)
4980 switch(m_spellInfo
->SpellFamilyName
)
4982 case SPELLFAMILY_GENERIC
:
4984 switch(m_spellInfo
->Id
)
4986 // PX-238 Winter Wondervolt TRAP
4989 uint32 spells
[4] = { 26272, 26157, 26273, 26274 };
4992 for(int j
= 0; j
< 4; ++j
)
4993 if(unitTarget
->HasAura(spells
[j
],0))
4997 uint32 iTmpSpellId
= spells
[urand(0,3)];
5000 unitTarget
->CastSpell(unitTarget
, iTmpSpellId
, true);
5006 if(!itemTarget
&& m_caster
->GetTypeId()!=TYPEID_PLAYER
)
5009 uint32 spell_id
= 0;
5012 case 1: spell_id
= 8854; break;
5013 default: spell_id
= 8855; break;
5016 m_caster
->CastSpell(m_caster
,spell_id
,true,NULL
);
5019 // Brittle Armor - need remove one 24575 Brittle Armor aura
5021 unitTarget
->RemoveSingleSpellAurasFromStack(24575);
5023 // Mercurial Shield - need remove one 26464 Mercurial Shield aura
5025 unitTarget
->RemoveSingleSpellAurasFromStack(26464);
5027 // Orb teleport spells
5041 switch(m_spellInfo
->Id
)
5043 case 25140: spellid
= 32571; break;
5044 case 25143: spellid
= 32572; break;
5045 case 25650: spellid
= 30140; break;
5046 case 25652: spellid
= 30141; break;
5047 case 29128: spellid
= 32568; break;
5048 case 29129: spellid
= 32569; break;
5049 case 35376: spellid
= 25649; break;
5050 case 35727: spellid
= 35730; break;
5055 unitTarget
->CastSpell(unitTarget
,spellid
,false);
5058 // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
5073 if(!unitTarget
|| !unitTarget
->isAlive())
5076 // Onyxia Scale Cloak
5077 if(unitTarget
->GetDummyAura(22683))
5081 m_caster
->CastSpell(unitTarget
, 22682, true);
5084 // Summon Black Qiraji Battle Tank
5090 // Prevent stacking of mounts
5091 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
5093 // Two separate mounts depending on area id (allows use both in and out of specific instance)
5094 if (unitTarget
->GetAreaId() == 3428)
5095 unitTarget
->CastSpell(unitTarget
, 25863, false);
5097 unitTarget
->CastSpell(unitTarget
, 26655, false);
5100 // Piccolo of the Flaming Fire
5103 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5105 unitTarget
->HandleEmoteCommand(EMOTE_STATE_DANCE
);
5108 // Demonic Empowerment (succubus Vanish effect)
5114 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5115 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
5116 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED
);
5117 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN
);
5126 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5127 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED
);
5130 // Mirren's Drinking Hat
5134 switch ( urand(1, 6) )
5139 item
= 23584; break; // Loch Modan Lager
5142 item
= 23585; break; // Stouthammer Lite
5144 item
= 23586; break; // Aerie Peak Pale Ale
5147 DoCreateItem(effIndex
,item
);
5155 // Removes snares and roots.
5156 unitTarget
->RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK
,30918,true);
5165 unitTarget
->CastSpell(unitTarget
, 41131, true);
5168 // Force Cast - Portal Effect: Sunwell Isle
5174 unitTarget
->CastSpell(unitTarget
, 44870, true);
5177 // Goblin Weather Machine
5186 case 0: spellId
= 46740; break;
5187 case 1: spellId
= 46739; break;
5188 case 2: spellId
= 46738; break;
5189 case 3: spellId
= 46736; break;
5191 unitTarget
->CastSpell(unitTarget
, spellId
, true);
5197 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5200 ((Player
*)unitTarget
)->ModifyMoney(50000000);
5204 // Emblazon Runeblade
5207 if(!m_originalCaster
)
5210 m_originalCaster
->CastSpell(m_originalCaster
, damage
, false);
5216 if(!unitTarget
|| unitTarget
->getClass() != CLASS_DEATH_KNIGHT
)
5218 // triggered spell is stored in m_spellInfo->EffectBasePoints[0]
5219 unitTarget
->CastSpell(unitTarget
, damage
, false);
5222 // Winged Steed of the Ebon Blade
5225 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5228 // Prevent stacking of mounts
5229 unitTarget
->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED
);
5231 // Triggered spell id dependent of riding skill
5232 if(uint16 skillval
= ((Player
*)unitTarget
)->GetSkillValue(SKILL_RIDING
))
5234 if (skillval
>= 300)
5235 unitTarget
->CastSpell(unitTarget
, 54727, true);
5237 unitTarget
->CastSpell(unitTarget
, 54726, true);
5241 case 55693: // Remove Collapsing Cave Aura
5244 unitTarget
->RemoveAurasDueToSpell(m_spellInfo
->CalculateSimpleValue(effIndex
));
5246 case 58418: // Portal to Orgrimmar
5247 case 58420: // Portal to Stormwind
5249 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
|| effIndex
!=0)
5252 uint32 spellID
= m_spellInfo
->CalculateSimpleValue(0);
5253 uint32 questID
= m_spellInfo
->CalculateSimpleValue(1);
5255 if (((Player
*)unitTarget
)->GetQuestStatus(questID
) == QUEST_STATUS_COMPLETE
&& !((Player
*)unitTarget
)->GetQuestRewardStatus (questID
))
5256 unitTarget
->CastSpell(unitTarget
, spellID
, true);
5260 case 59317: // Teleporting
5261 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5265 if (((Player
*)unitTarget
)->GetAreaId() == 4637)
5266 unitTarget
->CastSpell(unitTarget
, 59316, true);
5269 unitTarget
->CastSpell(unitTarget
, 59314, true);
5272 // random spell learn instead placeholder
5273 case 60893: // Northrend Alchemy Research
5274 case 61177: // Northrend Inscription Research
5275 case 61288: // Minor Inscription Research
5276 case 61756: // Northrend Inscription Research (FAST QA VERSION)
5277 case 64323: // Book of Glyph Mastery
5279 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5282 // learn random explicit discovery recipe (if any)
5283 if(uint32 discoveredSpell
= GetExplicitDiscoverySpell(m_spellInfo
->Id
, (Player
*)m_caster
))
5284 ((Player
*)m_caster
)->learnSpell(discoveredSpell
, false);
5290 case SPELLFAMILY_WARLOCK
:
5292 switch(m_spellInfo
->Id
)
5294 // Healthstone creating spells
5308 Unit::AuraList
const& mDummyAuras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
5309 for(Unit::AuraList::const_iterator i
= mDummyAuras
.begin();i
!= mDummyAuras
.end(); ++i
)
5311 if((*i
)->GetId() == 18692)
5316 else if((*i
)->GetId() == 18693)
5323 static uint32
const itypes
[8][3] = {
5324 { 5512, 19004, 19005}, // Minor Healthstone
5325 { 5511, 19006, 19007}, // Lesser Healthstone
5326 { 5509, 19008, 19009}, // Healthstone
5327 { 5510, 19010, 19011}, // Greater Healthstone
5328 { 9421, 19012, 19013}, // Major Healthstone
5329 {22103, 22104, 22105}, // Master Healthstone
5330 {36889, 36890, 36891}, // Demonic Healthstone
5331 {36892, 36893, 36894} // Fel Healthstone
5334 switch(m_spellInfo
->Id
)
5337 itemtype
=itypes
[0][rank
];break; // Minor Healthstone
5339 itemtype
=itypes
[1][rank
];break; // Lesser Healthstone
5341 itemtype
=itypes
[2][rank
];break; // Healthstone
5343 itemtype
=itypes
[3][rank
];break; // Greater Healthstone
5345 itemtype
=itypes
[4][rank
];break; // Major Healthstone
5347 itemtype
=itypes
[5][rank
];break; // Master Healthstone
5349 itemtype
=itypes
[6][rank
];break; // Demonic Healthstone
5351 itemtype
=itypes
[7][rank
];break; // Fel Healthstone
5355 DoCreateItem( effIndex
, itemtype
);
5358 // Demonic Empowerment
5363 uint32 entry
= unitTarget
->GetEntry();
5367 case 416: spellID
= 54444; break; //imp
5368 case 417: spellID
= 54509; break; //fellhunter
5369 case 1860: spellID
= 54443; break; //void
5370 case 1863: spellID
= 54435; break; //succubus
5371 case 17252: spellID
= 54508; break; //fellguard
5375 unitTarget
->CastSpell(unitTarget
,spellID
,true);
5378 // Everlasting Affliction
5381 // Need refresh caster corruption auras on target
5382 Unit::AuraMap
& suAuras
= unitTarget
->GetAuras();
5383 for(Unit::AuraMap::iterator itr
= suAuras
.begin(); itr
!= suAuras
.end(); ++itr
)
5385 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5386 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_WARLOCK
&&
5387 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000000002)) &&
5388 (*itr
).second
->GetCasterGUID()==m_caster
->GetGUID())
5389 (*itr
).second
->RefreshAura();
5393 // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
5396 // Divine Plea, refresh on target (3 aura slots)
5397 if (Aura
* aura
= unitTarget
->GetAura(54428,0))
5398 aura
->RefreshAura();
5404 case SPELLFAMILY_PRIEST
:
5406 switch(m_spellInfo
->Id
)
5408 // Pain and Suffering
5413 // Refresh Shadow Word: Pain on target
5414 Unit::AuraMap
& auras
= unitTarget
->GetAuras();
5415 for(Unit::AuraMap::iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
5417 SpellEntry
const *spellInfo
= (*itr
).second
->GetSpellProto();
5418 if (spellInfo
->SpellFamilyName
== SPELLFAMILY_PRIEST
&&
5419 (spellInfo
->SpellFamilyFlags
& UI64LIT(0x0000000000008000)) &&
5420 (*itr
).second
->GetCasterGUID() == m_caster
->GetGUID())
5422 (*itr
).second
->RefreshAura();
5433 case SPELLFAMILY_HUNTER
:
5435 switch(m_spellInfo
->Id
)
5443 int32 basePoint
= 0;
5444 Unit
* target
= unitTarget
;
5445 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
5446 for(Unit::AuraMap::iterator i
= Auras
.begin(); i
!= Auras
.end(); ++i
)
5448 Aura
*aura
= (*i
).second
;
5449 if (aura
->GetCasterGUID() != m_caster
->GetGUID())
5451 // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
5452 uint64 familyFlag
= aura
->GetSpellProto()->SpellFamilyFlags
;
5453 if (!(familyFlag
& UI64LIT(0x000000800000C000)))
5455 // Refresh aura duration
5456 aura
->RefreshAura();
5458 // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
5459 if ((familyFlag
& UI64LIT(0x0000000000004000)) && aura
->GetEffIndex() == 0)
5461 // m_amount already include RAP bonus
5462 basePoint
= aura
->GetModifier()->m_amount
* 5 * 40 / 100;
5463 spellId
= 53353; // Chimera Shot - Serpent
5465 // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
5466 if ((familyFlag
& UI64LIT(0x0000008000000000)) && aura
->GetEffIndex() == 0)
5468 uint32 target_max_mana
= unitTarget
->GetMaxPower(POWER_MANA
);
5469 if (!target_max_mana
)
5472 // ignore non positive values (can be result apply spellmods to aura damage
5473 uint32 pdamage
= aura
->GetModifier()->m_amount
> 0 ? aura
->GetModifier()->m_amount
: 0;
5475 // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
5476 uint32 maxmana
= m_caster
->GetMaxPower(POWER_MANA
) * pdamage
* 2 / 100;
5478 pdamage
= target_max_mana
* pdamage
/ 100;
5479 if (pdamage
> maxmana
)
5482 pdamage
*= 4; // total aura damage
5483 basePoint
= pdamage
* 60 / 100;
5484 spellId
= 53358; // Chimera Shot - Viper
5487 // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
5488 if (familyFlag
& UI64LIT(0x0000000000008000))
5489 spellId
= 53359; // Chimera Shot - Scorpid
5490 // ?? nothing say in spell desc (possibly need addition check)
5491 //if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
5492 // (familyFlag & UI64LIT(0x0000100000000000))) // stun
5494 // spellId = 53366; // 53366 Chimera Shot - Wyvern
5498 m_caster
->CastCustomSpell(target
, spellId
, &basePoint
, 0, 0, false);
5501 case 53412: // Invigoration (pet triggered script, master targeted)
5506 Unit::AuraList
const& auras
= unitTarget
->GetAurasByType(SPELL_AURA_DUMMY
);
5507 for(Unit::AuraList::const_iterator i
= auras
.begin();i
!= auras
.end(); ++i
)
5509 // Invigoration (master talent)
5510 if ((*i
)->GetModifier()->m_miscvalue
== 8 && (*i
)->GetSpellProto()->SpellIconID
== 3487)
5512 if (roll_chance_i((*i
)->GetModifier()->m_amount
))
5514 unitTarget
->CastSpell(unitTarget
, 53398, true, NULL
, (*i
), m_caster
->GetGUID());
5527 // script effect have in value, but this outdated removed part
5528 unitTarget
->CastSpell(unitTarget
, 62305, true);
5536 case SPELLFAMILY_PALADIN
:
5538 // Judgement (seal trigger)
5539 if (m_spellInfo
->Category
== SPELLCATEGORY_JUDGEMENT
)
5541 if(!unitTarget
|| !unitTarget
->isAlive())
5543 uint32 spellId1
= 0;
5544 uint32 spellId2
= 0;
5546 // Judgement self add switch
5547 switch (m_spellInfo
->Id
)
5549 case 53407: spellId1
= 20184; break; // Judgement of Justice
5550 case 20271: // Judgement of Light
5551 case 57774: spellId1
= 20185; break; // Judgement of Light
5552 case 53408: spellId1
= 20186; break; // Judgement of Wisdom
5554 sLog
.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo
->Id
);
5557 // offensive seals have aura dummy in 2 effect
5558 Unit::AuraList
const& m_dummyAuras
= m_caster
->GetAurasByType(SPELL_AURA_DUMMY
);
5559 for(Unit::AuraList::const_iterator itr
= m_dummyAuras
.begin(); itr
!= m_dummyAuras
.end(); ++itr
)
5561 // search seal (offensive seals have judgement's aura dummy spell id in 2 effect
5562 if ((*itr
)->GetEffIndex() != 2 || !IsSealSpell((*itr
)->GetSpellProto()))
5564 spellId2
= (*itr
)->GetModifier()->m_amount
;
5565 SpellEntry
const *judge
= sSpellStore
.LookupEntry(spellId2
);
5570 // if there were no offensive seals than there is seal with proc trigger aura
5573 Unit::AuraList
const& procTriggerAuras
= m_caster
->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL
);
5574 for(Unit::AuraList::const_iterator itr
= procTriggerAuras
.begin(); itr
!= procTriggerAuras
.end(); ++itr
)
5576 if ((*itr
)->GetEffIndex() != 0 || !IsSealSpell((*itr
)->GetSpellProto()))
5583 m_caster
->CastSpell(unitTarget
, spellId1
, true);
5585 m_caster
->CastSpell(unitTarget
, spellId2
, true);
5589 case SPELLFAMILY_POTION
:
5591 switch(m_spellInfo
->Id
)
5598 unitTarget
->CastSpell(unitTarget
, 28694, true);
5606 // 25% chance of casting a random buff
5607 if(roll_chance_i(75))
5610 // triggered spells are 28703 to 28707
5611 // Note: some sources say, that there was the possibility of
5612 // receiving a debuff. However, this seems to be removed by a patch.
5613 const uint32 spellid
= 28703;
5615 // don't overwrite an existing aura
5616 for(uint8 i
= 0; i
< 5; ++i
)
5617 if(unitTarget
->HasAura(spellid
+ i
, 0))
5619 unitTarget
->CastSpell(unitTarget
, spellid
+urand(0, 4), true);
5628 // 25% chance of casting Nightmare Pollen
5629 if(roll_chance_i(75))
5631 unitTarget
->CastSpell(unitTarget
, 28721, true);
5637 case SPELLFAMILY_DEATHKNIGHT
:
5639 switch(m_spellInfo
->Id
)
5647 Unit
* mainTarget
= m_targets
.getUnitTarget();
5651 // do only refresh diseases on main target if caster has Glyph of Disease
5652 if(mainTarget
== unitTarget
&& !m_caster
->HasAura(63334))
5656 if(mainTarget
->HasAura(55078))
5657 m_caster
->CastSpell(unitTarget
, 55078, true);
5660 if(mainTarget
->HasAura(55095))
5661 m_caster
->CastSpell(unitTarget
, 55095, true);
5670 // normal DB scripted effect
5674 sLog
.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo
->Id
);
5675 m_caster
->GetMap()->ScriptsStart(sSpellScripts
, m_spellInfo
->Id
, m_caster
, unitTarget
);
5678 void Spell::EffectSanctuary(uint32
/*i*/)
5682 //unitTarget->CombatStop();
5684 unitTarget
->CombatStop();
5685 unitTarget
->getHostileRefManager().deleteReferences(); // stop all fighting
5686 // Vanish allows to remove all threat and cast regular stealth so other spells can be used
5687 if(m_spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
&& (m_spellInfo
->SpellFamilyFlags
& SPELLFAMILYFLAG_ROGUE_VANISH
))
5689 ((Player
*)m_caster
)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT
);
5693 void Spell::EffectAddComboPoints(uint32
/*i*/)
5698 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5704 ((Player
*)m_caster
)->AddComboPoints(unitTarget
, damage
);
5707 void Spell::EffectDuel(uint32 i
)
5709 if(!m_caster
|| !unitTarget
|| m_caster
->GetTypeId() != TYPEID_PLAYER
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5712 Player
*caster
= (Player
*)m_caster
;
5713 Player
*target
= (Player
*)unitTarget
;
5715 // caster or target already have requested duel
5716 if( caster
->duel
|| target
->duel
|| !target
->GetSocial() || target
->GetSocial()->HasIgnore(caster
->GetGUIDLow()) )
5719 // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5720 // Don't have to check the target's map since you cannot challenge someone across maps
5721 uint32 mapid
= caster
->GetMapId();
5722 if( mapid
!= 0 && mapid
!= 1 && mapid
!= 530 && mapid
!= 571 && mapid
!= 609)
5724 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5728 AreaTableEntry
const* casterAreaEntry
= GetAreaEntryByAreaID(caster
->GetZoneId());
5729 if(casterAreaEntry
&& (casterAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5731 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5735 AreaTableEntry
const* targetAreaEntry
= GetAreaEntryByAreaID(target
->GetZoneId());
5736 if(targetAreaEntry
&& (targetAreaEntry
->flags
& AREA_FLAG_CAPITAL
) )
5738 SendCastResult(SPELL_FAILED_NO_DUELING
); // Dueling isn't allowed here
5742 //CREATE DUEL FLAG OBJECT
5743 GameObject
* pGameObj
= new GameObject
;
5745 uint32 gameobject_id
= m_spellInfo
->EffectMiscValue
[i
];
5747 Map
*map
= m_caster
->GetMap();
5748 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), gameobject_id
,
5749 map
, m_caster
->GetPhaseMask(),
5750 m_caster
->GetPositionX()+(unitTarget
->GetPositionX()-m_caster
->GetPositionX())/2 ,
5751 m_caster
->GetPositionY()+(unitTarget
->GetPositionY()-m_caster
->GetPositionY())/2 ,
5752 m_caster
->GetPositionZ(),
5753 m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
5759 pGameObj
->SetUInt32Value(GAMEOBJECT_FACTION
, m_caster
->getFaction() );
5760 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel()+1 );
5761 int32 duration
= GetSpellDuration(m_spellInfo
);
5762 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
5763 pGameObj
->SetSpellId(m_spellInfo
->Id
);
5765 m_caster
->AddGameObject(pGameObj
);
5770 WorldPacket
data(SMSG_DUEL_REQUESTED
, 8 + 8);
5771 data
<< uint64(pGameObj
->GetGUID());
5772 data
<< uint64(caster
->GetGUID());
5773 caster
->GetSession()->SendPacket(&data
);
5774 target
->GetSession()->SendPacket(&data
);
5777 DuelInfo
*duel
= new DuelInfo
;
5778 duel
->initiator
= caster
;
5779 duel
->opponent
= target
;
5780 duel
->startTime
= 0;
5781 duel
->startTimer
= 0;
5782 caster
->duel
= duel
;
5784 DuelInfo
*duel2
= new DuelInfo
;
5785 duel2
->initiator
= caster
;
5786 duel2
->opponent
= caster
;
5787 duel2
->startTime
= 0;
5788 duel2
->startTimer
= 0;
5789 target
->duel
= duel2
;
5791 caster
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
5792 target
->SetUInt64Value(PLAYER_DUEL_ARBITER
, pGameObj
->GetGUID());
5795 void Spell::EffectStuck(uint32
/*i*/)
5797 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5800 if(!sWorld
.getConfig(CONFIG_CAST_UNSTUCK
))
5803 Player
* pTarget
= (Player
*)unitTarget
;
5805 sLog
.outDebug("Spell Effect: Stuck");
5806 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());
5808 if(pTarget
->isInFlight())
5811 // homebind location is loaded always
5812 pTarget
->TeleportToHomebind(unitTarget
==m_caster
? TELE_TO_SPELL
: 0);
5814 // Stuck spell trigger Hearthstone cooldown
5815 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(8690);
5818 Spell
spell(pTarget
, spellInfo
, true, 0);
5819 spell
.SendSpellCooldown();
5822 void Spell::EffectSummonPlayer(uint32
/*i*/)
5824 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5827 // Evil Twin (ignore player summon, but hide this for summoner)
5828 if(unitTarget
->GetDummyAura(23445))
5832 m_caster
->GetClosePoint(x
, y
, z
, unitTarget
->GetObjectSize());
5834 ((Player
*)unitTarget
)->SetSummonPoint(m_caster
->GetMapId(),x
,y
,z
);
5836 WorldPacket
data(SMSG_SUMMON_REQUEST
, 8+4+4);
5837 data
<< uint64(m_caster
->GetGUID()); // summoner guid
5838 data
<< uint32(m_caster
->GetZoneId()); // summoner zone
5839 data
<< uint32(MAX_PLAYER_SUMMON_DELAY
*IN_MILISECONDS
); // auto decline after msecs
5840 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);
5843 static ScriptInfo
generateActivateCommand()
5846 si
.command
= SCRIPT_COMMAND_ACTIVATE_OBJECT
;
5850 void Spell::EffectActivateObject(uint32 effect_idx
)
5855 static ScriptInfo activateCommand
= generateActivateCommand();
5857 int32 delay_secs
= m_spellInfo
->EffectMiscValue
[effect_idx
];
5859 gameObjTarget
->GetMap()->ScriptCommandStart(activateCommand
, delay_secs
, m_caster
, gameObjTarget
);
5862 void Spell::EffectApplyGlyph(uint32 i
)
5864 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
5867 Player
*player
= (Player
*)m_caster
;
5870 if(uint32 glyph
= m_spellInfo
->EffectMiscValue
[i
])
5872 if(GlyphPropertiesEntry
const *gp
= sGlyphPropertiesStore
.LookupEntry(glyph
))
5874 if(GlyphSlotEntry
const *gs
= sGlyphSlotStore
.LookupEntry(player
->GetGlyphSlot(m_glyphIndex
)))
5876 if(gp
->TypeFlags
!= gs
->TypeFlags
)
5878 SendCastResult(SPELL_FAILED_INVALID_GLYPH
);
5879 return; // glyph slot mismatch
5884 if(uint32 oldglyph
= player
->GetGlyph(m_glyphIndex
))
5886 if(GlyphPropertiesEntry
const *old_gp
= sGlyphPropertiesStore
.LookupEntry(oldglyph
))
5888 player
->RemoveAurasDueToSpell(old_gp
->SpellId
);
5889 player
->SetGlyph(m_glyphIndex
, 0);
5893 player
->CastSpell(m_caster
, gp
->SpellId
, true);
5894 player
->SetGlyph(m_glyphIndex
, glyph
);
5895 player
->SendTalentsInfoData(false);
5900 void Spell::EffectSummonTotem(uint32 i
, uint8 slot
)
5902 slot
= slot
? (slot
- 1): 255;
5904 if(slot
< MAX_TOTEM
)
5906 uint64 guid
= m_caster
->m_TotemSlot
[slot
];
5909 Creature
*OldTotem
= m_caster
->GetMap()->GetCreature(guid
);
5910 if(OldTotem
&& OldTotem
->isTotem())
5911 ((Totem
*)OldTotem
)->UnSummon();
5916 if (m_caster
->GetTypeId()==TYPEID_PLAYER
)
5917 team
= ((Player
*)m_caster
)->GetTeam();
5919 Totem
* pTotem
= new Totem
;
5921 if(!pTotem
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_UNIT
), m_caster
->GetMap(), m_caster
->GetPhaseMask(),
5922 m_spellInfo
->EffectMiscValue
[i
], team
))
5928 float angle
= slot
< MAX_TOTEM
? M_PI
/MAX_TOTEM
- (slot
*2*M_PI
/MAX_TOTEM
) : 0;
5931 m_caster
->GetClosePoint(x
, y
, z
, pTotem
->GetObjectSize(), 2.0f
, angle
);
5933 // totem must be at same Z in case swimming caster and etc.
5934 if( fabs( z
- m_caster
->GetPositionZ() ) > 5 )
5935 z
= m_caster
->GetPositionZ();
5937 pTotem
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
5939 if(slot
< MAX_TOTEM
)
5940 m_caster
->m_TotemSlot
[slot
] = pTotem
->GetGUID();
5942 pTotem
->SetOwner(m_caster
->GetGUID());
5943 pTotem
->SetTypeBySummonSpell(m_spellInfo
); // must be after Create call where m_spells initilized
5945 int32 duration
=GetSpellDuration(m_spellInfo
);
5946 if(Player
* modOwner
= m_caster
->GetSpellModOwner())
5947 modOwner
->ApplySpellMod(m_spellInfo
->Id
, SPELLMOD_DURATION
, duration
);
5948 pTotem
->SetDuration(duration
);
5950 if (damage
) // if not spell info, DB values used
5952 pTotem
->SetMaxHealth(damage
);
5953 pTotem
->SetHealth(damage
);
5956 pTotem
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
5958 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
5959 pTotem
->SetFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_PVP_ATTACKABLE
);
5961 if(m_caster
->IsPvP())
5962 pTotem
->SetPvP(true);
5964 pTotem
->Summon(m_caster
);
5966 if(slot
< MAX_TOTEM
&& m_caster
->GetTypeId() == TYPEID_PLAYER
)
5968 WorldPacket
data(SMSG_TOTEM_CREATED
, 1 + 8 + 4 + 4);
5969 data
<< uint8(slot
);
5970 data
<< uint64(pTotem
->GetGUID());
5971 data
<< uint32(duration
);
5972 data
<< uint32(m_spellInfo
->Id
);
5973 ((Player
*)m_caster
)->SendDirectMessage(&data
);
5977 void Spell::EffectEnchantHeldItem(uint32 i
)
5979 // this is only item spell effect applied to main-hand weapon of target player (players in area)
5980 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
5983 Player
* item_owner
= (Player
*)unitTarget
;
5984 Item
* item
= item_owner
->GetItemByPos(INVENTORY_SLOT_BAG_0
, EQUIPMENT_SLOT_MAINHAND
);
5990 if(!item
->IsEquipped())
5993 if (m_spellInfo
->EffectMiscValue
[i
])
5995 uint32 enchant_id
= m_spellInfo
->EffectMiscValue
[i
];
5996 int32 duration
= GetSpellDuration(m_spellInfo
); //Try duration index first ..
5998 duration
= m_currentBasePoints
[i
]+1; //Base points after ..
6000 duration
= 10; //10 seconds for enchants which don't have listed duration
6002 SpellItemEnchantmentEntry
const *pEnchant
= sSpellItemEnchantmentStore
.LookupEntry(enchant_id
);
6006 // Always go to temp enchantment slot
6007 EnchantmentSlot slot
= TEMP_ENCHANTMENT_SLOT
;
6009 // Enchantment will not be applied if a different one already exists
6010 if(item
->GetEnchantmentId(slot
) && item
->GetEnchantmentId(slot
) != enchant_id
)
6013 // Apply the temporary enchantment
6014 item
->SetEnchantment(slot
, enchant_id
, duration
*IN_MILISECONDS
, 0);
6015 item_owner
->ApplyEnchantment(item
, slot
, true);
6019 void Spell::EffectDisEnchant(uint32
/*i*/)
6021 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6024 Player
* p_caster
= (Player
*)m_caster
;
6025 if(!itemTarget
|| !itemTarget
->GetProto()->DisenchantID
)
6028 p_caster
->UpdateCraftSkill(m_spellInfo
->Id
);
6030 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(),LOOT_DISENCHANTING
);
6032 // item will be removed at disenchanting end
6035 void Spell::EffectInebriate(uint32
/*i*/)
6037 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6040 Player
*player
= (Player
*)unitTarget
;
6041 uint16 currentDrunk
= player
->GetDrunkValue();
6042 uint16 drunkMod
= damage
* 256;
6043 if (currentDrunk
+ drunkMod
> 0xFFFF)
6044 currentDrunk
= 0xFFFF;
6046 currentDrunk
+= drunkMod
;
6047 player
->SetDrunkValue(currentDrunk
, m_CastItem
? m_CastItem
->GetEntry() : 0);
6050 void Spell::EffectFeedPet(uint32 i
)
6052 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6055 Player
*_player
= (Player
*)m_caster
;
6057 Item
* foodItem
= m_targets
.getItemTarget();
6061 Pet
*pet
= _player
->GetPet();
6068 int32 benefit
= pet
->GetCurrentFoodBenefitLevel(foodItem
->GetProto()->ItemLevel
);
6073 _player
->DestroyItemCount(foodItem
,count
,true);
6074 // TODO: fix crash when a spell has two effects, both pointed at the same item target
6076 m_caster
->CastCustomSpell(pet
, m_spellInfo
->EffectTriggerSpell
[i
], &benefit
, NULL
, NULL
, true);
6079 void Spell::EffectDismissPet(uint32
/*i*/)
6081 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6084 Pet
* pet
= m_caster
->GetPet();
6086 // not let dismiss dead pet
6087 if(!pet
||!pet
->isAlive())
6090 ((Player
*)m_caster
)->RemovePet(pet
, PET_SAVE_NOT_IN_SLOT
);
6093 void Spell::EffectSummonObject(uint32 i
)
6095 uint32 go_id
= m_spellInfo
->EffectMiscValue
[i
];
6098 switch(m_spellInfo
->Effect
[i
])
6100 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1
: slot
= 0; break;
6101 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2
: slot
= 1; break;
6102 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3
: slot
= 2; break;
6103 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4
: slot
= 3; break;
6107 if(uint64 guid
= m_caster
->m_ObjectSlot
[slot
])
6109 if(GameObject
* obj
= m_caster
? m_caster
->GetMap()->GetGameObject(guid
) : NULL
)
6110 obj
->SetLootState(GO_JUST_DEACTIVATED
);
6111 m_caster
->m_ObjectSlot
[slot
] = 0;
6114 GameObject
* pGameObj
= new GameObject
;
6117 // If dest location if present
6118 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6120 x
= m_targets
.m_destX
;
6121 y
= m_targets
.m_destY
;
6122 z
= m_targets
.m_destZ
;
6124 // Summon in random point all other units if location present
6126 m_caster
->GetClosePoint(x
, y
, z
, DEFAULT_WORLD_OBJECT_SIZE
);
6128 Map
*map
= m_caster
->GetMap();
6129 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), go_id
, map
,
6130 m_caster
->GetPhaseMask(), x
, y
, z
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0, GO_STATE_READY
))
6136 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
,m_caster
->getLevel());
6137 int32 duration
= GetSpellDuration(m_spellInfo
);
6138 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6139 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6140 m_caster
->AddGameObject(pGameObj
);
6144 m_caster
->m_ObjectSlot
[slot
] = pGameObj
->GetGUID();
6147 void Spell::EffectResurrect(uint32
/*effIndex*/)
6151 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6154 if(unitTarget
->isAlive())
6156 if(!unitTarget
->IsInWorld())
6159 switch (m_spellInfo
->Id
)
6161 // Defibrillate (Goblin Jumper Cables) have 33% chance on success
6163 if (roll_chance_i(67))
6165 m_caster
->CastSpell(m_caster
, 8338, true, m_CastItem
);
6169 // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
6171 if (roll_chance_i(50))
6173 m_caster
->CastSpell(m_caster
, 23055, true, m_CastItem
);
6181 Player
* pTarget
= ((Player
*)unitTarget
);
6183 if(pTarget
->isRessurectRequested()) // already have one active request
6186 uint32 health
= pTarget
->GetMaxHealth() * damage
/ 100;
6187 uint32 mana
= pTarget
->GetMaxPower(POWER_MANA
) * damage
/ 100;
6189 pTarget
->setResurrectRequestData(m_caster
->GetGUID(), m_caster
->GetMapId(), m_caster
->GetPositionX(), m_caster
->GetPositionY(), m_caster
->GetPositionZ(), health
, mana
);
6190 SendResurrectRequest(pTarget
);
6193 void Spell::EffectAddExtraAttacks(uint32
/*i*/)
6195 if(!unitTarget
|| !unitTarget
->isAlive())
6198 if( unitTarget
->m_extraAttacks
)
6201 unitTarget
->m_extraAttacks
= damage
;
6204 void Spell::EffectParry(uint32
/*i*/)
6206 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6207 ((Player
*)unitTarget
)->SetCanParry(true);
6210 void Spell::EffectBlock(uint32
/*i*/)
6212 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6213 ((Player
*)unitTarget
)->SetCanBlock(true);
6216 void Spell::EffectLeapForward(uint32 i
)
6218 if(unitTarget
->isInFlight())
6221 if( m_spellInfo
->rangeIndex
== 1) //self range
6223 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[i
]));
6227 unitTarget
->GetClosePoint(fx
, fy
, fz
, unitTarget
->GetObjectSize(), dis
);
6229 unitTarget
->GetPosition(ox
, oy
, oz
);
6231 float fx2
, fy2
, fz2
; // getObjectHitPos overwrite last args in any result case
6232 if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget
->GetMapId(), ox
,oy
,oz
+0.5, fx
,fy
,oz
+0.5,fx2
,fy2
,fz2
, -0.5))
6237 unitTarget
->UpdateGroundPositionZ(fx
, fy
, fz
);
6240 unitTarget
->NearTeleportTo(fx
, fy
, fz
, unitTarget
->GetOrientation(), unitTarget
== m_caster
);
6244 void Spell::EffectLeapBack(uint32 i
)
6246 if(unitTarget
->isInFlight())
6249 m_caster
->KnockBackFrom(unitTarget
,float(m_spellInfo
->EffectMiscValue
[i
])/10,float(damage
)/10);
6252 void Spell::EffectReputation(uint32 i
)
6254 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6257 Player
*_player
= (Player
*)unitTarget
;
6259 int32 rep_change
= m_currentBasePoints
[i
]+1; // field store reputation change -1
6261 uint32 faction_id
= m_spellInfo
->EffectMiscValue
[i
];
6263 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
6268 _player
->GetReputationMgr().ModifyReputation(factionEntry
, rep_change
);
6271 void Spell::EffectQuestComplete(uint32 i
)
6273 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6276 Player
*_player
= (Player
*)m_caster
;
6278 uint32 quest_id
= m_spellInfo
->EffectMiscValue
[i
];
6279 _player
->AreaExploredOrEventHappens(quest_id
);
6282 void Spell::EffectSelfResurrect(uint32 i
)
6284 if(!unitTarget
|| unitTarget
->isAlive())
6286 if(unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6288 if(!unitTarget
->IsInWorld())
6297 health
= uint32(-damage
);
6298 mana
= m_spellInfo
->EffectMiscValue
[i
];
6303 health
= uint32(damage
/100.0f
*unitTarget
->GetMaxHealth());
6304 if(unitTarget
->GetMaxPower(POWER_MANA
) > 0)
6305 mana
= uint32(damage
/100.0f
*unitTarget
->GetMaxPower(POWER_MANA
));
6308 Player
*plr
= ((Player
*)unitTarget
);
6309 plr
->ResurrectPlayer(0.0f
);
6311 plr
->SetHealth( health
);
6312 plr
->SetPower(POWER_MANA
, mana
);
6313 plr
->SetPower(POWER_RAGE
, 0 );
6314 plr
->SetPower(POWER_ENERGY
, plr
->GetMaxPower(POWER_ENERGY
) );
6316 plr
->SpawnCorpseBones();
6319 void Spell::EffectSkinning(uint32
/*i*/)
6321 if(unitTarget
->GetTypeId() != TYPEID_UNIT
)
6323 if(!m_caster
|| m_caster
->GetTypeId() != TYPEID_PLAYER
)
6326 Creature
* creature
= (Creature
*) unitTarget
;
6327 int32 targetLevel
= creature
->getLevel();
6329 uint32 skill
= creature
->GetCreatureInfo()->GetRequiredLootSkill();
6331 ((Player
*)m_caster
)->SendLoot(creature
->GetGUID(),LOOT_SKINNING
);
6332 creature
->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6334 int32 reqValue
= targetLevel
< 10 ? 0 : targetLevel
< 20 ? (targetLevel
-10)*10 : targetLevel
*5;
6336 int32 skillValue
= ((Player
*)m_caster
)->GetPureSkillValue(skill
);
6338 // Double chances for elites
6339 ((Player
*)m_caster
)->UpdateGatherSkill(skill
, skillValue
, reqValue
, creature
->isElite() ? 2 : 1 );
6342 void Spell::EffectCharge(uint32
/*i*/)
6347 //TODO: research more ContactPoint/attack distance.
6348 //3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
6350 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
, 3.666666f
);
6352 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6353 ((Creature
*)unitTarget
)->StopMoving();
6355 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6356 m_caster
->SendMonsterMove(x
, y
, z
, 0, m_caster
->GetTypeId()==TYPEID_PLAYER
? MONSTER_MOVE_WALK
: ((Creature
*)m_caster
)->GetMonsterMoveFlags(), 1);
6358 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
6359 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
6361 // not all charge effects used in negative spells
6362 if (unitTarget
!= m_caster
&& !IsPositiveSpell(m_spellInfo
->Id
))
6363 m_caster
->Attack(unitTarget
,true);
6366 void Spell::EffectCharge2(uint32
/*i*/)
6369 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6371 x
= m_targets
.m_destX
;
6372 y
= m_targets
.m_destY
;
6373 z
= m_targets
.m_destZ
;
6375 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6376 ((Creature
*)unitTarget
)->StopMoving();
6378 else if (unitTarget
&& unitTarget
!= m_caster
)
6379 unitTarget
->GetContactPoint(m_caster
, x
, y
, z
, 3.666666f
);
6383 // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
6384 m_caster
->SendMonsterMove(x
, y
, z
, 0, m_caster
->GetTypeId()==TYPEID_PLAYER
? MONSTER_MOVE_WALK
: ((Creature
*)m_caster
)->GetMonsterMoveFlags(), 1);
6386 if (m_caster
->GetTypeId() != TYPEID_PLAYER
)
6387 m_caster
->GetMap()->CreatureRelocation((Creature
*)m_caster
,x
,y
,z
,m_caster
->GetOrientation());
6389 // not all charge effects used in negative spells
6390 if (unitTarget
&& unitTarget
!= m_caster
&& !IsPositiveSpell(m_spellInfo
->Id
))
6391 m_caster
->Attack(unitTarget
,true);
6394 void Spell::EffectSummonCritter(uint32 i
, uint32 forceFaction
)
6396 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6398 Player
* player
= (Player
*)m_caster
;
6400 uint32 pet_entry
= m_spellInfo
->EffectMiscValue
[i
];
6404 Pet
* old_critter
= player
->GetMiniPet();
6406 // for same pet just despawn
6407 if(old_critter
&& old_critter
->GetEntry() == pet_entry
)
6409 player
->RemoveMiniPet();
6413 // despawn old pet before summon new
6415 player
->RemoveMiniPet();
6418 Pet
* critter
= new Pet(MINI_PET
);
6420 Map
*map
= m_caster
->GetMap();
6421 uint32 pet_number
= sObjectMgr
.GeneratePetNumber();
6422 if(!critter
->Create(map
->GenerateLocalLowGuid(HIGHGUID_PET
), map
, m_caster
->GetPhaseMask(),
6423 pet_entry
, pet_number
))
6425 sLog
.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo
->Id
, pet_entry
);
6431 // If dest location if present
6432 if (m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6434 x
= m_targets
.m_destX
;
6435 y
= m_targets
.m_destY
;
6436 z
= m_targets
.m_destZ
;
6438 // Summon if dest location not present near caster
6440 m_caster
->GetClosePoint(x
, y
, z
, critter
->GetObjectSize());
6442 critter
->Relocate(x
, y
, z
, m_caster
->GetOrientation());
6444 if(!critter
->IsPositionValid())
6446 sLog
.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
6447 critter
->GetGUIDLow(), critter
->GetEntry(), critter
->GetPositionX(), critter
->GetPositionY());
6452 critter
->SetOwnerGUID(m_caster
->GetGUID());
6453 critter
->SetCreatorGUID(m_caster
->GetGUID());
6455 critter
->SetUInt32Value(UNIT_CREATED_BY_SPELL
, m_spellInfo
->Id
);
6456 critter
->setFaction(forceFaction
? forceFaction
: m_caster
->getFaction());
6457 critter
->AIM_Initialize();
6458 critter
->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
6459 //critter->InitLevelupSpellsForLevel(); // none?
6460 critter
->SelectLevel(critter
->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
6461 critter
->SetUInt32Value(UNIT_NPC_FLAGS
, critter
->GetCreatureInfo()->npcflag
);
6462 // some mini-pets have quests
6464 // set timer for unsummon
6465 int32 duration
= GetSpellDuration(m_spellInfo
);
6467 critter
->SetDuration(duration
);
6469 std::string name
= player
->GetName();
6470 name
.append(petTypeSuffix
[critter
->getPetType()]);
6471 critter
->SetName( name
);
6472 player
->SetMiniPet(critter
);
6474 map
->Add((Creature
*)critter
);
6477 void Spell::EffectKnockBack(uint32 i
)
6482 unitTarget
->KnockBackFrom(m_caster
,float(m_spellInfo
->EffectMiscValue
[i
])/10,float(damage
)/10);
6485 void Spell::EffectSendTaxi(uint32 i
)
6487 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6490 ((Player
*)unitTarget
)->ActivateTaxiPathTo(m_spellInfo
->EffectMiscValue
[i
],m_spellInfo
->Id
);
6493 void Spell::EffectPlayerPull(uint32 i
)
6498 unitTarget
->KnockBackFrom(m_caster
,float(damage
? damage
: unitTarget
->GetDistance2d(m_caster
)),float(m_spellInfo
->EffectMiscValue
[i
])/10);
6501 void Spell::EffectDispelMechanic(uint32 i
)
6506 uint32 mechanic
= m_spellInfo
->EffectMiscValue
[i
];
6508 Unit::AuraMap
& Auras
= unitTarget
->GetAuras();
6509 for(Unit::AuraMap::iterator iter
= Auras
.begin(), next
; iter
!= Auras
.end(); iter
= next
)
6513 SpellEntry
const *spell
= sSpellStore
.LookupEntry(iter
->second
->GetSpellProto()->Id
);
6514 if(spell
->Mechanic
== mechanic
|| spell
->EffectMechanic
[iter
->second
->GetEffIndex()] == mechanic
)
6516 unitTarget
->RemoveAurasDueToSpell(spell
->Id
);
6520 next
= Auras
.begin();
6526 void Spell::EffectSummonDeadPet(uint32
/*i*/)
6528 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6530 Player
*_player
= (Player
*)m_caster
;
6531 Pet
*pet
= _player
->GetPet();
6538 pet
->SetUInt32Value(UNIT_DYNAMIC_FLAGS
, 0);
6539 pet
->RemoveFlag (UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
6540 pet
->setDeathState( ALIVE
);
6541 pet
->clearUnitState(UNIT_STAT_ALL_STATE
);
6542 pet
->SetHealth( uint32(pet
->GetMaxHealth()*(float(damage
)/100)));
6544 pet
->AIM_Initialize();
6546 // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive
6547 pet
->SavePetToDB(PET_SAVE_AS_CURRENT
);
6550 void Spell::EffectDestroyAllTotems(uint32
/*i*/)
6553 for(int slot
= 0; slot
< MAX_TOTEM
; ++slot
)
6555 if(!m_caster
->m_TotemSlot
[slot
])
6558 Creature
* totem
= m_caster
->GetMap()->GetCreature(m_caster
->m_TotemSlot
[slot
]);
6559 if(totem
&& totem
->isTotem())
6561 uint32 spell_id
= totem
->GetUInt32Value(UNIT_CREATED_BY_SPELL
);
6562 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell_id
);
6565 uint32 manacost
= m_caster
->GetCreateMana() * spellInfo
->ManaCostPercentage
/ 100;
6566 mana
+= manacost
* damage
/ 100;
6568 ((Totem
*)totem
)->UnSummon();
6573 m_caster
->CastCustomSpell(m_caster
, 39104, &mana
, NULL
, NULL
, true);
6576 void Spell::EffectDurabilityDamage(uint32 i
)
6578 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6581 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6583 // FIXME: some spells effects have value -1/-2
6584 // Possibly its mean -1 all player equipped items and -2 all items
6587 ((Player
*)unitTarget
)->DurabilityPointsLossAll(damage
, (slot
< -1));
6591 // invalid slot value
6592 if(slot
>= INVENTORY_SLOT_BAG_END
)
6595 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
6596 ((Player
*)unitTarget
)->DurabilityPointsLoss(item
, damage
);
6599 void Spell::EffectDurabilityDamagePCT(uint32 i
)
6601 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6604 int32 slot
= m_spellInfo
->EffectMiscValue
[i
];
6606 // FIXME: some spells effects have value -1/-2
6607 // Possibly its mean -1 all player equipped items and -2 all items
6610 ((Player
*)unitTarget
)->DurabilityLossAll(double(damage
)/100.0f
, (slot
< -1));
6614 // invalid slot value
6615 if(slot
>= INVENTORY_SLOT_BAG_END
)
6621 if(Item
* item
= ((Player
*)unitTarget
)->GetItemByPos(INVENTORY_SLOT_BAG_0
, slot
))
6622 ((Player
*)unitTarget
)->DurabilityLoss(item
, double(damage
)/100.0f
);
6625 void Spell::EffectModifyThreatPercent(uint32
/*effIndex*/)
6630 unitTarget
->getThreatManager().modifyThreatPercent(m_caster
, damage
);
6633 void Spell::EffectTransmitted(uint32 effIndex
)
6635 uint32 name_id
= m_spellInfo
->EffectMiscValue
[effIndex
];
6637 GameObjectInfo
const* goinfo
= ObjectMgr::GetGameObjectInfo(name_id
);
6641 sLog
.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id
, m_spellInfo
->Id
);
6647 if(m_targets
.m_targetMask
& TARGET_FLAG_DEST_LOCATION
)
6649 fx
= m_targets
.m_destX
;
6650 fy
= m_targets
.m_destY
;
6651 fz
= m_targets
.m_destZ
;
6653 //FIXME: this can be better check for most objects but still hack
6654 else if(m_spellInfo
->EffectRadiusIndex
[effIndex
] && m_spellInfo
->speed
==0)
6656 float dis
= GetSpellRadius(sSpellRadiusStore
.LookupEntry(m_spellInfo
->EffectRadiusIndex
[effIndex
]));
6657 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6661 float min_dis
= GetSpellMinRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6662 float max_dis
= GetSpellMaxRange(sSpellRangeStore
.LookupEntry(m_spellInfo
->rangeIndex
));
6663 float dis
= rand_norm() * (max_dis
- min_dis
) + min_dis
;
6665 m_caster
->GetClosePoint(fx
, fy
, fz
, DEFAULT_WORLD_OBJECT_SIZE
, dis
);
6668 Map
*cMap
= m_caster
->GetMap();
6670 if(goinfo
->type
==GAMEOBJECT_TYPE_FISHINGNODE
)
6672 if ( !cMap
->IsInWater(fx
, fy
, fz
-0.5f
)) // Hack to prevent fishing bobber from failing to land on fishing hole
6673 { // but this is not proper, we really need to ignore not materialized objects
6674 SendCastResult(SPELL_FAILED_NOT_HERE
);
6675 SendChannelUpdate(0);
6679 // replace by water level in this case
6680 fz
= cMap
->GetWaterLevel(fx
, fy
);
6682 // if gameobject is summoning object, it should be spawned right on caster's position
6683 else if(goinfo
->type
==GAMEOBJECT_TYPE_SUMMONING_RITUAL
)
6685 m_caster
->GetPosition(fx
, fy
, fz
);
6688 GameObject
* pGameObj
= new GameObject
;
6690 if(!pGameObj
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), name_id
, cMap
,
6691 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
6697 int32 duration
= GetSpellDuration(m_spellInfo
);
6699 switch(goinfo
->type
)
6701 case GAMEOBJECT_TYPE_FISHINGNODE
:
6703 m_caster
->SetChannelObjectGUID(pGameObj
->GetGUID());
6704 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6706 // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6707 // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6711 case 0: lastSec
= 3; break;
6712 case 1: lastSec
= 7; break;
6713 case 2: lastSec
= 13; break;
6714 case 3: lastSec
= 17; break;
6717 duration
= duration
- lastSec
*IN_MILISECONDS
+ FISHING_BOBBER_READY_TIME
*IN_MILISECONDS
;
6720 case GAMEOBJECT_TYPE_SUMMONING_RITUAL
:
6722 if(m_caster
->GetTypeId() == TYPEID_PLAYER
)
6724 pGameObj
->AddUniqueUse((Player
*)m_caster
);
6725 m_caster
->AddGameObject(pGameObj
); // will removed at spell cancel
6729 case GAMEOBJECT_TYPE_FISHINGHOLE
:
6730 case GAMEOBJECT_TYPE_CHEST
:
6735 pGameObj
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6737 pGameObj
->SetOwnerGUID(m_caster
->GetGUID());
6739 pGameObj
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel());
6740 pGameObj
->SetSpellId(m_spellInfo
->Id
);
6742 DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted");
6743 //m_caster->AddGameObject(pGameObj);
6744 //m_ObjToDel.push_back(pGameObj);
6746 cMap
->Add(pGameObj
);
6748 if(uint32 linkedEntry
= pGameObj
->GetGOInfo()->GetLinkedGameObjectEntry())
6750 GameObject
* linkedGO
= new GameObject
;
6751 if(linkedGO
->Create(sObjectMgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
), linkedEntry
, cMap
,
6752 m_caster
->GetPhaseMask(), fx
, fy
, fz
, m_caster
->GetOrientation(), 0.0f
, 0.0f
, 0.0f
, 0.0f
, 100, GO_STATE_READY
))
6754 linkedGO
->SetRespawnTime(duration
> 0 ? duration
/IN_MILISECONDS
: 0);
6755 linkedGO
->SetUInt32Value(GAMEOBJECT_LEVEL
, m_caster
->getLevel());
6756 linkedGO
->SetSpellId(m_spellInfo
->Id
);
6757 linkedGO
->SetOwnerGUID(m_caster
->GetGUID());
6759 linkedGO
->GetMap()->Add(linkedGO
);
6770 void Spell::EffectProspecting(uint32
/*i*/)
6772 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6775 Player
* p_caster
= (Player
*)m_caster
;
6776 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_MINING_SUPP
))
6779 if(itemTarget
->GetCount() < 5)
6782 if( sWorld
.getConfig(CONFIG_SKILL_PROSPECTING
))
6784 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_JEWELCRAFTING
);
6785 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6786 p_caster
->UpdateGatherSkill(SKILL_JEWELCRAFTING
, SkillValue
, reqSkillValue
);
6789 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_PROSPECTING
);
6792 void Spell::EffectMilling(uint32
/*i*/)
6794 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6797 Player
* p_caster
= (Player
*)m_caster
;
6798 if(!itemTarget
|| !(itemTarget
->GetProto()->BagFamily
& BAG_FAMILY_MASK_HERBS
))
6801 if(itemTarget
->GetCount() < 5)
6804 if( sWorld
.getConfig(CONFIG_SKILL_MILLING
))
6806 uint32 SkillValue
= p_caster
->GetPureSkillValue(SKILL_INSCRIPTION
);
6807 uint32 reqSkillValue
= itemTarget
->GetProto()->RequiredSkillRank
;
6808 p_caster
->UpdateGatherSkill(SKILL_INSCRIPTION
, SkillValue
, reqSkillValue
);
6811 ((Player
*)m_caster
)->SendLoot(itemTarget
->GetGUID(), LOOT_MILLING
);
6814 void Spell::EffectSkill(uint32
/*i*/)
6816 sLog
.outDebug("WORLD: SkillEFFECT");
6819 void Spell::EffectSpiritHeal(uint32
/*i*/)
6821 // TODO player can't see the heal-animation - he should respawn some ticks later
6822 if (!unitTarget
|| unitTarget
->isAlive())
6824 if (unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6826 if (!unitTarget
->IsInWorld())
6828 if (m_spellInfo
->Id
== 22012 && !unitTarget
->HasAura(2584))
6831 ((Player
*)unitTarget
)->ResurrectPlayer(1.0f
);
6832 ((Player
*)unitTarget
)->SpawnCorpseBones();
6835 // remove insignia spell effect
6836 void Spell::EffectSkinPlayerCorpse(uint32
/*i*/)
6838 sLog
.outDebug("Effect: SkinPlayerCorpse");
6839 if ( (m_caster
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->GetTypeId() != TYPEID_PLAYER
) || (unitTarget
->isAlive()) )
6842 ((Player
*)unitTarget
)->RemovedInsignia( (Player
*)m_caster
);
6845 void Spell::EffectStealBeneficialBuff(uint32 i
)
6847 sLog
.outDebug("Effect: StealBeneficialBuff");
6849 if(!unitTarget
|| unitTarget
==m_caster
) // can't steal from self
6852 std::vector
<Aura
*> steal_list
;
6853 // Create dispel mask by dispel type
6854 uint32 dispelMask
= GetDispellMask( DispelType(m_spellInfo
->EffectMiscValue
[i
]) );
6855 Unit::AuraMap
const& auras
= unitTarget
->GetAuras();
6856 for(Unit::AuraMap::const_iterator itr
= auras
.begin(); itr
!= auras
.end(); ++itr
)
6858 Aura
*aur
= (*itr
).second
;
6859 if (aur
&& (1<<aur
->GetSpellProto()->Dispel
) & dispelMask
)
6861 // Need check for passive? this
6862 if (aur
->IsPositive() && !aur
->IsPassive() && !(aur
->GetSpellProto()->AttributesEx4
& SPELL_ATTR_EX4_NOT_STEALABLE
))
6863 steal_list
.push_back(aur
);
6866 // Ok if exist some buffs for dispel try dispel it
6867 if (!steal_list
.empty())
6869 std::list
< std::pair
<uint32
,uint64
> > success_list
;
6870 int32 list_size
= steal_list
.size();
6871 // Dispell N = damage buffs (or while exist buffs for dispel)
6872 for (int32 count
=0; count
< damage
&& list_size
> 0; ++count
)
6874 // Random select buff for dispel
6875 Aura
*aur
= steal_list
[urand(0, list_size
-1)];
6876 // Not use chance for steal
6877 // TODO possible need do it
6878 success_list
.push_back( std::pair
<uint32
,uint64
>(aur
->GetId(),aur
->GetCasterGUID()));
6880 // Remove buff from list for prevent doubles
6881 for (std::vector
<Aura
*>::iterator j
= steal_list
.begin(); j
!= steal_list
.end(); )
6884 if (stealed
->GetId() == aur
->GetId() && stealed
->GetCasterGUID() == aur
->GetCasterGUID())
6886 j
= steal_list
.erase(j
);
6893 // Really try steal and send log
6894 if (!success_list
.empty())
6896 int32 count
= success_list
.size();
6897 WorldPacket
data(SMSG_SPELLSTEALLOG
, 8+8+4+1+4+count
*5);
6898 data
.append(unitTarget
->GetPackGUID()); // Victim GUID
6899 data
.append(m_caster
->GetPackGUID()); // Caster GUID
6900 data
<< uint32(m_spellInfo
->Id
); // Dispell spell id
6901 data
<< uint8(0); // not used
6902 data
<< uint32(count
); // count
6903 for (std::list
<std::pair
<uint32
,uint64
> >::iterator j
= success_list
.begin(); j
!= success_list
.end(); ++j
)
6905 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(j
->first
);
6906 data
<< uint32(spellInfo
->Id
); // Spell Id
6907 data
<< uint8(0); // 0 - steals !=0 transfers
6908 unitTarget
->RemoveAurasDueToSpellBySteal(spellInfo
->Id
, j
->second
, m_caster
);
6910 m_caster
->SendMessageToSet(&data
, true);
6915 void Spell::EffectKillCreditPersonal(uint32 i
)
6917 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6920 ((Player
*)unitTarget
)->KilledMonsterCredit(m_spellInfo
->EffectMiscValue
[i
], 0);
6923 void Spell::EffectKillCredit(uint32 i
)
6925 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6928 ((Player
*)unitTarget
)->RewardPlayerAndGroupAtEvent(m_spellInfo
->EffectMiscValue
[i
], unitTarget
);
6931 void Spell::EffectQuestFail(uint32 i
)
6933 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6936 ((Player
*)unitTarget
)->FailQuest(m_spellInfo
->EffectMiscValue
[i
]);
6939 void Spell::EffectActivateRune(uint32 eff_idx
)
6941 if(m_caster
->GetTypeId() != TYPEID_PLAYER
)
6944 Player
*plr
= (Player
*)m_caster
;
6946 if(plr
->getClass() != CLASS_DEATH_KNIGHT
)
6949 for(uint32 j
= 0; j
< MAX_RUNES
; ++j
)
6951 if(plr
->GetRuneCooldown(j
) && plr
->GetCurrentRune(j
) == RuneType(m_spellInfo
->EffectMiscValue
[eff_idx
]))
6953 plr
->SetRuneCooldown(j
, 0);
6958 void Spell::EffectTitanGrip(uint32
/*eff_idx*/)
6960 if (unitTarget
&& unitTarget
->GetTypeId() == TYPEID_PLAYER
)
6961 ((Player
*)unitTarget
)->SetCanTitanGrip(true);
6964 void Spell::EffectRenamePet(uint32
/*eff_idx*/)
6966 if (!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_UNIT
||
6967 !((Creature
*)unitTarget
)->isPet() || ((Pet
*)unitTarget
)->getPetType() != HUNTER_PET
)
6970 unitTarget
->SetByteValue(UNIT_FIELD_BYTES_2
, 2, UNIT_RENAME_ALLOWED
);
6973 void Spell::EffectPlayMusic(uint32 i
)
6975 if(!unitTarget
|| unitTarget
->GetTypeId() != TYPEID_PLAYER
)
6978 uint32 soundid
= m_spellInfo
->EffectMiscValue
[i
];
6980 if (!sSoundEntriesStore
.LookupEntry(soundid
))
6982 sLog
.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid
,m_spellInfo
->Id
);
6986 WorldPacket
data(SMSG_PLAY_MUSIC
, 4);
6987 data
<< uint32(soundid
);
6988 ((Player
*)unitTarget
)->GetSession()->SendPacket(&data
);