View difference between Paste ID: Fg1gTWLX and 0nq1x2wY
SHOW: | | - or go back to the newest paste.
1
/
2
 * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
3
 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4
 *
5
 * This program is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License as published by the
7
 * Free Software Foundation; either version 2 of the License, or (at your
8
 * option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
 * more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program. If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
#include "Common.h"
20
#include "DatabaseEnv.h"
21
#include "WorldPacket.h"
22
#include "Opcodes.h"
23
#include "Log.h"
24
#include "UpdateMask.h"
25
#include "World.h"
26
#include "ObjectMgr.h"
27
#include "SpellMgr.h"
28
#include "Player.h"
29
#include "SkillExtraItems.h"
30
#include "Unit.h"
31
#include "Spell.h"
32
#include "DynamicObject.h"
33
#include "SpellAuras.h"
34
#include "SpellAuraEffects.h"
35
#include "Group.h"
36
#include "UpdateData.h"
37
#include "MapManager.h"
38
#include "ObjectAccessor.h"
39
#include "SharedDefines.h"
40
#include "Pet.h"
41
#include "GameObject.h"
42
#include "GossipDef.h"
43
#include "Creature.h"
44
#include "Totem.h"
45
#include "CreatureAI.h"
46
#include "BattlegroundMgr.h"
47
#include "Battleground.h"
48
#include "BattlegroundEY.h"
49
#include "BattlegroundWS.h"
50
#include "OutdoorPvPMgr.h"
51
#include "Language.h"
52
#include "SocialMgr.h"
53
#include "Util.h"
54
#include "VMapFactory.h"
55
#include "TemporarySummon.h"
56
#include "CellImpl.h"
57
#include "GridNotifiers.h"
58
#include "GridNotifiersImpl.h"
59
#include "SkillDiscovery.h"
60
#include "Formulas.h"
61
#include "Vehicle.h"
62
#include "ScriptMgr.h"
63
#include "GameObjectAI.h"
64
#include "AccountMgr.h"
65
#include "InstanceScript.h"
66
#include "ReputationMgr.h"
67
68
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
69
{
70
    &Spell::EffectNULL,                                     //  0
71
    &Spell::EffectInstaKill,                                //  1 SPELL_EFFECT_INSTAKILL
72
    &Spell::EffectSchoolDMG,                                //  2 SPELL_EFFECT_SCHOOL_DAMAGE
73
    &Spell::EffectDummy,                                    //  3 SPELL_EFFECT_DUMMY
74
    &Spell::EffectUnused,                                   //  4 SPELL_EFFECT_PORTAL_TELEPORT          unused
75
    &Spell::EffectTeleportUnits,                            //  5 SPELL_EFFECT_TELEPORT_UNITS
76
    &Spell::EffectApplyAura,                                //  6 SPELL_EFFECT_APPLY_AURA
77
    &Spell::EffectEnvironmentalDMG,                         //  7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
78
    &Spell::EffectPowerDrain,                               //  8 SPELL_EFFECT_POWER_DRAIN
79
    &Spell::EffectHealthLeech,                              //  9 SPELL_EFFECT_HEALTH_LEECH
80
    &Spell::EffectHeal,                                     // 10 SPELL_EFFECT_HEAL
81
    &Spell::EffectBind,                                     // 11 SPELL_EFFECT_BIND
82
    &Spell::EffectNULL,                                     // 12 SPELL_EFFECT_PORTAL
83
    &Spell::EffectUnused,                                   // 13 SPELL_EFFECT_RITUAL_BASE              unused
84
    &Spell::EffectUnused,                                   // 14 SPELL_EFFECT_RITUAL_SPECIALIZE        unused
85
    &Spell::EffectUnused,                                   // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL   unused
86
    &Spell::EffectQuestComplete,                            // 16 SPELL_EFFECT_QUEST_COMPLETE
87
    &Spell::EffectWeaponDmg,                                // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
88
    &Spell::EffectResurrect,                                // 18 SPELL_EFFECT_RESURRECT
89
    &Spell::EffectAddExtraAttacks,                          // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
90
    &Spell::EffectUnused,                                   // 20 SPELL_EFFECT_DODGE                    one spell: Dodge
91
    &Spell::EffectUnused,                                   // 21 SPELL_EFFECT_EVADE                    one spell: Evade (DND)
92
    &Spell::EffectParry,                                    // 22 SPELL_EFFECT_PARRY
93
    &Spell::EffectBlock,                                    // 23 SPELL_EFFECT_BLOCK                    one spell: Block
94
    &Spell::EffectCreateItem,                               // 24 SPELL_EFFECT_CREATE_ITEM
95
    &Spell::EffectUnused,                                   // 25 SPELL_EFFECT_WEAPON
96
    &Spell::EffectUnused,                                   // 26 SPELL_EFFECT_DEFENSE                  one spell: Defense
97
    &Spell::EffectPersistentAA,                             // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
98
    &Spell::EffectSummonType,                               // 28 SPELL_EFFECT_SUMMON
99
    &Spell::EffectLeap,                                     // 29 SPELL_EFFECT_LEAP
100
    &Spell::EffectEnergize,                                 // 30 SPELL_EFFECT_ENERGIZE
101
    &Spell::EffectWeaponDmg,                                // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
102
    &Spell::EffectTriggerMissileSpell,                      // 32 SPELL_EFFECT_TRIGGER_MISSILE
103
    &Spell::EffectOpenLock,                                 // 33 SPELL_EFFECT_OPEN_LOCK
104
    &Spell::EffectSummonChangeItem,                         // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
105
    &Spell::EffectApplyAreaAura,                            // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
106
    &Spell::EffectLearnSpell,                               // 36 SPELL_EFFECT_LEARN_SPELL
107
    &Spell::EffectUnused,                                   // 37 SPELL_EFFECT_SPELL_DEFENSE            one spell: SPELLDEFENSE (DND)
108
    &Spell::EffectDispel,                                   // 38 SPELL_EFFECT_DISPEL
109
    &Spell::EffectUnused,                                   // 39 SPELL_EFFECT_LANGUAGE
110
    &Spell::EffectDualWield,                                // 40 SPELL_EFFECT_DUAL_WIELD
111
    &Spell::EffectJump,                                     // 41 SPELL_EFFECT_JUMP
112
    &Spell::EffectJumpDest,                                 // 42 SPELL_EFFECT_JUMP_DEST
113
    &Spell::EffectTeleUnitsFaceCaster,                      // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
114
    &Spell::EffectLearnSkill,                               // 44 SPELL_EFFECT_SKILL_STEP
115
    &Spell::EffectAddHonor,                                 // 45 SPELL_EFFECT_ADD_HONOR                honor/pvp related
116
    &Spell::EffectUnused,                                   // 46 SPELL_EFFECT_SPAWN clientside, unit appears as if it was just spawned
117
    &Spell::EffectTradeSkill,                               // 47 SPELL_EFFECT_TRADE_SKILL
118
    &Spell::EffectUnused,                                   // 48 SPELL_EFFECT_STEALTH                  one spell: Base Stealth
119
    &Spell::EffectUnused,                                   // 49 SPELL_EFFECT_DETECT                   one spell: Detect
120
    &Spell::EffectTransmitted,                              // 50 SPELL_EFFECT_TRANS_DOOR
121
    &Spell::EffectUnused,                                   // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT       unused
122
    &Spell::EffectUnused,                                   // 52 SPELL_EFFECT_GUARANTEE_HIT            one spell: zzOLDCritical Shot
123
    &Spell::EffectEnchantItemPerm,                          // 53 SPELL_EFFECT_ENCHANT_ITEM
124
    &Spell::EffectEnchantItemTmp,                           // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
125
    &Spell::EffectTameCreature,                             // 55 SPELL_EFFECT_TAMECREATURE
126
    &Spell::EffectSummonPet,                                // 56 SPELL_EFFECT_SUMMON_PET
127
    &Spell::EffectLearnPetSpell,                            // 57 SPELL_EFFECT_LEARN_PET_SPELL
128
    &Spell::EffectWeaponDmg,                                // 58 SPELL_EFFECT_WEAPON_DAMAGE
129
    &Spell::EffectCreateRandomItem,                         // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM       create item base at spell specific loot
130
    &Spell::EffectProficiency,                              // 60 SPELL_EFFECT_PROFICIENCY
131
    &Spell::EffectSendEvent,                                // 61 SPELL_EFFECT_SEND_EVENT
132
    &Spell::EffectPowerBurn,                                // 62 SPELL_EFFECT_POWER_BURN
133
    &Spell::EffectThreat,                                   // 63 SPELL_EFFECT_THREAT
134
    &Spell::EffectTriggerSpell,                             // 64 SPELL_EFFECT_TRIGGER_SPELL
135
    &Spell::EffectApplyAreaAura,                            // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
136
    &Spell::EffectRechargeManaGem,                          // 66 SPELL_EFFECT_CREATE_MANA_GEM          (possibly recharge it, misc - is item ID)
137
    &Spell::EffectHealMaxHealth,                            // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
138
    &Spell::EffectInterruptCast,                            // 68 SPELL_EFFECT_INTERRUPT_CAST
139
    &Spell::EffectDistract,                                 // 69 SPELL_EFFECT_DISTRACT
140
    &Spell::EffectPull,                                     // 70 SPELL_EFFECT_PULL                     one spell: Distract Move
141
    &Spell::EffectPickPocket,                               // 71 SPELL_EFFECT_PICKPOCKET
142
    &Spell::EffectAddFarsight,                              // 72 SPELL_EFFECT_ADD_FARSIGHT
143
    &Spell::EffectUntrainTalents,                           // 73 SPELL_EFFECT_UNTRAIN_TALENTS
144
    &Spell::EffectApplyGlyph,                               // 74 SPELL_EFFECT_APPLY_GLYPH
145
    &Spell::EffectHealMechanical,                           // 75 SPELL_EFFECT_HEAL_MECHANICAL          one spell: Mechanical Patch Kit
146
    &Spell::EffectSummonObjectWild,                         // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
147
    &Spell::EffectScriptEffect,                             // 77 SPELL_EFFECT_SCRIPT_EFFECT
148
    &Spell::EffectUnused,                                   // 78 SPELL_EFFECT_ATTACK
149
    &Spell::EffectSanctuary,                                // 79 SPELL_EFFECT_SANCTUARY
150
    &Spell::EffectAddComboPoints,                           // 80 SPELL_EFFECT_ADD_COMBO_POINTS
151
    &Spell::EffectUnused,                                   // 81 SPELL_EFFECT_CREATE_HOUSE             one spell: Create House (TEST)
152
    &Spell::EffectNULL,                                     // 82 SPELL_EFFECT_BIND_SIGHT
153
    &Spell::EffectDuel,                                     // 83 SPELL_EFFECT_DUEL
154
    &Spell::EffectStuck,                                    // 84 SPELL_EFFECT_STUCK
155
    &Spell::EffectSummonPlayer,                             // 85 SPELL_EFFECT_SUMMON_PLAYER
156
    &Spell::EffectActivateObject,                           // 86 SPELL_EFFECT_ACTIVATE_OBJECT
157
    &Spell::EffectGameObjectDamage,                         // 87 SPELL_EFFECT_GAMEOBJECT_DAMAGE
158
    &Spell::EffectGameObjectRepair,                         // 88 SPELL_EFFECT_GAMEOBJECT_REPAIR
159
    &Spell::EffectGameObjectSetDestructionState,            // 89 SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE
160
    &Spell::EffectKillCreditPersonal,                       // 90 SPELL_EFFECT_KILL_CREDIT              Kill credit but only for single person
161
    &Spell::EffectUnused,                                   // 91 SPELL_EFFECT_THREAT_ALL               one spell: zzOLDBrainwash
162
    &Spell::EffectEnchantHeldItem,                          // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
163
    &Spell::EffectForceDeselect,                            // 93 SPELL_EFFECT_FORCE_DESELECT
164
    &Spell::EffectSelfResurrect,                            // 94 SPELL_EFFECT_SELF_RESURRECT
165
    &Spell::EffectSkinning,                                 // 95 SPELL_EFFECT_SKINNING
166
    &Spell::EffectCharge,                                   // 96 SPELL_EFFECT_CHARGE
167
    &Spell::EffectCastButtons,                              // 97 SPELL_EFFECT_CAST_BUTTON (totem bar since 3.2.2a)
168
    &Spell::EffectKnockBack,                                // 98 SPELL_EFFECT_KNOCK_BACK
169
    &Spell::EffectDisEnchant,                               // 99 SPELL_EFFECT_DISENCHANT
170
    &Spell::EffectInebriate,                                //100 SPELL_EFFECT_INEBRIATE
171
    &Spell::EffectFeedPet,                                  //101 SPELL_EFFECT_FEED_PET
172
    &Spell::EffectDismissPet,                               //102 SPELL_EFFECT_DISMISS_PET
173
    &Spell::EffectReputation,                               //103 SPELL_EFFECT_REPUTATION
174
    &Spell::EffectSummonObject,                             //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
175
    &Spell::EffectSummonObject,                             //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
176
    &Spell::EffectSummonObject,                             //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
177
    &Spell::EffectSummonObject,                             //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
178
    &Spell::EffectDispelMechanic,                           //108 SPELL_EFFECT_DISPEL_MECHANIC
179
    &Spell::EffectSummonDeadPet,                            //109 SPELL_EFFECT_SUMMON_DEAD_PET
180
    &Spell::EffectDestroyAllTotems,                         //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
181
    &Spell::EffectDurabilityDamage,                         //111 SPELL_EFFECT_DURABILITY_DAMAGE
182
    &Spell::EffectUnused,                                   //112 SPELL_EFFECT_112
183
    &Spell::EffectResurrectNew,                             //113 SPELL_EFFECT_RESURRECT_NEW
184
    &Spell::EffectTaunt,                                    //114 SPELL_EFFECT_ATTACK_ME
185
    &Spell::EffectDurabilityDamagePCT,                      //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
186
    &Spell::EffectSkinPlayerCorpse,                         //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE       one spell: Remove Insignia, bg usage, required special corpse flags...
187
    &Spell::EffectSpiritHeal,                               //117 SPELL_EFFECT_SPIRIT_HEAL              one spell: Spirit Heal
188
    &Spell::EffectSkill,                                    //118 SPELL_EFFECT_SKILL                    professions and more
189
    &Spell::EffectApplyAreaAura,                            //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
190
    &Spell::EffectUnused,                                   //120 SPELL_EFFECT_TELEPORT_GRAVEYARD       one spell: Graveyard Teleport Test
191
    &Spell::EffectWeaponDmg,                                //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
192
    &Spell::EffectUnused,                                   //122 SPELL_EFFECT_122                      unused
193
    &Spell::EffectSendTaxi,                                 //123 SPELL_EFFECT_SEND_TAXI                taxi/flight related (misc value is taxi path id)
194
    &Spell::EffectPullTowards,                              //124 SPELL_EFFECT_PULL_TOWARDS
195
    &Spell::EffectModifyThreatPercent,                      //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
196
    &Spell::EffectStealBeneficialBuff,                      //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF    spell steal effect?
197
    &Spell::EffectProspecting,                              //127 SPELL_EFFECT_PROSPECTING              Prospecting spell
198
    &Spell::EffectApplyAreaAura,                            //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
199
    &Spell::EffectApplyAreaAura,                            //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
200
    &Spell::EffectRedirectThreat,                           //130 SPELL_EFFECT_REDIRECT_THREAT
201
    &Spell::EffectPlayerNotification,                       //131 SPELL_EFFECT_PLAYER_NOTIFICATION      sound id in misc value (SoundEntries.dbc)
202
    &Spell::EffectPlayMusic,                                //132 SPELL_EFFECT_PLAY_MUSIC               sound id in misc value (SoundEntries.dbc)
203
    &Spell::EffectUnlearnSpecialization,                    //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION   unlearn profession specialization
204
    &Spell::EffectKillCredit,                               //134 SPELL_EFFECT_KILL_CREDIT              misc value is creature entry
205
    &Spell::EffectNULL,                                     //135 SPELL_EFFECT_CALL_PET
206
    &Spell::EffectHealPct,                                  //136 SPELL_EFFECT_HEAL_PCT
207
    &Spell::EffectEnergizePct,                              //137 SPELL_EFFECT_ENERGIZE_PCT
208
    &Spell::EffectLeapBack,                                 //138 SPELL_EFFECT_LEAP_BACK                Leap back
209
    &Spell::EffectQuestClear,                               //139 SPELL_EFFECT_CLEAR_QUEST              Reset quest status (miscValue - quest ID)
210
    &Spell::EffectForceCast,                                //140 SPELL_EFFECT_FORCE_CAST
211
    &Spell::EffectForceCast,                                //141 SPELL_EFFECT_FORCE_CAST_WITH_VALUE
212
    &Spell::EffectTriggerSpell,                             //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
213
    &Spell::EffectApplyAreaAura,                            //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
214
    &Spell::EffectKnockBack,                                //144 SPELL_EFFECT_KNOCK_BACK_DEST
215
    &Spell::EffectPullTowards,                              //145 SPELL_EFFECT_PULL_TOWARDS_DEST                      Black Hole Effect
216
    &Spell::EffectActivateRune,                             //146 SPELL_EFFECT_ACTIVATE_RUNE
217
    &Spell::EffectQuestFail,                                //147 SPELL_EFFECT_QUEST_FAIL               quest fail
218
    &Spell::EffectTriggerMissileSpell,                      //148 SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE
219
    &Spell::EffectChargeDest,                               //149 SPELL_EFFECT_CHARGE_DEST
220
    &Spell::EffectQuestStart,                               //150 SPELL_EFFECT_QUEST_START
221
    &Spell::EffectTriggerRitualOfSummoning,                 //151 SPELL_EFFECT_TRIGGER_SPELL_2
222
    &Spell::EffectSummonRaFFriend,                          //152 SPELL_EFFECT_SUMMON_RAF_FRIEND        summon Refer-a-Friend
223
    &Spell::EffectCreateTamedPet,                           //153 SPELL_EFFECT_CREATE_TAMED_PET         misc value is creature entry
224
    &Spell::EffectDiscoverTaxi,                             //154 SPELL_EFFECT_DISCOVER_TAXI
225
    &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.
226
    &Spell::EffectEnchantItemPrismatic,                     //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
227
    &Spell::EffectCreateItem2,                              //157 SPELL_EFFECT_CREATE_ITEM_2            create item or create item template and replace by some randon spell loot item
228
    &Spell::EffectMilling,                                  //158 SPELL_EFFECT_MILLING                  milling
229
    &Spell::EffectRenamePet,                                //159 SPELL_EFFECT_ALLOW_RENAME_PET         allow rename pet once again
230
    &Spell::EffectNULL,                                     //160 SPELL_EFFECT_160                      1 spell - 45534
231
    &Spell::EffectSpecCount,                                //161 SPELL_EFFECT_TALENT_SPEC_COUNT        second talent spec (learn/revert)
232
    &Spell::EffectActivateSpec,                             //162 SPELL_EFFECT_TALENT_SPEC_SELECT       activate primary/secondary spec
233
    &Spell::EffectNULL,                                     //163 unused
234
    &Spell::EffectRemoveAura,                               //164 SPELL_EFFECT_REMOVE_AURA
235
};
236
237
void Spell::EffectNULL(SpellEffIndex /*effIndex*/)
238
{
239
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: Spell Effect DUMMY");
240
}
241
242
void Spell::EffectUnused(SpellEffIndex /*effIndex*/)
243
{
244
    // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN TRINITY
245
}
246
247
void Spell::EffectResurrectNew(SpellEffIndex effIndex)
248
{
249
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
250
        return;
251
252
    if (!unitTarget || unitTarget->isAlive())
253
        return;
254
255
    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
256
        return;
257
258
    if (!unitTarget->IsInWorld())
259
        return;
260
261
    Player* target = unitTarget->ToPlayer();
262
263
    if (target->isRessurectRequested())       // already have one active request
264
        return;
265
266
    uint32 health = damage;
267
    uint32 mana = m_spellInfo->Effects[effIndex].MiscValue;
268
    ExecuteLogEffectResurrect(effIndex, target);
269
    target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
270
    SendResurrectRequest(target);
271
}
272
273
void Spell::EffectInstaKill(SpellEffIndex /*effIndex*/)
274
{
275
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
276
        return;
277
278
    if (!unitTarget || !unitTarget->isAlive())
279
        return;
280
281
    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
282
        if (unitTarget->ToPlayer()->GetCommandStatus(CHEAT_GOD))
283
            return;
284
285
    if (m_caster == unitTarget)                              // prevent interrupt message
286
        finish();
287
288
    WorldPacket data(SMSG_SPELLINSTAKILLLOG, 8+8+4);
289
    data << uint64(m_caster->GetGUID());
290
    data << uint64(unitTarget->GetGUID());
291
    data << uint32(m_spellInfo->Id);
292
    m_caster->SendMessageToSet(&data, true);
293
294
    m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
295
}
296
297
void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
298
{
299
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
300
        return;
301
302
    if (!unitTarget || !unitTarget->isAlive())
303
        return;
304
305
    uint32 absorb = 0;
306
    uint32 resist = 0;
307
308
    m_caster->CalcAbsorbResist(unitTarget, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo);
309
310
    m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
311
    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
312
        unitTarget->ToPlayer()->EnvironmentalDamage(DAMAGE_FIRE, damage);
313
}
314
315
void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
316
{
317
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
318
        return;
319
320
    if (unitTarget && unitTarget->isAlive())
321
    {
322
        bool apply_direct_bonus = true;
323
        switch (m_spellInfo->SpellFamilyName)
324
        {
325
            case SPELLFAMILY_GENERIC:
326
            {
327
                // Meteor like spells (divided damage to targets)
328
                if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_SHARE_DAMAGE)
329
                {
330
                    uint32 count = 0;
331
                    for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
332
                        if (ihit->effectMask & (1<<effIndex))
333
                            ++count;
334
335
                    damage /= count;                    // divide to all targets
336
                }
337
338
                switch (m_spellInfo->Id)                     // better way to check unknown
339
                {
340
                    // Consumption
341
                    case 28865:
342
                        damage = (((InstanceMap*)m_caster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 2750 : 4250);
343
                        break;
344
                    // percent from health with min
345
                    case 25599:                             // Thundercrash
346
                    {
347
                        damage = unitTarget->GetHealth() / 2;
348
                        if (damage < 200)
349
                            damage = 200;
350
                        break;
351
                    }
352
                    // arcane charge. must only affect demons (also undead?)
353
                    case 45072:
354
                    {
355
                        if (unitTarget->GetCreatureType() != CREATURE_TYPE_DEMON
356
                            && unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD)
357
                            return;
358
                        break;
359
                    }
360
                    // Gargoyle Strike
361
                    case 51963:
362
                    {
363
                        // about +4 base spell dmg per level
364
                        damage = (m_caster->getLevel() - 60) * 4 + 60;
365
                        break;
366
                    }
367
                }
368
                break;
369
            }
370
            case SPELLFAMILY_WARRIOR:
371
            {
372
                // Shield Slam
373
                if (m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->Category == 1209)
374
                {
375
                    uint8 level = m_caster->getLevel();
376
                    uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 24.5f), uint32(float(level) * 34.5f));
377
                    damage += int32(m_caster->ApplyEffectModifiers(m_spellInfo, effIndex, float(block_value)));
378
                }
379
                // Victory Rush
380
                else if (m_spellInfo->SpellFamilyFlags[1] & 0x100)
381
                    ApplyPct(damage, m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
382
                // Shockwave
383
                else if (m_spellInfo->Id == 46968)
384
                {
385
                    int32 pct = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, 2);
386
                    if (pct > 0)
387
                        damage += int32(CalculatePct(m_caster->GetTotalAttackPowerValue(BASE_ATTACK), pct));
388
                    break;
389
                }
390
                break;
391
            }
392
            case SPELLFAMILY_WARLOCK:
393
            {
394
                // Incinerate Rank 1 & 2
395
                if ((m_spellInfo->SpellFamilyFlags[1] & 0x000040) && m_spellInfo->SpellIconID == 2128)
396
                {
397
                    // Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
398
                    // Check aura state for speed but aura state set not only for Immolate spell
399
                    if (unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
400
                    {
401
                        if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x4, 0, 0))
402
                            damage += damage/4;
403
                    }
404
                }
405
                // Conflagrate - consumes Immolate or Shadowflame
406
                else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
407
                {
408
                    AuraEffect const* aura = NULL;                // found req. aura for damage calculation
409
410
                    Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
411
                    for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
412
                    {
413
                        // for caster applied auras only
414
                        if ((*i)->GetSpellInfo()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
415
                            (*i)->GetCasterGUID() != m_caster->GetGUID())
416
                            continue;
417
418
                        // Immolate
419
                        if ((*i)->GetSpellInfo()->SpellFamilyFlags[0] & 0x4)
420
                        {
421
                            aura = *i;                      // it selected always if exist
422
                            break;
423
                        }
424
425
                        // Shadowflame
426
                        if ((*i)->GetSpellInfo()->SpellFamilyFlags[2] & 0x00000002)
427
                            aura = *i;                      // remember but wait possible Immolate as primary priority
428
                    }
429
430
                    // found Immolate or Shadowflame
431
                    if (aura)
432
                    {
433
                        uint32 pdamage = uint32(std::max(aura->GetAmount(), 0));
434
                        pdamage = m_caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
435
                        pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
436
                        uint32 pct_dir = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 1));
437
                        uint8 baseTotalTicks = uint8(m_caster->CalcSpellDuration(aura->GetSpellInfo()) / aura->GetSpellInfo()->Effects[EFFECT_0].Amplitude);
438
                        damage += int32(CalculatePct(pdamage * baseTotalTicks, pct_dir));
439
440
                        uint32 pct_dot = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 2)) / 3;
441
                        m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(int32(CalculatePct(pdamage * baseTotalTicks, pct_dot)));
442
443
                        apply_direct_bonus = false;
444
                        // Glyph of Conflagrate
445
                        if (!m_caster->HasAura(56235))
446
                            unitTarget->RemoveAurasDueToSpell(aura->GetId(), m_caster->GetGUID());
447
448
                        break;
449
                    }
450
                }
451
                // Shadow Bite
452
                else if (m_spellInfo->SpellFamilyFlags[1] & 0x400000)
453
                {
454
                    if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->isPet())
455
                    {
456
                        if (Player* owner = m_caster->GetOwner()->ToPlayer())
457
                        {
458
                            if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, 214, 0))
459
                            {
460
                                int32 bp0 = aurEff->GetId() == 54037 ? 4 : 8;
461
                                m_caster->CastCustomSpell(m_caster, 54425, &bp0, NULL, NULL, true);
462
                            }
463
                        }
464
                    }
465
                }
466
                break;
467
            }
468
            case SPELLFAMILY_PRIEST:
469
            {
470
                // Improved Mind Blast (Mind Blast in shadow form bonus)
471
                if (m_caster->GetShapeshiftForm() == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags[0] & 0x00002000))
472
                {
473
                    Unit::AuraEffectList const& ImprMindBlast = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_FLAT_MODIFIER);
474
                    for (Unit::AuraEffectList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i)
475
                    {
476
                        if ((*i)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PRIEST &&
477
                            ((*i)->GetSpellInfo()->SpellIconID == 95))
478
                        {
479
                            int chance = (*i)->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster);
480
                            if (roll_chance_i(chance))
481
                                // Mind Trauma
482
                                m_caster->CastSpell(unitTarget, 48301, true, 0);
483
                            break;
484
                        }
485
                    }
486
                }
487
                break;
488
            }
489
            case SPELLFAMILY_DRUID:
490
            {
491
                // Ferocious Bite
492
                if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[0] & 0x000800000) && m_spellInfo->SpellVisual[0] == 6587)
493
                {
494
                    // converts each extra point of energy into ($f1+$AP/410) additional damage
495
                    float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
496
                    float multiple = ap / 410 + m_spellInfo->Effects[effIndex].DamageMultiplier;
497
                    int32 energy = -(m_caster->ModifyPower(POWER_ENERGY, -30));
498
                    damage += int32(energy * multiple);
499
                    damage += int32(CalculatePct(m_caster->ToPlayer()->GetComboPoints() * ap, 7));
500
                }
501
                // Wrath
502
                else if (m_spellInfo->SpellFamilyFlags[0] & 0x00000001)
503
                {
504
                    // Improved Insect Swarm
505
                    if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0))
506
                        if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00200000, 0, 0))
507
                            AddPct(damage, aurEff->GetAmount());
508
                }
509
                break;
510
            }
511
            case SPELLFAMILY_ROGUE:
512
            {
513
                // Envenom
514
                if (m_spellInfo->SpellFamilyFlags[1] & 0x00000008)
515
                {
516
                    if (Player* player = m_caster->ToPlayer())
517
                    {
518
                        // consume from stack dozes not more that have combo-points
519
                        if (uint32 combo = player->GetComboPoints())
520
                        {
521
                            // Lookup for Deadly poison (only attacker applied)
522
                            if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00010000, 0, 0, m_caster->GetGUID()))
523
                            {
524
                                // count consumed deadly poison doses at target
525
                                bool needConsume = true;
526
                                uint32 spellId = aurEff->GetId();
527
528
                                uint32 doses = aurEff->GetBase()->GetStackAmount();
529
                                if (doses > combo)
530
                                    doses = combo;
531
532
                                // Master Poisoner
533
                                Unit::AuraEffectList const& auraList = player->GetAuraEffectsByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK);
534
                                for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter)
535
                                {
536
                                    if ((*iter)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellInfo()->SpellIconID == 1960)
537
                                    {
538
                                        uint32 chance = (*iter)->GetSpellInfo()->Effects[EFFECT_2].CalcValue(m_caster);
539
540
                                        if (chance && roll_chance_i(chance))
541
                                            needConsume = false;
542
543
                                        break;
544
                                    }
545
                                }
546
547
                                if (needConsume)
548
                                    for (uint32 i = 0; i < doses; ++i)
549
                                        unitTarget->RemoveAuraFromStack(spellId);
550
551
                                damage *= doses;
552
                                damage += int32(player->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * combo);
553
                            }
554
555
                            // Eviscerate and Envenom Bonus Damage (item set effect)
556
                            if (m_caster->HasAura(37169))
557
                                damage += combo * 40;
558
                        }
559
                    }
560
                }
561
                // Eviscerate
562
                else if (m_spellInfo->SpellFamilyFlags[0] & 0x00020000)
563
                {
564
                    if (m_caster->GetTypeId() == TYPEID_PLAYER)
565
                    {
566
                        if (uint32 combo = ((Player*)m_caster)->GetComboPoints())
567
                        {
568
                            float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
569
                            damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
570
571
                            // Eviscerate and Envenom Bonus Damage (item set effect)
572
                            if (m_caster->HasAura(37169))
573
                                damage += combo*40;
574
                        }
575
                    }
576
                }
577
                break;
578
            }
579
            case SPELLFAMILY_HUNTER:
580
            {
581
                //Gore
582
                if (m_spellInfo->SpellIconID == 1578)
583
                {
584
                    if (m_caster->HasAura(57627))           // Charge 6 sec post-affect
585
                        damage *= 2;
586
                }
587
                // Steady Shot
588
                else if (m_spellInfo->SpellFamilyFlags[1] & 0x1)
589
                {
590
                    bool found = false;
591
                    // check dazed affect
592
                    Unit::AuraEffectList const& decSpeedList = unitTarget->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED);
593
                    for (Unit::AuraEffectList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
594
                    {
595
                        if ((*iter)->GetSpellInfo()->SpellIconID == 15 && (*iter)->GetSpellInfo()->Dispel == 0)
596
                        {
597
                            found = true;
598
                            break;
599
                        }
600
                    }
601
602
                    // TODO: should this be put on taken but not done?
603
                    if (found)
604
                        damage += m_spellInfo->Effects[EFFECT_1].CalcValue();
605
606
                    if (Player* caster = m_caster->ToPlayer())
607
                    {
608
                        // Add Ammo and Weapon damage plus RAP * 0.1
609
                        if (Item* item = caster->GetWeaponForAttack(RANGED_ATTACK))
610
                        {
611
                            ItemTemplate const* weaponTemplate = item->GetTemplate();
612
                            float dmg_min = weaponTemplate->Damage[0].DamageMin;
613
                            float dmg_max = weaponTemplate->Damage[0].DamageMax;
614
                            if (dmg_max == 0.0f && dmg_min > dmg_max)
615
                                damage += int32(dmg_min);
616
                            else
617
                                damage += irand(int32(dmg_min), int32(dmg_max));
618
                            damage += int32(caster->GetAmmoDPS() * weaponTemplate->Delay * 0.001f);
619
                        }
620
                    }
621
                }
622
                break;
623
            }
624
            case SPELLFAMILY_PALADIN:
625
            {
626
                // Hammer of the Righteous
627
                if (m_spellInfo->SpellFamilyFlags[1]&0x00040000)
628
                {
629
                    // Add main hand dps * effect[2] amount
630
                    float average = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
631
                    int32 count = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, EFFECT_2);
632
                    damage += count * int32(average * IN_MILLISECONDS) / m_caster->GetAttackTime(BASE_ATTACK);
633
                    break;
634
                }
635
                // Shield of Righteousness
636
                if (m_spellInfo->SpellFamilyFlags[EFFECT_1] & 0x100000)
637
                {
638
                    uint8 level = m_caster->getLevel();
639
                    uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 29.5f), uint32(float(level) * 39.5f));
640
                    damage += CalculatePct(block_value, m_spellInfo->Effects[EFFECT_1].CalcValue());
641
                    break;
642
                }
643
                break;
644
            }
645
            case SPELLFAMILY_DEATHKNIGHT:
646
            {
647
                // Blood Boil - bonus for diseased targets
648
                if (m_spellInfo->SpellFamilyFlags[0] & 0x00040000)
649
                {
650
                    if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0, 0x00000002, m_caster->GetGUID()))
651
                    {
652
                        damage += m_damage / 2;
653
                        damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.035f);
654
                    }
655
                }
656
                break;
657
            }
658
            case SPELLFAMILY_MAGE:
659
            {
660
                // Deep Freeze should deal damage to permanently stun-immune targets.
661
                if (m_spellInfo->Id == 71757)
662
                    if (unitTarget->GetTypeId() != TYPEID_UNIT || !(unitTarget->IsImmunedToSpellEffect(sSpellMgr->GetSpellInfo(44572), 0)))
663
                        return;
664
                break;
665
            }
666
        }
667
668
        if (m_originalCaster && damage > 0 && apply_direct_bonus)
669
        {
670
            damage = m_originalCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
671
            damage = unitTarget->SpellDamageBonusTaken(m_originalCaster, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
672
        }
673
674
        m_damage += damage;
675
    }
676
}
677
678
void Spell::EffectDummy(SpellEffIndex effIndex)
679
{
680
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
681
        return;
682
683
    if (!unitTarget && !gameObjTarget && !itemTarget)
684
        return;
685
686
    uint32 spell_id = 0;
687
    int32 bp = 0;
688
    bool triggered = true;
689
    SpellCastTargets targets;
690
691
    // selection by spell family
692
    switch (m_spellInfo->SpellFamilyName)
693
    {
694
        case SPELLFAMILY_PALADIN:
695
            switch (m_spellInfo->Id)
696
            {
697
                case 31789:                                 // Righteous Defense (step 1)
698
                {
699
                    // Clear targets for eff 1
700
                    for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
701
                        ihit->effectMask &= ~(1<<1);
702
703
                    // not empty (checked), copy
704
                    Unit::AttackerSet attackers = unitTarget->getAttackers();
705
706
                    // remove invalid attackers
707
                    for (Unit::AttackerSet::iterator aItr = attackers.begin(); aItr != attackers.end();)
708
                        if (!(*aItr)->IsValidAttackTarget(m_caster))
709
                            attackers.erase(aItr++);
710
                        else
711
                            ++aItr;
712
713
                    // selected from list 3
714
                    uint32 maxTargets = std::min<uint32>(3, attackers.size());
715
                    for (uint32 i = 0; i < maxTargets; ++i)
716
                    {
717
                        Unit* attacker = Trinity::Containers::SelectRandomContainerElement(attackers);
718
                        AddUnitTarget(attacker, 1 << 1);
719
                        attackers.erase(attacker);
720
                    }
721
722
                    // now let next effect cast spell at each target.
723
                    return;
724
                }
725
            }
726
            break;
727
        case SPELLFAMILY_DEATHKNIGHT:
728
            switch (m_spellInfo->Id)
729
            {
730
                case 46584: // Raise Dead
731
                    if (m_caster->GetTypeId() != TYPEID_PLAYER)
732
                        return;
733
734
                    // Do we have talent Master of Ghouls?
735
                    if (m_caster->HasAura(52143))
736
                        // summon as pet
737
                        bp = 52150;
738
                    else
739
                        // or guardian
740
                        bp = 46585;
741
742
                    if (m_targets.HasDst())
743
                        targets.SetDst(*m_targets.GetDstPos());
744
                    else
745
                    {
746
                        targets.SetDst(*m_caster);
747
                        // Corpse not found - take reagents (only not triggered cast can take them)
748
                        triggered = false;
749
                    }
750
                    // Remove cooldown - summon spellls have category
751
                    m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
752
                    spell_id = 48289;
753
                    break;
754
                // Raise dead - take reagents and trigger summon spells
755
                case 48289:
756
                    if (m_targets.HasDst())
757
                        targets.SetDst(*m_targets.GetDstPos());
758
                    spell_id = CalculateDamage(0, NULL);
759
                    break;
760
            }
761
            break;
762
    }
763
764
    //spells triggered by dummy effect should not miss
765
    if (spell_id)
766
    {
767
        SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
768
769
        if (!spellInfo)
770
        {
771
            sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id);
772
            return;
773
        }
774
775
        targets.SetUnitTarget(unitTarget);
776
        Spell* spell = new Spell(m_caster, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, m_originalCasterGUID, true);
777
        if (bp) spell->SetSpellValue(SPELLVALUE_BASE_POINT0, bp);
778
        spell->prepare(&targets);
779
    }
780
781
    // pet auras
782
    if (PetAura const* petSpell = sSpellMgr->GetPetAura(m_spellInfo->Id, effIndex))
783
    {
784
        m_caster->AddPetAura(petSpell);
785
        return;
786
    }
787
788
    // normal DB scripted effect
789
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell ScriptStart spellid %u in EffectDummy(%u)", m_spellInfo->Id, effIndex);
790
    m_caster->GetMap()->ScriptsStart(sSpellScripts, uint32(m_spellInfo->Id | (effIndex << 24)), m_caster, unitTarget);
791
792
    // Script based implementation. Must be used only for not good for implementation in core spell effects
793
    // So called only for not proccessed cases
794
    if (gameObjTarget)
795
        sScriptMgr->OnDummyEffect(m_caster, m_spellInfo->Id, effIndex, gameObjTarget);
796
    else if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT)
797
        sScriptMgr->OnDummyEffect(m_caster, m_spellInfo->Id, effIndex, unitTarget->ToCreature());
798
    else if (itemTarget)
799
        sScriptMgr->OnDummyEffect(m_caster, m_spellInfo->Id, effIndex, itemTarget);
800
}
801
802
void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
803
{
804
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET
805
        && effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
806
        return;
807
808
    uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
809
810
    // todo: move those to spell scripts
811
    if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL
812
        && effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
813
    {
814
        // special cases
815
        switch (triggered_spell_id)
816
        {
817
            // Mirror Image
818
            case 58832:
819
            {
820
                // Glyph of Mirror Image
821
                if (m_caster->HasAura(63093))
822
                   m_caster->CastSpell(m_caster, 65047, true); // Mirror Image
823
824
                break;
825
            }
826
            // Vanish (not exist)
827
            case 18461:
828
            {
829
                unitTarget->RemoveMovementImpairingAuras();
830
                unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STALKED);
831
832
                // If this spell is given to an NPC, it must handle the rest using its own AI
833
                if (unitTarget->GetTypeId() != TYPEID_PLAYER)
834
                    return;
835
836
                // See if we already are stealthed. If so, we're done.
837
                if (unitTarget->HasAura(1784))
838
                    return;
839
840
                // Reset cooldown on stealth if needed
841
                if (unitTarget->ToPlayer()->HasSpellCooldown(1784))
842
                    unitTarget->ToPlayer()->RemoveSpellCooldown(1784);
843
844
                unitTarget->CastSpell(unitTarget, 1784, true);
845
                return;
846
            }
847
            // Demonic Empowerment -- succubus
848
            case 54437:
849
            {
850
                unitTarget->RemoveMovementImpairingAuras();
851
                unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STALKED);
852
                unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STUN);
853
854
                // Cast Lesser Invisibility
855
                unitTarget->CastSpell(unitTarget, 7870, true);
856
                return;
857
            }
858
            // just skip
859
            case 23770:                                         // Sayge's Dark Fortune of *
860
                // not exist, common cooldown can be implemented in scripts if need.
861
                return;
862
            // Brittle Armor - (need add max stack of 24575 Brittle Armor)
863
            case 29284:
864
            {
865
                // Brittle Armor
866
                SpellInfo const* spell = sSpellMgr->GetSpellInfo(24575);
867
                if (!spell)
868
                    return;
869
870
                for (uint32 j = 0; j < spell->StackAmount; ++j)
871
                    m_caster->CastSpell(unitTarget, spell->Id, true);
872
                return;
873
            }
874
            // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
875
            case 29286:
876
            {
877
                // Mercurial Shield
878
                SpellInfo const* spell = sSpellMgr->GetSpellInfo(26464);
879
                if (!spell)
880
                    return;
881
882
                for (uint32 j = 0; j < spell->StackAmount; ++j)
883
                    m_caster->CastSpell(unitTarget, spell->Id, true);
884
                return;
885
            }
886
            // Righteous Defense
887
            case 31980:
888
            {
889
                m_caster->CastSpell(unitTarget, 31790, true);
890
                return;
891
            }
892
            // Cloak of Shadows
893
            case 35729:
894
            {
895
                uint32 dispelMask = SpellInfo::GetDispelMask(DISPEL_ALL);
896
                Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
897
                for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();)
898
                {
899
                    // remove all harmful spells on you...
900
                    SpellInfo const* spell = iter->second->GetBase()->GetSpellInfo();
901
                    if ((spell->DmgClass == SPELL_DAMAGE_CLASS_MAGIC // only affect magic spells
902
                        || ((spell->GetDispelMask()) & dispelMask))
903
                        // ignore positive and passive auras
904
                        && !iter->second->IsPositive() && !iter->second->GetBase()->IsPassive())
905
                    {
906
                        m_caster->RemoveAura(iter);
907
                    }
908
                    else
909
                        ++iter;
910
                }
911
                return;
912
            }
913
        }
914
    }
915
916
    // normal case
917
    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
918
    if (!spellInfo)
919
    {
920
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
921
        return;
922
    }
923
924
    SpellCastTargets targets;
925
    if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
926
    {
927
        if (!spellInfo->NeedsToBeTriggeredByCaster())
928
            return;
929
        targets.SetUnitTarget(unitTarget);
930
    }
931
    else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH)
932
    {
933
        if (spellInfo->NeedsToBeTriggeredByCaster() && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
934
            return;
935
936
        if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION)
937
            targets.SetDst(m_targets);
938
939
        targets.SetUnitTarget(m_caster);
940
    }
941
942
    CustomSpellValues values;
943
    // set basepoints for trigger with value effect
944
    if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE)
945
    {
946
        // maybe need to set value only when basepoints == 0?
947
        values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
948
        values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage);
949
        values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage);
950
    }
951
952
    // Remove spell cooldown (not category) if spell triggering spell with cooldown and same category
953
    if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime
954
        && m_spellInfo->Category == spellInfo->Category)
955
        m_caster->ToPlayer()->RemoveSpellCooldown(spellInfo->Id);
956
957
    // original caster guid only for GO cast
958
    m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, NULL, NULL, m_originalCasterGUID);
959
}
960
961
void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex)
962
{
963
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET
964
        && effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
965
        return;
966
967
    uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
968
969
    // normal case
970
    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
971
    if (!spellInfo)
972
    {
973
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
974
        return;
975
    }
976
977
    SpellCastTargets targets;
978
    if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
979
    {
980
        if (!spellInfo->NeedsToBeTriggeredByCaster())
981
            return;
982
        targets.SetUnitTarget(unitTarget);
983
    }
984
    else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
985
    {
986
        if (spellInfo->NeedsToBeTriggeredByCaster() && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK))
987
            return;
988
989
        if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION)
990
            targets.SetDst(m_targets);
991
992
        targets.SetUnitTarget(m_caster);
993
    }
994
995
    CustomSpellValues values;
996
    // set basepoints for trigger with value effect
997
    if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE)
998
    {
999
        // maybe need to set value only when basepoints == 0?
1000
        values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
1001
        values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage);
1002
        values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage);
1003
    }
1004
1005
    // Remove spell cooldown (not category) if spell triggering spell with cooldown and same category
1006
    if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime
1007
        && m_spellInfo->Category == spellInfo->Category)
1008
        m_caster->ToPlayer()->RemoveSpellCooldown(spellInfo->Id);
1009
1010
    // original caster guid only for GO cast
1011
    m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, NULL, NULL, m_originalCasterGUID);
1012
}
1013
1014
void Spell::EffectForceCast(SpellEffIndex effIndex)
1015
{
1016
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1017
        return;
1018
1019
    if (!unitTarget)
1020
        return;
1021
1022
    uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
1023
1024
    // normal case
1025
    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
1026
1027
    if (!spellInfo)
1028
    {
1029
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id);
1030
        return;
1031
    }
1032
1033
    if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST && damage)
1034
    {
1035
        switch (m_spellInfo->Id)
1036
        {
1037
            case 52588: // Skeletal Gryphon Escape
1038
            case 48598: // Ride Flamebringer Cue
1039
                unitTarget->RemoveAura(damage);
1040
                break;
1041
            case 52463: // Hide In Mine Car
1042
            case 52349: // Overtake
1043
                unitTarget->CastCustomSpell(unitTarget, spellInfo->Id, &damage, NULL, NULL, true, NULL, NULL, m_originalCasterGUID);
1044
                return;
1045
        }
1046
    }
1047
1048
    CustomSpellValues values;
1049
    // set basepoints for trigger with value effect
1050
    if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE)
1051
    {
1052
        // maybe need to set value only when basepoints == 0?
1053
        values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
1054
        values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage);
1055
        values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage);
1056
    }
1057
1058
    SpellCastTargets targets;
1059
    targets.SetUnitTarget(m_caster);
1060
1061
    unitTarget->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK);
1062
}
1063
1064
void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex)
1065
{
1066
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
1067
        return;
1068
1069
    uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell;
1070
    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
1071
1072
    if (!spellInfo)
1073
    {
1074
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id, triggered_spell_id);
1075
        return;
1076
    }
1077
1078
    finish();
1079
1080
    m_caster->CastSpell((Unit*)NULL, spellInfo, false);
1081
}
1082
1083
void Spell::EffectJump(SpellEffIndex effIndex)
1084
{
1085
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
1086
        return;
1087
1088
    if (m_caster->isInFlight())
1089
        return;
1090
1091
    if (!unitTarget)
1092
        return;
1093
1094
    float x, y, z;
1095
    unitTarget->GetContactPoint(m_caster, x, y, z, CONTACT_DISTANCE);
1096
1097
    float speedXY, speedZ;
1098
    CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(x, y), speedXY, speedZ);
1099
    m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
1100
}
1101
1102
void Spell::EffectJumpDest(SpellEffIndex effIndex)
1103
{
1104
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
1105
        return;
1106
1107
    if (m_caster->isInFlight())
1108
        return;
1109
1110
    if (!m_targets.HasDst())
1111
        return;
1112
1113
    // Init dest coordinates
1114
    float x, y, z;
1115
    destTarget->GetPosition(x, y, z);
1116
1117
    float speedXY, speedZ;
1118
    CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(x, y), speedXY, speedZ);
1119
    m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
1120
}
1121
1122
void Spell::CalculateJumpSpeeds(uint8 i, float dist, float & speedXY, float & speedZ)
1123
{
1124
    if (m_spellInfo->Effects[i].MiscValue)
1125
        speedZ = float(m_spellInfo->Effects[i].MiscValue)/10;
1126
    else if (m_spellInfo->Effects[i].MiscValueB)
1127
        speedZ = float(m_spellInfo->Effects[i].MiscValueB)/10;
1128
    else
1129
        speedZ = 10.0f;
1130
    speedXY = dist * 10.0f / speedZ;
1131
}
1132
1133
void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/)
1134
{
1135
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1136
        return;
1137
1138
    if (!unitTarget || unitTarget->isInFlight())
1139
        return;
1140
1141
    // Pre effects
1142
    uint8 uiMaxSafeLevel = 0;
1143
    switch (m_spellInfo->Id)
1144
    {
1145
        case 48129:  // Scroll of Recall
1146
            uiMaxSafeLevel = 40;
1147
        case 60320:  // Scroll of Recall II
1148
            if (!uiMaxSafeLevel)
1149
                uiMaxSafeLevel = 70;
1150
        case 60321:  // Scroll of Recal III
1151
            if (!uiMaxSafeLevel)
1152
                uiMaxSafeLevel = 80;
1153
1154
            if (unitTarget->getLevel() > uiMaxSafeLevel)
1155
            {
1156
                unitTarget->AddAura(60444, unitTarget); //Apply Lost! Aura
1157
1158
                // ALLIANCE from 60323 to 60330 - HORDE from 60328 to 60335
1159
                uint32 spellId = 60323;
1160
                if (m_caster->ToPlayer()->GetTeam() == HORDE)
1161
                    spellId += 5;
1162
1163
                spellId += urand(0, 7);
1164
                m_caster->CastSpell(m_caster, spellId, true);
1165
                return;
1166
            }
1167
            break;
1168
        case 66550: // teleports outside (Isle of Conquest)
1169
            if (Player* target = unitTarget->ToPlayer())
1170
            {
1171
                if (target->GetTeamId() == TEAM_ALLIANCE)
1172
                    m_targets.SetDst(442.24f, -835.25f, 44.30f, 0.06f, 628);
1173
                else
1174
                    m_targets.SetDst(1120.43f, -762.11f, 47.92f, 2.94f, 628);
1175
            }
1176
            break;
1177
        case 66551: // teleports inside (Isle of Conquest)
1178
            if (Player* target = unitTarget->ToPlayer())
1179
            {
1180
                if (target->GetTeamId() == TEAM_ALLIANCE)
1181
                    m_targets.SetDst(389.57f, -832.38f, 48.65f, 3.00f, 628);
1182
                else
1183
                    m_targets.SetDst(1174.85f, -763.24f, 48.72f, 6.26f, 628);
1184
            }
1185
            break;
1186
    }
1187
1188
    // If not exist data for dest location - return
1189
    if (!m_targets.HasDst())
1190
    {
1191
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id);
1192
        return;
1193
    }
1194
1195
    // Init dest coordinates
1196
    uint32 mapid = destTarget->GetMapId();
1197
    if (mapid == MAPID_INVALID)
1198
        mapid = unitTarget->GetMapId();
1199
    float x, y, z, orientation;
1200
    destTarget->GetPosition(x, y, z, orientation);
1201
    if (!orientation && m_targets.GetUnitTarget())
1202
        orientation = m_targets.GetUnitTarget()->GetOrientation();
1203
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTeleportUnits - teleport unit to %u %f %f %f %f\n", mapid, x, y, z, orientation);
1204
1205
    if (mapid == unitTarget->GetMapId())
1206
        unitTarget->NearTeleportTo(x, y, z, orientation, unitTarget == m_caster);
1207
    else if (unitTarget->GetTypeId() == TYPEID_PLAYER)
1208
        unitTarget->ToPlayer()->TeleportTo(mapid, x, y, z, orientation, unitTarget == m_caster ? TELE_TO_SPELL : 0);
1209
1210
    // post effects for TARGET_DEST_DB
1211
    switch (m_spellInfo->Id)
1212
    {
1213
        // Dimensional Ripper - Everlook
1214
        case 23442:
1215
        {
1216
            int32 r = irand(0, 119);
1217
            if (r >= 70)                                  // 7/12 success
1218
            {
1219
                if (r < 100)                              // 4/12 evil twin
1220
                    m_caster->CastSpell(m_caster, 23445, true);
1221
                else                                        // 1/12 fire
1222
                    m_caster->CastSpell(m_caster, 23449, true);
1223
            }
1224
            return;
1225
        }
1226
        // Ultrasafe Transporter: Toshley's Station
1227
        case 36941:
1228
        {
1229
            if (roll_chance_i(50))                        // 50% success
1230
            {
1231
                int32 rand_eff = urand(1, 7);
1232
                switch (rand_eff)
1233
                {
1234
                    case 1:
1235
                        // soul split - evil
1236
                        m_caster->CastSpell(m_caster, 36900, true);
1237
                        break;
1238
                    case 2:
1239
                        // soul split - good
1240
                        m_caster->CastSpell(m_caster, 36901, true);
1241
                        break;
1242
                    case 3:
1243
                        // Increase the size
1244
                        m_caster->CastSpell(m_caster, 36895, true);
1245
                        break;
1246
                    case 4:
1247
                        // Decrease the size
1248
                        m_caster->CastSpell(m_caster, 36893, true);
1249
                        break;
1250
                    case 5:
1251
                    // Transform
1252
                    {
1253
                        if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
1254
                            m_caster->CastSpell(m_caster, 36897, true);
1255
                        else
1256
                            m_caster->CastSpell(m_caster, 36899, true);
1257
                        break;
1258
                    }
1259
                    case 6:
1260
                        // chicken
1261
                        m_caster->CastSpell(m_caster, 36940, true);
1262
                        break;
1263
                    case 7:
1264
                        // evil twin
1265
                        m_caster->CastSpell(m_caster, 23445, true);
1266
                        break;
1267
                }
1268
            }
1269
            return;
1270
        }
1271
        // Dimensional Ripper - Area 52
1272
        case 36890:
1273
        {
1274
            if (roll_chance_i(50))                        // 50% success
1275
            {
1276
                int32 rand_eff = urand(1, 4);
1277
                switch (rand_eff)
1278
                {
1279
                    case 1:
1280
                        // soul split - evil
1281
                        m_caster->CastSpell(m_caster, 36900, true);
1282
                        break;
1283
                    case 2:
1284
                        // soul split - good
1285
                        m_caster->CastSpell(m_caster, 36901, true);
1286
                        break;
1287
                    case 3:
1288
                        // Increase the size
1289
                        m_caster->CastSpell(m_caster, 36895, true);
1290
                        break;
1291
                    case 4:
1292
                        // Transform
1293
                    {
1294
                        if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
1295
                            m_caster->CastSpell(m_caster, 36897, true);
1296
                        else
1297
                            m_caster->CastSpell(m_caster, 36899, true);
1298
                        break;
1299
                    }
1300
                }
1301
            }
1302
            return;
1303
        }
1304
    }
1305
}
1306
1307
void Spell::EffectApplyAura(SpellEffIndex effIndex)
1308
{
1309
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1310
        return;
1311
1312
    if (!m_spellAura || !unitTarget)
1313
        return;
1314
    ASSERT(unitTarget == m_spellAura->GetOwner());
1315
    m_spellAura->_ApplyEffectForTargets(effIndex);
1316
}
1317
1318
void Spell::EffectApplyAreaAura(SpellEffIndex effIndex)
1319
{
1320
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1321
        return;
1322
1323
    if (!m_spellAura || !unitTarget)
1324
        return;
1325
    ASSERT (unitTarget == m_spellAura->GetOwner());
1326
    m_spellAura->_ApplyEffectForTargets(effIndex);
1327
}
1328
1329
void Spell::EffectUnlearnSpecialization(SpellEffIndex effIndex)
1330
{
1331
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1332
        return;
1333
1334
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
1335
        return;
1336
1337
    Player* player = unitTarget->ToPlayer();
1338
    uint32 spellToUnlearn = m_spellInfo->Effects[effIndex].TriggerSpell;
1339
1340
    player->removeSpell(spellToUnlearn);
1341
1342
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell: Player %u has unlearned spell %u from NpcGUID: %u", player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow());
1343
}
1344
1345
void Spell::EffectPowerDrain(SpellEffIndex effIndex)
1346
{
1347
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1348
        return;
1349
1350
    if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
1351
        return;
1352
1353
    Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
1354
1355
    if (!unitTarget || !unitTarget->isAlive() || unitTarget->getPowerType() != powerType || damage < 0)
1356
        return;
1357
1358
    // add spell damage bonus
1359
    damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
1360
    damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
1361
1362
    // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
1363
    int32 power = damage;
1364
    if (powerType == POWER_MANA)
1365
        power -= unitTarget->GetSpellCritDamageReduction(power);
1366
1367
    int32 newDamage = -(unitTarget->ModifyPower(powerType, -int32(power)));
1368
1369
    float gainMultiplier = 0.0f;
1370
1371
    // Don`t restore from self drain
1372
    if (m_caster != unitTarget)
1373
    {
1374
        gainMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
1375
1376
        int32 gain = int32(newDamage* gainMultiplier);
1377
1378
        m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, powerType);
1379
    }
1380
    ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, gainMultiplier);
1381
}
1382
1383
void Spell::EffectSendEvent(SpellEffIndex effIndex)
1384
{
1385
    // we do not handle a flag dropping or clicking on flag in battleground by sendevent system
1386
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET
1387
        && effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
1388
        return;
1389
1390
    WorldObject* target = NULL;
1391
1392
    // call events for object target if present
1393
    if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
1394
    {
1395
        if (unitTarget)
1396
            target = unitTarget;
1397
        else if (gameObjTarget)
1398
            target = gameObjTarget;
1399
    }
1400
    else // if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
1401
    {
1402
        // let's prevent executing effect handler twice in case when spell effect is capable of targeting an object
1403
        // this check was requested by scripters, but it has some downsides:
1404
        // now it's impossible to script (using sEventScripts) a cast which misses all targets
1405
        // or to have an ability to script the moment spell hits dest (in a case when there are object targets present)
1406
        if (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK))
1407
            return;
1408
        // some spells have no target entries in dbc and they use focus target
1409
        if (focusObject)
1410
            target = focusObject;
1411
        // TODO: there should be a possibility to pass dest target to event script
1412
    }
1413
1414
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id);
1415
1416
    if (ZoneScript* zoneScript = m_caster->GetZoneScript())
1417
        zoneScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue);
1418
    else if (InstanceScript* instanceScript = m_caster->GetInstanceScript())    // needed in case Player is the caster
1419
        instanceScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue);
1420
1421
    m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->Effects[effIndex].MiscValue, m_caster, target);
1422
}
1423
1424
void Spell::EffectPowerBurn(SpellEffIndex effIndex)
1425
{
1426
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1427
        return;
1428
1429
    if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
1430
        return;
1431
1432
    Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
1433
1434
    if (!unitTarget || !unitTarget->isAlive() || unitTarget->getPowerType() != powerType || damage < 0)
1435
        return;
1436
1437
    // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
1438
    if (m_spellInfo->Id == 8129)
1439
    {
1440
        int32 maxDamage = int32(CalculatePct(m_caster->GetMaxPower(powerType), damage * 2));
1441
        damage = int32(CalculatePct(unitTarget->GetMaxPower(powerType), damage));
1442
        damage = std::min(damage, maxDamage);
1443
    }
1444
1445
    int32 power = damage;
1446
    // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
1447
    if (powerType == POWER_MANA)
1448
        power -= unitTarget->GetSpellCritDamageReduction(power);
1449
1450
    int32 newDamage = -(unitTarget->ModifyPower(powerType, -power));
1451
1452
    // NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier
1453
    float dmgMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
1454
1455
    // add log data before multiplication (need power amount, not damage)
1456
    ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, 0.0f);
1457
1458
    newDamage = int32(newDamage* dmgMultiplier);
1459
1460
    m_damage += newDamage;
1461
}
1462
1463
void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
1464
{
1465
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
1466
        return;
1467
1468
    if (unitTarget && unitTarget->isAlive() && damage >= 0)
1469
    {
1470
        // Try to get original caster
1471
        Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
1472
1473
        // Skip if m_originalCaster not available
1474
        if (!caster)
1475
            return;
1476
1477
        int32 addhealth = damage;
1478
1479
        // Vessel of the Naaru (Vial of the Sunwell trinket)
1480
        if (m_spellInfo->Id == 45064)
1481
        {
1482
            // Amount of heal - depends from stacked Holy Energy
1483
            int damageAmount = 0;
1484
            if (AuraEffect const* aurEff = m_caster->GetAuraEffect(45062, 0))
1485
            {
1486
                damageAmount+= aurEff->GetAmount();
1487
                m_caster->RemoveAurasDueToSpell(45062);
1488
            }
1489
1490
            addhealth += damageAmount;
1491
        }
1492
        // Runic Healing Injector (heal increased by 25% for engineers - 3.2.0 patch change)
1493
        else if (m_spellInfo->Id == 67489)
1494
        {
1495
            if (Player* player = m_caster->ToPlayer())
1496
                if (player->HasSkill(SKILL_ENGINEERING))
1497
                    AddPct(addhealth, 25);
1498
        }
1499
        // Swiftmend - consumes Regrowth or Rejuvenation
1500
        else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND, m_spellInfo, m_caster))
1501
        {
1502
            Unit::AuraEffectList const& RejorRegr = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
1503
            // find most short by duration
1504
            AuraEffect* targetAura = NULL;
1505
            for (Unit::AuraEffectList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
1506
            {
1507
                if ((*i)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DRUID
1508
                    && (*i)->GetSpellInfo()->SpellFamilyFlags[0] & 0x50)
1509
                {
1510
                    if (!targetAura || (*i)->GetBase()->GetDuration() < targetAura->GetBase()->GetDuration())
1511
                        targetAura = *i;
1512
                }
1513
            }
1514
1515
            if (!targetAura)
1516
            {
1517
                sLog->outError(LOG_FILTER_SPELLS_AURAS, "Target(GUID:" UI64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
1518
                return;
1519
            }
1520
1521
            int32 tickheal = targetAura->GetAmount();
1522
            if (Unit* auraCaster = targetAura->GetCaster())
1523
                tickheal = auraCaster->SpellHealingBonusDone(unitTarget, targetAura->GetSpellInfo(), tickheal, DOT);
1524
            //int32 tickheal = targetAura->GetSpellInfo()->EffectBasePoints[idx] + 1;
1525
            //It is said that talent bonus should not be included
1526
1527
            int32 tickcount = 0;
1528
            // Rejuvenation
1529
            if (targetAura->GetSpellInfo()->SpellFamilyFlags[0] & 0x10)
1530
                tickcount = 4;
1531
            // Regrowth
1532
            else // if (targetAura->GetSpellInfo()->SpellFamilyFlags[0] & 0x40)
1533
                tickcount = 6;
1534
1535
            addhealth += tickheal * tickcount;
1536
1537
            // Glyph of Swiftmend
1538
            if (!caster->HasAura(54824))
1539
                unitTarget->RemoveAura(targetAura->GetId(), targetAura->GetCasterGUID());
1540
1541
            //addhealth += tickheal * tickcount;
1542
            //addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth, HEAL, unitTarget);
1543
        }
1544
        // Nourish
1545
        else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x2000000)
1546
        {
1547
            addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
1548
1549
            // Glyph of Nourish
1550
            if (AuraEffect const* aurEff = m_caster->GetAuraEffect(62971, 0))
1551
            {
1552
                Unit::AuraEffectList const& Periodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
1553
                for (Unit::AuraEffectList::const_iterator i = Periodic.begin(); i != Periodic.end(); ++i)
1554
                {
1555
                    if (m_caster->GetGUID() == (*i)->GetCasterGUID())
1556
                        AddPct(addhealth, aurEff->GetAmount());
1557
                }
1558
            }
1559
        }
1560
        // Death Pact - return pct of max health to caster
1561
        else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000)
1562
            addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL);
1563
        else
1564
            addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
1565
1566
        addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL);
1567
1568
        // Remove Grievious bite if fully healed
1569
        if (unitTarget->HasAura(48920) && (unitTarget->GetHealth() + addhealth >= unitTarget->GetMaxHealth()))
1570
            unitTarget->RemoveAura(48920);
1571
1572
        m_damage -= addhealth;
1573
    }
1574
}
1575
1576
void Spell::EffectHealPct(SpellEffIndex /*effIndex*/)
1577
{
1578
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1579
        return;
1580
1581
    if (!unitTarget || !unitTarget->isAlive() || damage < 0)
1582
        return;
1583
1584
    // Skip if m_originalCaster not available
1585
    if (!m_originalCaster)
1586
        return;
1587
1588
    // Rune Tap - Party
1589
    if (m_spellInfo->Id == 59754 && unitTarget == m_caster)
1590
        return;
1591
1592
    uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL);
1593
    heal = unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
1594
1595
    m_healing += heal;
1596
}
1597
1598
void Spell::EffectHealMechanical(SpellEffIndex /*effIndex*/)
1599
{
1600
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1601
        return;
1602
1603
    if (!unitTarget || !unitTarget->isAlive() || damage < 0)
1604
        return;
1605
1606
    // Skip if m_originalCaster not available
1607
    if (!m_originalCaster)
1608
        return;
1609
1610
    uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, uint32(damage), HEAL);
1611
1612
    m_healing += unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
1613
}
1614
1615
void Spell::EffectHealthLeech(SpellEffIndex effIndex)
1616
{
1617
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1618
        return;
1619
1620
    if (!unitTarget || !unitTarget->isAlive() || damage < 0)
1621
        return;
1622
1623
    damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
1624
    damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
1625
1626
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "HealthLeech :%i", damage);
1627
1628
    float healMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this);
1629
1630
    m_damage += damage;
1631
    // get max possible damage, don't count overkill for heal
1632
    uint32 healthGain = uint32(-unitTarget->GetHealthGain(-damage) * healMultiplier);
1633
1634
    if (m_caster->isAlive())
1635
    {
1636
        healthGain = m_caster->SpellHealingBonusDone(m_caster, m_spellInfo, healthGain, HEAL);
1637
        healthGain = m_caster->SpellHealingBonusTaken(m_caster, m_spellInfo, healthGain, HEAL);
1638
1639
        m_caster->HealBySpell(m_caster, m_spellInfo, uint32(healthGain));
1640
    }
1641
}
1642
1643
void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
1644
{
1645
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
1646
        return;
1647
1648
    Player* player = unitTarget->ToPlayer();
1649
1650
    uint32 newitemid = itemtype;
1651
    ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(newitemid);
1652
    if (!pProto)
1653
    {
1654
        player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
1655
        return;
1656
    }
1657
1658
    // bg reward have some special in code work
1659
    uint32 bgType = 0;
1660
    switch (m_spellInfo->Id)
1661
    {
1662
        case SPELL_AV_MARK_WINNER:
1663
        case SPELL_AV_MARK_LOSER:
1664
            bgType = BATTLEGROUND_AV;
1665
            break;
1666
        case SPELL_WS_MARK_WINNER:
1667
        case SPELL_WS_MARK_LOSER:
1668
            bgType = BATTLEGROUND_WS;
1669
            break;
1670
        case SPELL_AB_MARK_WINNER:
1671
        case SPELL_AB_MARK_LOSER:
1672
            bgType = BATTLEGROUND_AB;
1673
            break;
1674
        default:
1675
            break;
1676
    }
1677
1678
    uint32 num_to_add = damage;
1679
1680
    if (num_to_add < 1)
1681
        num_to_add = 1;
1682
    if (num_to_add > pProto->GetMaxStackSize())
1683
        num_to_add = pProto->GetMaxStackSize();
1684
1685
    // init items_count to 1, since 1 item will be created regardless of specialization
1686
    int items_count=1;
1687
    // the chance to create additional items
1688
    float additionalCreateChance=0.0f;
1689
    // the maximum number of created additional items
1690
    uint8 additionalMaxNum=0;
1691
    // get the chance and maximum number for creating extra items
1692
    if (canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum))
1693
    {
1694
        // roll with this chance till we roll not to create or we create the max num
1695
        while (roll_chance_f(additionalCreateChance) && items_count <= additionalMaxNum)
1696
            ++items_count;
1697
    }
1698
1699
    // really will be created more items
1700
    num_to_add *= items_count;
1701
1702
    // can the player store the new item?
1703
    ItemPosCountVec dest;
1704
    uint32 no_space = 0;
1705
    InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space);
1706
    if (msg != EQUIP_ERR_OK)
1707
    {
1708
        // convert to possible store amount
1709
        if (msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS)
1710
            num_to_add -= no_space;
1711
        else
1712
        {
1713
            // if not created by another reason from full inventory or unique items amount limitation
1714
            player->SendEquipError(msg, NULL, NULL, newitemid);
1715
            return;
1716
        }
1717
    }
1718
1719
    if (num_to_add)
1720
    {
1721
        // create the new item and store it
1722
        Item* pItem = player->StoreNewItem(dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
1723
1724
        // was it successful? return error if not
1725
        if (!pItem)
1726
        {
1727
            player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
1728
            return;
1729
        }
1730
1731
        // set the "Crafted by ..." property of the item
1732
        if (pItem->GetTemplate()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetTemplate()->Class != ITEM_CLASS_QUEST && newitemid != 6265 && newitemid != 6948)
1733
            pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow());
1734
1735
        // send info to the client
1736
        player->SendNewItem(pItem, num_to_add, true, bgType == 0);
1737
1738
        // we succeeded in creating at least one item, so a levelup is possible
1739
        if (bgType == 0)
1740
            player->UpdateCraftSkill(m_spellInfo->Id);
1741
    }
1742
1743
/*
1744
    // for battleground marks send by mail if not add all expected
1745
    if (no_space > 0 && bgType)
1746
    {
1747
        if (Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BattlegroundTypeId(bgType)))
1748
            bg->SendRewardMarkByMail(player, newitemid, no_space);
1749
    }
1750
*/
1751
}
1752
1753
void Spell::EffectCreateItem(SpellEffIndex effIndex)
1754
{
1755
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1756
        return;
1757
1758
    DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType);
1759
    ExecuteLogEffectCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType);
1760
}
1761
1762
void Spell::EffectCreateItem2(SpellEffIndex effIndex)
1763
{
1764
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1765
        return;
1766
1767
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
1768
        return;
1769
1770
    Player* player = unitTarget->ToPlayer();
1771
1772
    uint32 item_id = m_spellInfo->Effects[effIndex].ItemType;
1773
1774
    if (item_id)
1775
        DoCreateItem(effIndex, item_id);
1776
1777
    // special case: fake item replaced by generate using spell_loot_template
1778
    if (m_spellInfo->IsLootCrafting())
1779
    {
1780
        if (item_id)
1781
        {
1782
            if (!player->HasItemCount(item_id))
1783
                return;
1784
1785
            // remove reagent
1786
            uint32 count = 1;
1787
            player->DestroyItemCount(item_id, count, true);
1788
1789
            // create some random items
1790
            player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
1791
        }
1792
        else
1793
            player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);    // create some random items
1794
    }
1795
    // TODO: ExecuteLogEffectCreateItem(i, m_spellInfo->Effects[i].ItemType);
1796
}
1797
1798
void Spell::EffectCreateRandomItem(SpellEffIndex /*effIndex*/)
1799
{
1800
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1801
        return;
1802
1803
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
1804
        return;
1805
    Player* player = unitTarget->ToPlayer();
1806
1807
    // create some random items
1808
    player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
1809
    // TODO: ExecuteLogEffectCreateItem(i, m_spellInfo->Effects[i].ItemType);
1810
}
1811
1812
void Spell::EffectPersistentAA(SpellEffIndex effIndex)
1813
{
1814
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
1815
        return;
1816
1817
    if (!m_spellAura)
1818
    {
1819
        Unit* caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster;
1820
        float radius = m_spellInfo->Effects[effIndex].CalcRadius(caster);
1821
1822
        // Caster not in world, might be spell triggered from aura removal
1823
        if (!caster->IsInWorld())
1824
            return;
1825
        DynamicObject* dynObj = new DynamicObject(false);
1826
        if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL))
1827
        {
1828
            delete dynObj;
1829
            return;
1830
        }
1831
1832
        if (Aura* aura = Aura::TryCreate(m_spellInfo, MAX_EFFECT_MASK, dynObj, caster, &m_spellValue->EffectBasePoints[0]))
1833
        {
1834
            m_spellAura = aura;
1835
            m_spellAura->_RegisterForTargets();
1836
        }
1837
        else
1838
            return;
1839
    }
1840
1841
    ASSERT(m_spellAura->GetDynobjOwner());
1842
    m_spellAura->_ApplyEffectForTargets(effIndex);
1843
}
1844
1845
void Spell::EffectEnergize(SpellEffIndex effIndex)
1846
{
1847
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1848
        return;
1849
1850
    if (!unitTarget)
1851
        return;
1852
    if (!unitTarget->isAlive())
1853
        return;
1854
1855
    if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
1856
        return;
1857
1858
    Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
1859
1860
    // Some level depends spells
1861
    int level_multiplier = 0;
1862
    int level_diff = 0;
1863
    switch (m_spellInfo->Id)
1864
    {
1865
        case 9512:                                          // Restore Energy
1866
            level_diff = m_caster->getLevel() - 40;
1867
            level_multiplier = 2;
1868
            break;
1869
        case 24571:                                         // Blood Fury
1870
            level_diff = m_caster->getLevel() - 60;
1871
            level_multiplier = 10;
1872
            break;
1873
        case 24532:                                         // Burst of Energy
1874
            level_diff = m_caster->getLevel() - 60;
1875
            level_multiplier = 4;
1876
            break;
1877
        case 31930:                                         // Judgements of the Wise
1878
        case 63375:                                         // Improved Stormstrike
1879
        case 68082:                                         // Glyph of Seal of Command
1880
            damage = int32(CalculatePct(unitTarget->GetCreateMana(), damage));
1881
            break;
1882
        case 48542:                                         // Revitalize
1883
            damage = int32(CalculatePct(unitTarget->GetMaxPower(power), damage));
1884
            break;
1885
        case 67490:                                         // Runic Mana Injector (mana gain increased by 25% for engineers - 3.2.0 patch change)
1886
        {
1887
            if (Player* player = m_caster->ToPlayer())
1888
                if (player->HasSkill(SKILL_ENGINEERING))
1889
                    AddPct(damage, 25);
1890
            break;
1891
        }
1892
        case 71132:                                         // Glyph of Shadow Word: Pain
1893
            damage = int32(CalculatePct(unitTarget->GetCreateMana(), 1));  // set 1 as value, missing in dbc
1894
            break;
1895
        default:
1896
            break;
1897
    }
1898
1899
    if (level_diff > 0)
1900
        damage -= level_multiplier * level_diff;
1901
1902
    if (damage < 0)
1903
        return;
1904
1905
    if (unitTarget->GetMaxPower(power) == 0)
1906
        return;
1907
1908
    m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
1909
1910
    // Mad Alchemist's Potion
1911
    if (m_spellInfo->Id == 45051)
1912
    {
1913
        // find elixirs on target
1914
        bool guardianFound = false;
1915
        bool battleFound = false;
1916
        Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
1917
        for (Unit::AuraApplicationMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
1918
        {
1919
            uint32 spell_id = itr->second->GetBase()->GetId();
1920
            if (!guardianFound)
1921
                if (sSpellMgr->IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_GUARDIAN))
1922
                    guardianFound = true;
1923
            if (!battleFound)
1924
                if (sSpellMgr->IsSpellMemberOfSpellGroup(spell_id, SPELL_GROUP_ELIXIR_BATTLE))
1925
                    battleFound = true;
1926
            if (battleFound && guardianFound)
1927
                break;
1928
        }
1929
1930
        // get all available elixirs by mask and spell level
1931
        std::set<uint32> avalibleElixirs;
1932
        if (!guardianFound)
1933
            sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_GUARDIAN, avalibleElixirs);
1934
        if (!battleFound)
1935
            sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, avalibleElixirs);
1936
        for (std::set<uint32>::iterator itr = avalibleElixirs.begin(); itr != avalibleElixirs.end();)
1937
        {
1938
            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(*itr);
1939
            if (spellInfo->SpellLevel < m_spellInfo->SpellLevel || spellInfo->SpellLevel > unitTarget->getLevel())
1940
                avalibleElixirs.erase(itr++);
1941
            else if (sSpellMgr->IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_SHATTRATH))
1942
                avalibleElixirs.erase(itr++);
1943
            else if (sSpellMgr->IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_UNSTABLE))
1944
                avalibleElixirs.erase(itr++);
1945
            else
1946
                ++itr;
1947
        }
1948
1949
        if (!avalibleElixirs.empty())
1950
        {
1951
            // cast random elixir on target
1952
            m_caster->CastSpell(unitTarget, Trinity::Containers::SelectRandomContainerElement(avalibleElixirs), true, m_CastItem);
1953
        }
1954
    }
1955
}
1956
1957
void Spell::EffectEnergizePct(SpellEffIndex effIndex)
1958
{
1959
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
1960
        return;
1961
1962
    if (!unitTarget)
1963
        return;
1964
    if (!unitTarget->isAlive())
1965
        return;
1966
1967
    if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS))
1968
        return;
1969
1970
    Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
1971
1972
    uint32 maxPower = unitTarget->GetMaxPower(power);
1973
    if (maxPower == 0)
1974
        return;
1975
1976
    uint32 gain = CalculatePct(maxPower, damage);
1977
    m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
1978
}
1979
1980
void Spell::SendLoot(uint64 guid, LootType loottype)
1981
{
1982
    Player* player = m_caster->ToPlayer();
1983
    if (!player)
1984
        return;
1985
1986
    if (gameObjTarget)
1987
    {
1988
        // Players shouldn't be able to loot gameobjects that are currently despawned
1989
        if (!gameObjTarget->isSpawned() && !player->isGameMaster())
1990
        {
1991
            sLog->outError(LOG_FILTER_SPELLS_AURAS, "Possible hacking attempt: Player %s [guid: %u] tried to loot a gameobject [entry: %u id: %u] which is on respawn time without being in GM mode!",
1992
                            player->GetName().c_str(), player->GetGUIDLow(), gameObjTarget->GetEntry(), gameObjTarget->GetGUIDLow());
1993
            return;
1994
        }
1995
        // special case, already has GossipHello inside so return and avoid calling twice
1996
        if (gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_GOOBER)
1997
        {
1998
            gameObjTarget->Use(m_caster);
1999
            return;
2000
        }
2001
2002
        if (sScriptMgr->OnGossipHello(player, gameObjTarget))
2003
            return;
2004
2005
        if (gameObjTarget->AI()->GossipHello(player))
2006
            return;
2007
2008
        switch (gameObjTarget->GetGoType())
2009
        {
2010
            case GAMEOBJECT_TYPE_DOOR:
2011
            case GAMEOBJECT_TYPE_BUTTON:
2012
                gameObjTarget->UseDoorOrButton(0, false, player);
2013
                player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2014
                return;
2015
2016
            case GAMEOBJECT_TYPE_QUESTGIVER:
2017
                player->PrepareGossipMenu(gameObjTarget, gameObjTarget->GetGOInfo()->questgiver.gossipID);
2018
                player->SendPreparedGossip(gameObjTarget);
2019
                return;
2020
2021
            case GAMEOBJECT_TYPE_SPELL_FOCUS:
2022
                // triggering linked GO
2023
                if (uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2024
                    gameObjTarget->TriggeringLinkedGameObject(trapEntry, m_caster);
2025
                return;
2026
2027
            case GAMEOBJECT_TYPE_CHEST:
2028
                // TODO: possible must be moved to loot release (in different from linked triggering)
2029
                if (gameObjTarget->GetGOInfo()->chest.eventId)
2030
                {
2031
                    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId, gameObjTarget->GetDBTableGUIDLow());
2032
                    player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2033
                }
2034
2035
                // triggering linked GO
2036
                if (uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2037
                    gameObjTarget->TriggeringLinkedGameObject(trapEntry, m_caster);
2038
2039
                // Don't return, let loots been taken
2040
            default:
2041
                break;
2042
        }
2043
    }
2044
2045
    // Send loot
2046
    player->SendLoot(guid, loottype);
2047
}
2048
2049
void Spell::EffectOpenLock(SpellEffIndex effIndex)
2050
{
2051
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2052
        return;
2053
2054
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2055
    {
2056
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: Open Lock - No Player Caster!");
2057
        return;
2058
    }
2059
2060
    Player* player = m_caster->ToPlayer();
2061
2062
    uint32 lockId = 0;
2063
    uint64 guid = 0;
2064
2065
    // Get lockId
2066
    if (gameObjTarget)
2067
    {
2068
        GameObjectTemplate const* goInfo = gameObjTarget->GetGOInfo();
2069
        // Arathi Basin banner opening. // TODO: Verify correctness of this check
2070
        if ((goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune) ||
2071
            (goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK))
2072
        {
2073
            //CanUseBattlegroundObject() already called in CheckCast()
2074
            // in battleground check
2075
            if (Battleground* bg = player->GetBattleground())
2076
            {
2077
                bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2078
                return;
2079
            }
2080
        }
2081
        else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2082
        {
2083
            //CanUseBattlegroundObject() already called in CheckCast()
2084
            // in battleground check
2085
            if (Battleground* bg = player->GetBattleground())
2086
            {
2087
                if (bg->GetTypeID(true) == BATTLEGROUND_EY)
2088
                    bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2089
                return;
2090
            }
2091
        }
2092
        else if (m_spellInfo->Id == 1842 && gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_TRAP && gameObjTarget->GetOwner())
2093
        {
2094
            gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2095
            return;
2096
        }
2097
        // TODO: Add script for spell 41920 - Filling, becouse server it freze when use this spell
2098
        // handle outdoor pvp object opening, return true if go was registered for handling
2099
        // these objects must have been spawned by outdoorpvp!
2100
        else if (gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr->HandleOpenGo(player, gameObjTarget->GetGUID()))
2101
            return;
2102
        lockId = goInfo->GetLockId();
2103
        guid = gameObjTarget->GetGUID();
2104
    }
2105
    else if (itemTarget)
2106
    {
2107
        lockId = itemTarget->GetTemplate()->LockID;
2108
        guid = itemTarget->GetGUID();
2109
    }
2110
    else
2111
    {
2112
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: Open Lock - No GameObject/Item Target!");
2113
        return;
2114
    }
2115
2116
    SkillType skillId = SKILL_NONE;
2117
    int32 reqSkillValue = 0;
2118
    int32 skillValue;
2119
2120
    SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue);
2121
    if (res != SPELL_CAST_OK)
2122
    {
2123
        SendCastResult(res);
2124
        return;
2125
    }
2126
2127
    if (gameObjTarget)
2128
        SendLoot(guid, LOOT_SKINNING);
2129
    else if (itemTarget)
2130
        itemTarget->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED);
2131
2132
    // not allow use skill grow at item base open
2133
    if (!m_CastItem && skillId != SKILL_NONE)
2134
    {
2135
        // update skill if really known
2136
        if (uint32 pureSkillValue = player->GetPureSkillValue(skillId))
2137
        {
2138
            if (gameObjTarget)
2139
            {
2140
                // Allow one skill-up until respawned
2141
                if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) &&
2142
                    player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue))
2143
                    gameObjTarget->AddToSkillupList(player->GetGUIDLow());
2144
            }
2145
            else if (itemTarget)
2146
            {
2147
                // Do one skill-up
2148
                player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
2149
            }
2150
        }
2151
    }
2152
    ExecuteLogEffectOpenLock(effIndex, gameObjTarget ? (Object*)gameObjTarget : (Object*)itemTarget);
2153
}
2154
2155
void Spell::EffectSummonChangeItem(SpellEffIndex effIndex)
2156
{
2157
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
2158
        return;
2159
2160
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2161
        return;
2162
2163
    Player* player = m_caster->ToPlayer();
2164
2165
    // applied only to using item
2166
    if (!m_CastItem)
2167
        return;
2168
2169
    // ... only to item in own inventory/bank/equip_slot
2170
    if (m_CastItem->GetOwnerGUID() != player->GetGUID())
2171
        return;
2172
2173
    uint32 newitemid = m_spellInfo->Effects[effIndex].ItemType;
2174
    if (!newitemid)
2175
        return;
2176
2177
    uint16 pos = m_CastItem->GetPos();
2178
2179
    Item* pNewItem = Item::CreateItem(newitemid, 1, player);
2180
    if (!pNewItem)
2181
        return;
2182
2183
    for (uint8 j = PERM_ENCHANTMENT_SLOT; j <= TEMP_ENCHANTMENT_SLOT; ++j)
2184
        if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j)))
2185
            pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j)));
2186
2187
    if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
2188
    {
2189
        double lossPercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
2190
        player->DurabilityLoss(pNewItem, lossPercent);
2191
    }
2192
2193
    if (player->IsInventoryPos(pos))
2194
    {
2195
        ItemPosCountVec dest;
2196
        InventoryResult msg = player->CanStoreItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true);
2197
        if (msg == EQUIP_ERR_OK)
2198
        {
2199
            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
2200
2201
            // prevent crash at access and unexpected charges counting with item update queue corrupt
2202
            if (m_CastItem == m_targets.GetItemTarget())
2203
                m_targets.SetItemTarget(NULL);
2204
2205
            m_CastItem = NULL;
2206
2207
            player->StoreItem(dest, pNewItem, true);
2208
            return;
2209
        }
2210
    }
2211
    else if (player->IsBankPos(pos))
2212
    {
2213
        ItemPosCountVec dest;
2214
        uint8 msg = player->CanBankItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true);
2215
        if (msg == EQUIP_ERR_OK)
2216
        {
2217
            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
2218
2219
            // prevent crash at access and unexpected charges counting with item update queue corrupt
2220
            if (m_CastItem == m_targets.GetItemTarget())
2221
                m_targets.SetItemTarget(NULL);
2222
2223
            m_CastItem = NULL;
2224
2225
            player->BankItem(dest, pNewItem, true);
2226
            return;
2227
        }
2228
    }
2229
    else if (player->IsEquipmentPos(pos))
2230
    {
2231
        uint16 dest;
2232
2233
        player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
2234
2235
        uint8 msg = player->CanEquipItem(m_CastItem->GetSlot(), dest, pNewItem, true);
2236
2237
        if (msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CANT_DO_RIGHT_NOW)
2238
        {
2239
            if (msg == EQUIP_ERR_CANT_DO_RIGHT_NOW) dest = EQUIPMENT_SLOT_MAINHAND;
2240
2241
            // prevent crash at access and unexpected charges counting with item update queue corrupt
2242
            if (m_CastItem == m_targets.GetItemTarget())
2243
                m_targets.SetItemTarget(NULL);
2244
2245
            m_CastItem = NULL;
2246
2247
            player->EquipItem(dest, pNewItem, true);
2248
            player->AutoUnequipOffhandIfNeed();
2249
            return;
2250
        }
2251
    }
2252
2253
    // fail
2254
    delete pNewItem;
2255
}
2256
2257
void Spell::EffectProficiency(SpellEffIndex /*effIndex*/)
2258
{
2259
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
2260
        return;
2261
2262
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2263
        return;
2264
    Player* p_target = m_caster->ToPlayer();
2265
2266
    uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
2267
    if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask))
2268
    {
2269
        p_target->AddWeaponProficiency(subClassMask);
2270
        p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency());
2271
    }
2272
    if (m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask))
2273
    {
2274
        p_target->AddArmorProficiency(subClassMask);
2275
        p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency());
2276
    }
2277
}
2278
2279
void Spell::EffectSummonType(SpellEffIndex effIndex)
2280
{
2281
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
2282
        return;
2283
2284
    uint32 entry = m_spellInfo->Effects[effIndex].MiscValue;
2285
    if (!entry)
2286
        return;
2287
2288
    SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(m_spellInfo->Effects[effIndex].MiscValueB);
2289
    if (!properties)
2290
    {
2291
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectSummonType: Unhandled summon type %u", m_spellInfo->Effects[effIndex].MiscValueB);
2292
        return;
2293
    }
2294
2295
    if (!m_originalCaster)
2296
        return;
2297
2298
    int32 duration = m_spellInfo->GetDuration();
2299
    if (Player* modOwner = m_originalCaster->GetSpellModOwner())
2300
        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
2301
2302
    TempSummon* summon = NULL;
2303
2304
    // determine how many units should be summoned
2305
    uint32 numSummons;
2306
2307
    // some spells need to summon many units, for those spells number of summons is stored in effect value
2308
    // however so far noone found a generic check to find all of those (there's no related data in summonproperties.dbc
2309
    // and in spell attributes, possibly we need to add a table for those)
2310
    // so here's a list of MiscValueB values, which is currently most generic check
2311
    switch (properties->Id)
2312
    {
2313
        case 64:
2314
        case 61:
2315
        case 1101:
2316
        case 66:
2317
        case 648:
2318
        case 2301:
2319
        case 1061:
2320
        case 1261:
2321
        case 629:
2322
        case 181:
2323
        case 715:
2324
        case 1562:
2325
        case 833:
2326
        case 1161:
2327
            numSummons = (damage > 0) ? damage : 1;
2328
            break;
2329
        default:
2330
            numSummons = 1;
2331
            break;
2332
    }
2333
2334
    switch (properties->Category)
2335
    {
2336
        case SUMMON_CATEGORY_WILD:
2337
        case SUMMON_CATEGORY_ALLY:
2338
        case SUMMON_CATEGORY_UNK:
2339
            if (properties->Flags & 512)
2340
            {
2341
                SummonGuardian(effIndex, entry, properties, numSummons);
2342
                break;
2343
            }
2344
            switch (properties->Type)
2345
            {
2346
                case SUMMON_TYPE_PET:
2347
                case SUMMON_TYPE_GUARDIAN:
2348
                case SUMMON_TYPE_GUARDIAN2:
2349
                case SUMMON_TYPE_MINION:
2350
                    SummonGuardian(effIndex, entry, properties, numSummons);
2351
                    break;
2352
                // Summons a vehicle, but doesn't force anyone to enter it (see SUMMON_CATEGORY_VEHICLE)
2353
                case SUMMON_TYPE_VEHICLE:
2354
                case SUMMON_TYPE_VEHICLE2:
2355
                    summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
2356
                    break;
2357
                case SUMMON_TYPE_TOTEM:
2358
                {
2359
                    summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
2360
                    if (!summon || !summon->isTotem())
2361
                        return;
2362
2363
                    // Mana Tide Totem
2364
                    if (m_spellInfo->Id == 16190)
2365
                        damage = m_caster->CountPctFromMaxHealth(10);
2366
2367
                    if (damage)                                            // if not spell info, DB values used
2368
                    {
2369
                        summon->SetMaxHealth(damage);
2370
                        summon->SetHealth(damage);
2371
                    }
2372
                    break;
2373
                }
2374
                case SUMMON_TYPE_MINIPET:
2375
                {
2376
                    summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
2377
                    if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))
2378
                        return;
2379
2380
                    summon->SelectLevel(summon->GetCreatureTemplate());       // some summoned creaters have different from 1 DB data for level/hp
2381
                    summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag);
2382
2383
                    summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
2384
2385
                    summon->AI()->EnterEvadeMode();
2386
                    break;
2387
                }
2388
                default:
2389
                {
2390
                    float radius = m_spellInfo->Effects[effIndex].CalcRadius();
2391
2392
                    TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
2393
2394
                    for (uint32 count = 0; count < numSummons; ++count)
2395
                    {
2396
                        Position pos;
2397
                        if (count == 0)
2398
                            pos = *destTarget;
2399
                        else
2400
                            // randomize position for multiple summons
2401
                            m_caster->GetRandomPoint(*destTarget, radius, pos);
2402
2403
                        summon = m_originalCaster->SummonCreature(entry, pos, summonType, duration);
2404
                        if (!summon)
2405
                            continue;
2406
2407
                        if (properties->Category == SUMMON_CATEGORY_ALLY)
2408
                        {
2409
                            summon->SetOwnerGUID(m_originalCaster->GetGUID());
2410
                            summon->setFaction(m_originalCaster->getFaction());
2411
                            summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
2412
                        }
2413
2414
                        ExecuteLogEffectSummonObject(effIndex, summon);
2415
                    }
2416
                    return;
2417
                }
2418
            }//switch
2419
            break;
2420
        case SUMMON_CATEGORY_PET:
2421
            SummonGuardian(effIndex, entry, properties, numSummons);
2422
            break;
2423
        case SUMMON_CATEGORY_PUPPET:
2424
            summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id);
2425
            break;
2426
        case SUMMON_CATEGORY_VEHICLE:
2427
            // Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker
2428
            // to cast a ride vehicle spell on the summoned unit.
2429
            float x, y, z;
2430
            m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
2431
            summon = m_originalCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_caster, m_spellInfo->Id);
2432
            if (!summon || !summon->IsVehicle())
2433
                return;
2434
2435
            // The spell that this effect will trigger. It has SPELL_AURA_CONTROL_VEHICLE
2436
            uint32 spellId = VEHICLE_SPELL_RIDE_HARDCODED;
2437
            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].CalcValue());
2438
            if (spellInfo && spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
2439
                spellId = spellInfo->Id;
2440
2441
            // Hard coded enter vehicle spell
2442
            m_originalCaster->CastSpell(summon, spellId, true);
2443
2444
            uint32 faction = properties->Faction;
2445
            if (!faction)
2446
                faction = m_originalCaster->getFaction();
2447
2448
            summon->setFaction(faction);
2449
            break;
2450
    }
2451
2452
    if (summon)
2453
    {
2454
        summon->SetCreatorGUID(m_originalCaster->GetGUID());
2455
        ExecuteLogEffectSummonObject(effIndex, summon);
2456
    }
2457
}
2458
2459
void Spell::EffectLearnSpell(SpellEffIndex effIndex)
2460
{
2461
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2462
        return;
2463
2464
    if (!unitTarget)
2465
        return;
2466
2467
    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2468
    {
2469
        if (unitTarget->ToPet())
2470
            EffectLearnPetSpell(effIndex);
2471
        return;
2472
    }
2473
2474
    Player* player = unitTarget->ToPlayer();
2475
2476
    uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : m_spellInfo->Effects[effIndex].TriggerSpell;
2477
    player->learnSpell(spellToLearn, false);
2478
2479
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow());
2480
}
2481
2482
typedef std::list< std::pair<uint32, uint64> > DispelList;
2483
void Spell::EffectDispel(SpellEffIndex effIndex)
2484
{
2485
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2486
        return;
2487
2488
    if (!unitTarget)
2489
        return;
2490
2491
    // Create dispel mask by dispel type
2492
    uint32 dispel_type = m_spellInfo->Effects[effIndex].MiscValue;
2493
    uint32 dispelMask  = SpellInfo::GetDispelMask(DispelType(dispel_type));
2494
2495
    DispelChargesList dispel_list;
2496
    unitTarget->GetDispellableAuraList(m_caster, dispelMask, dispel_list);
2497
    if (dispel_list.empty())
2498
        return;
2499
2500
    // Ok if exist some buffs for dispel try dispel it
2501
    uint32 failCount = 0;
2502
    DispelChargesList success_list;
2503
    WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4);
2504
    // dispel N = damage buffs (or while exist buffs for dispel)
2505
    for (int32 count = 0; count < damage && !dispel_list.empty();)
2506
    {
2507
        // Random select buff for dispel
2508
        DispelChargesList::iterator itr = dispel_list.begin();
2509
        std::advance(itr, urand(0, dispel_list.size() - 1));
2510
2511
        int32 chance = itr->first->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster));
2512
        // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
2513
        if (!chance)
2514
        {
2515
            dispel_list.erase(itr);
2516
            continue;
2517
        }
2518
        else
2519
        {
2520
            if (roll_chance_i(chance))
2521
            {
2522
                bool alreadyListed = false;
2523
                for (DispelChargesList::iterator successItr = success_list.begin(); successItr != success_list.end(); ++successItr)
2524
                {
2525
                    if (successItr->first->GetId() == itr->first->GetId())
2526
                    {
2527
                        ++successItr->second;
2528
                        alreadyListed = true;
2529
                    }
2530
                }
2531
                if (!alreadyListed)
2532
                    success_list.push_back(std::make_pair(itr->first, 1));
2533
                --itr->second;
2534
                if (itr->second <= 0)
2535
                    dispel_list.erase(itr);
2536
            }
2537
            else
2538
            {
2539
                if (!failCount)
2540
                {
2541
                    // Failed to dispell
2542
                    dataFail << uint64(m_caster->GetGUID());            // Caster GUID
2543
                    dataFail << uint64(unitTarget->GetGUID());          // Victim GUID
2544
                    dataFail << uint32(m_spellInfo->Id);                // dispel spell id
2545
                }
2546
                ++failCount;
2547
                dataFail << uint32(itr->first->GetId());                         // Spell Id
2548
            }
2549
            ++count;
2550
        }
2551
    }
2552
2553
    if (failCount)
2554
        m_caster->SendMessageToSet(&dataFail, true);
2555
2556
    if (success_list.empty())
2557
        return;
2558
2559
    WorldPacket dataSuccess(SMSG_SPELLDISPELLOG, 8+8+4+1+4+success_list.size()*5);
2560
    // Send packet header
2561
    dataSuccess.append(unitTarget->GetPackGUID());         // Victim GUID
2562
    dataSuccess.append(m_caster->GetPackGUID());           // Caster GUID
2563
    dataSuccess << uint32(m_spellInfo->Id);                // dispel spell id
2564
    dataSuccess << uint8(0);                               // not used
2565
    dataSuccess << uint32(success_list.size());            // count
2566
    for (DispelChargesList::iterator itr = success_list.begin(); itr != success_list.end(); ++itr)
2567
    {
2568
        // Send dispelled spell info
2569
        dataSuccess << uint32(itr->first->GetId());              // Spell Id
2570
        dataSuccess << uint8(0);                        // 0 - dispelled !=0 cleansed
2571
        unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), m_spellInfo->Id, itr->first->GetCasterGUID(), m_caster, itr->second);
2572
    }
2573
    m_caster->SendMessageToSet(&dataSuccess, true);
2574
2575
    // On success dispel
2576
    // Devour Magic
2577
    if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC)
2578
    {
2579
        int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue();
2580
        m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true);
2581
        // Glyph of Felhunter
2582
        if (Unit* owner = m_caster->GetOwner())
2583
            if (owner->GetAura(56249))
2584
                owner->CastCustomSpell(owner, 19658, &heal_amount, NULL, NULL, true);
2585
    }
2586
}
2587
2588
void Spell::EffectDualWield(SpellEffIndex /*effIndex*/)
2589
{
2590
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2591
        return;
2592
2593
    unitTarget->SetCanDualWield(true);
2594
    if (unitTarget->GetTypeId() == TYPEID_UNIT)
2595
        unitTarget->ToCreature()->UpdateDamagePhysical(OFF_ATTACK);
2596
}
2597
2598
void Spell::EffectPull(SpellEffIndex effIndex)
2599
{
2600
    // TODO: create a proper pull towards distract spell center for distract
2601
    EffectNULL(effIndex);
2602
}
2603
2604
void Spell::EffectDistract(SpellEffIndex /*effIndex*/)
2605
{
2606
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2607
        return;
2608
2609
    // Check for possible target
2610
    if (!unitTarget || unitTarget->isInCombat())
2611
        return;
2612
2613
    // target must be OK to do this
2614
    if (unitTarget->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING))
2615
        return;
2616
2617
    unitTarget->SetFacingTo(unitTarget->GetAngle(destTarget));
2618
    unitTarget->ClearUnitState(UNIT_STATE_MOVING);
2619
2620
    if (unitTarget->GetTypeId() == TYPEID_UNIT)
2621
        unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
2622
}
2623
2624
void Spell::EffectPickPocket(SpellEffIndex /*effIndex*/)
2625
{
2626
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2627
        return;
2628
2629
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2630
        return;
2631
2632
    // victim must be creature and attackable
2633
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget))
2634
        return;
2635
2636
    // victim have to be alive and humanoid or undead
2637
    if (unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
2638
        m_caster->ToPlayer()->SendLoot(unitTarget->GetGUID(), LOOT_PICKPOCKETING);
2639
}
2640
2641
void Spell::EffectAddFarsight(SpellEffIndex effIndex)
2642
{
2643
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
2644
        return;
2645
2646
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2647
        return;
2648
2649
    float radius = m_spellInfo->Effects[effIndex].CalcRadius();
2650
    int32 duration = m_spellInfo->GetDuration();
2651
    // Caster not in world, might be spell triggered from aura removal
2652
    if (!m_caster->IsInWorld())
2653
        return;
2654
2655
    DynamicObject* dynObj = new DynamicObject(true);
2656
    if (!dynObj->CreateDynamicObject(sObjectMgr->GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS))
2657
    {
2658
        delete dynObj;
2659
        return;
2660
    }
2661
2662
    dynObj->SetDuration(duration);
2663
    dynObj->SetCasterViewpoint();
2664
}
2665
2666
void Spell::EffectUntrainTalents(SpellEffIndex /*effIndex*/)
2667
{
2668
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2669
        return;
2670
2671
    if (!unitTarget || m_caster->GetTypeId() == TYPEID_PLAYER)
2672
        return;
2673
2674
    if (uint64 guid = m_caster->GetGUID()) // the trainer is the caster
2675
        unitTarget->ToPlayer()->SendTalentWipeConfirm(guid);
2676
}
2677
2678
void Spell::EffectTeleUnitsFaceCaster(SpellEffIndex effIndex)
2679
{
2680
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2681
        return;
2682
2683
    if (!unitTarget)
2684
        return;
2685
2686
    if (unitTarget->isInFlight())
2687
        return;
2688
2689
    float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
2690
2691
    float fx, fy, fz;
2692
    m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
2693
2694
    unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget == m_caster);
2695
}
2696
2697
void Spell::EffectLearnSkill(SpellEffIndex effIndex)
2698
{
2699
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2700
        return;
2701
2702
    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2703
        return;
2704
2705
    if (damage < 0)
2706
        return;
2707
2708
    uint32 skillid = m_spellInfo->Effects[effIndex].MiscValue;
2709
    uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid);
2710
    unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), skillval?skillval:1, damage*75);
2711
}
2712
2713
void Spell::EffectAddHonor(SpellEffIndex /*effIndex*/)
2714
{
2715
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2716
        return;
2717
2718
    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
2719
        return;
2720
2721
    // not scale value for item based reward (/10 value expected)
2722
    if (m_CastItem)
2723
    {
2724
        unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage/10);
2725
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(), unitTarget->ToPlayer()->GetGUIDLow());
2726
        return;
2727
    }
2728
2729
    // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
2730
    if (damage <= 50)
2731
    {
2732
        uint32 honor_reward = Trinity::Honor::hk_honor_at_level(unitTarget->getLevel(), float(damage));
2733
        unitTarget->ToPlayer()->RewardHonor(NULL, 1, honor_reward);
2734
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, unitTarget->ToPlayer()->GetGUIDLow());
2735
    }
2736
    else
2737
    {
2738
        //maybe we have correct honor_gain in damage already
2739
        unitTarget->ToPlayer()->RewardHonor(NULL, 1, damage);
2740
        sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, unitTarget->ToPlayer()->GetGUIDLow());
2741
    }
2742
}
2743
2744
void Spell::EffectTradeSkill(SpellEffIndex /*effIndex*/)
2745
{
2746
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
2747
        return;
2748
2749
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2750
        return;
2751
    // uint32 skillid =  m_spellInfo->Effects[i].MiscValue;
2752
    // uint16 skillmax = unitTarget->ToPlayer()->(skillid);
2753
    // m_caster->ToPlayer()->SetSkill(skillid, skillval?skillval:1, skillmax+75);
2754
}
2755
2756
void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex)
2757
{
2758
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2759
        return;
2760
2761
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2762
        return;
2763
    if (!itemTarget)
2764
        return;
2765
2766
    Player* p_caster = (Player*)m_caster;
2767
2768
    // Handle vellums
2769
    if (itemTarget->IsWeaponVellum() || itemTarget->IsArmorVellum())
2770
    {
2771
        // destroy one vellum from stack
2772
        uint32 count = 1;
2773
        p_caster->DestroyItemCount(itemTarget, count, true);
2774
        unitTarget=p_caster;
2775
        // and add a scroll
2776
        DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType);
2777
        itemTarget=NULL;
2778
        m_targets.SetItemTarget(NULL);
2779
    }
2780
    else
2781
    {
2782
        // do not increase skill if vellum used
2783
        if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST))
2784
            p_caster->UpdateCraftSkill(m_spellInfo->Id);
2785
2786
        uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
2787
        if (!enchant_id)
2788
            return;
2789
2790
        SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
2791
        if (!pEnchant)
2792
            return;
2793
2794
        // item can be in trade slot and have owner diff. from caster
2795
        Player* item_owner = itemTarget->GetOwner();
2796
        if (!item_owner)
2797
            return;
2798
2799
        if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
2800
        {
2801
            sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
2802
                p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
2803
                itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(),
2804
                item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId());
2805
        }
2806
2807
        // remove old enchanting before applying new if equipped
2808
        item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, false);
2809
2810
        itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
2811
2812
        // add new enchanting if equipped
2813
        item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, true);
2814
2815
        item_owner->RemoveTradeableItem(itemTarget);
2816
        itemTarget->ClearSoulboundTradeable(item_owner);
2817
    }
2818
}
2819
2820
void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex)
2821
{
2822
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2823
        return;
2824
2825
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2826
        return;
2827
    if (!itemTarget)
2828
        return;
2829
2830
    Player* p_caster = (Player*)m_caster;
2831
2832
    uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
2833
    if (!enchant_id)
2834
        return;
2835
2836
    SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
2837
    if (!pEnchant)
2838
        return;
2839
2840
    // support only enchantings with add socket in this slot
2841
    {
2842
        bool add_socket = false;
2843
        for (uint8 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
2844
        {
2845
            if (pEnchant->type[i] == ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET)
2846
            {
2847
                add_socket = true;
2848
                break;
2849
            }
2850
        }
2851
        if (!add_socket)
2852
        {
2853
            sLog->outError(LOG_FILTER_SPELLS_AURAS, "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.",
2854
                m_spellInfo->Id, SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC, ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET);
2855
            return;
2856
        }
2857
    }
2858
2859
    // item can be in trade slot and have owner diff. from caster
2860
    Player* item_owner = itemTarget->GetOwner();
2861
    if (!item_owner)
2862
        return;
2863
2864
    if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
2865
    {
2866
        sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
2867
            p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
2868
            itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(),
2869
            item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId());
2870
    }
2871
2872
    // remove old enchanting before applying new if equipped
2873
    item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, false);
2874
2875
    itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0);
2876
2877
    // add new enchanting if equipped
2878
    item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, true);
2879
2880
    item_owner->RemoveTradeableItem(itemTarget);
2881
    itemTarget->ClearSoulboundTradeable(item_owner);
2882
}
2883
2884
void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex)
2885
{
2886
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
2887
        return;
2888
2889
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2890
        return;
2891
2892
    Player* p_caster = (Player*)m_caster;
2893
2894
    // Rockbiter Weapon apply to both weapon
2895
    if (!itemTarget)
2896
        return;
2897
    if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x400000)
2898
    {
2899
        uint32 spell_id = 0;
2900
2901
        // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
2902
        // Note: damage calculated (correctly) with rounding int32(float(v)) but
2903
        // RW enchantments applied damage int32(float(v)+0.5), this create  0..1 difference sometime
2904
        switch (damage)
2905
        {
2906
            // Rank 1
2907
            case  2: spell_id = 36744; break;               //  0% [ 7% == 2, 14% == 2, 20% == 2]
2908
            // Rank 2
2909
            case  4: spell_id = 36753; break;               //  0% [ 7% == 4, 14% == 4]
2910
            case  5: spell_id = 36751; break;               // 20%
2911
            // Rank 3
2912
            case  6: spell_id = 36754; break;               //  0% [ 7% == 6, 14% == 6]
2913
            case  7: spell_id = 36755; break;               // 20%
2914
            // Rank 4
2915
            case  9: spell_id = 36761; break;               //  0% [ 7% == 6]
2916
            case 10: spell_id = 36758; break;               // 14%
2917
            case 11: spell_id = 36760; break;               // 20%
2918
            default:
2919
                sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW", damage);
2920
                return;
2921
        }
2922
2923
        SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
2924
        if (!spellInfo)
2925
        {
2926
            sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
2927
            return;
2928
2929
        }
2930
2931
        for (int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
2932
        {
2933
            if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
2934
            {
2935
                if (item->IsFitToSpellRequirements(m_spellInfo))
2936
                {
2937
                    Spell* spell = new Spell(m_caster, spellInfo, TRIGGERED_FULL_MASK);
2938
                    SpellCastTargets targets;
2939
                    targets.SetItemTarget(item);
2940
                    spell->prepare(&targets);
2941
                }
2942
            }
2943
        }
2944
        return;
2945
    }
2946
    if (!itemTarget)
2947
        return;
2948
2949
    uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
2950
2951
    if (!enchant_id)
2952
    {
2953
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id", m_spellInfo->Id, effIndex);
2954
        return;
2955
    }
2956
2957
    SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
2958
    if (!pEnchant)
2959
    {
2960
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ", m_spellInfo->Id, effIndex, enchant_id);
2961
        return;
2962
    }
2963
2964
    // select enchantment duration
2965
    uint32 duration;
2966
2967
    // rogue family enchantments exception by duration
2968
    if (m_spellInfo->Id == 38615)
2969
        duration = 1800;                                    // 30 mins
2970
    // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
2971
    else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
2972
        duration = 3600;                                    // 1 hour
2973
    // shaman family enchantments
2974
    else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN)
2975
        duration = 1800;                                    // 30 mins
2976
    // other cases with this SpellVisual already selected
2977
    else if (m_spellInfo->SpellVisual[0] == 215)
2978
        duration = 1800;                                    // 30 mins
2979
    // some fishing pole bonuses except Glow Worm which lasts full hour
2980
    else if (m_spellInfo->SpellVisual[0] == 563 && m_spellInfo->Id != 64401)
2981
        duration = 600;                                     // 10 mins
2982
    // shaman rockbiter enchantments
2983
    else if (m_spellInfo->SpellVisual[0] == 0)
2984
        duration = 1800;                                    // 30 mins
2985
    else if (m_spellInfo->Id == 29702)
2986
        duration = 300;                                     // 5 mins
2987
    else if (m_spellInfo->Id == 37360)
2988
        duration = 300;                                     // 5 mins
2989
    // default case
2990
    else
2991
        duration = 3600;                                    // 1 hour
2992
2993
    // item can be in trade slot and have owner diff. from caster
2994
    Player* item_owner = itemTarget->GetOwner();
2995
    if (!item_owner)
2996
        return;
2997
2998
    if (item_owner != p_caster && !AccountMgr::IsPlayerAccount(p_caster->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE))
2999
    {
3000
        sLog->outCommand(p_caster->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3001
            p_caster->GetName().c_str(), p_caster->GetSession()->GetAccountId(),
3002
            itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(),
3003
            item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId());
3004
    }
3005
3006
    // remove old enchanting before applying new if equipped
3007
    item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, false);
3008
3009
    itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0);
3010
3011
    // add new enchanting if equipped
3012
    item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true);
3013
}
3014
3015
void Spell::EffectTameCreature(SpellEffIndex /*effIndex*/)
3016
{
3017
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
3018
        return;
3019
3020
    if (m_caster->GetPetGUID())
3021
        return;
3022
3023
    if (!unitTarget)
3024
        return;
3025
3026
    if (unitTarget->GetTypeId() != TYPEID_UNIT)
3027
        return;
3028
3029
    Creature* creatureTarget = unitTarget->ToCreature();
3030
3031
    if (creatureTarget->isPet())
3032
        return;
3033
3034
    if (m_caster->getClass() != CLASS_HUNTER)
3035
        return;
3036
3037
    // cast finish successfully
3038
    //SendChannelUpdate(0);
3039
    finish();
3040
3041
    Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id);
3042
    if (!pet)                                               // in very specific state like near world end/etc.
3043
        return;
3044
3045
    // "kill" original creature
3046
    creatureTarget->DespawnOrUnsummon();
3047
3048
    uint8 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel();
3049
3050
    // prepare visual effect for levelup
3051
    pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
3052
3053
    // add to world
3054
    pet->GetMap()->AddToMap(pet->ToCreature());
3055
3056
    // visual effect for levelup
3057
    pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
3058
3059
    // caster have pet now
3060
    m_caster->SetMinion(pet, true);
3061
3062
    pet->InitTalentForLevel();
3063
3064
    if (m_caster->GetTypeId() == TYPEID_PLAYER)
3065
    {
3066
        pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3067
        m_caster->ToPlayer()->PetSpellInitialize();
3068
    }
3069
}
3070
3071
void Spell::EffectSummonPet(SpellEffIndex effIndex)
3072
{
3073
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
3074
        return;
3075
3076
    Player* owner = NULL;
3077
    if (m_originalCaster)
3078
    {
3079
        owner = m_originalCaster->ToPlayer();
3080
        if (!owner && m_originalCaster->ToCreature()->isTotem())
3081
            owner = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself();
3082
    }
3083
3084
    uint32 petentry = m_spellInfo->Effects[effIndex].MiscValue;
3085
3086
    if (!owner)
3087
    {
3088
        SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67);
3089
        if (properties)
3090
            SummonGuardian(effIndex, petentry, properties, 1);
3091
        return;
3092
    }
3093
3094
    Pet* OldSummon = owner->GetPet();
3095
3096
    // if pet requested type already exist
3097
    if (OldSummon)
3098
    {
3099
        if (petentry == 0 || OldSummon->GetEntry() == petentry)
3100
        {
3101
            // pet in corpse state can't be summoned
3102
            if (OldSummon->isDead())
3103
                return;
3104
3105
            ASSERT(OldSummon->GetMap() == owner->GetMap());
3106
3107
            //OldSummon->GetMap()->Remove(OldSummon->ToCreature(), false);
3108
3109
            float px, py, pz;
3110
            owner->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
3111
3112
            OldSummon->NearTeleportTo(px, py, pz, OldSummon->GetOrientation());
3113
            //OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
3114
            //OldSummon->SetMap(owner->GetMap());
3115
            //owner->GetMap()->Add(OldSummon->ToCreature());
3116
3117
            if (owner->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled())
3118
                owner->ToPlayer()->PetSpellInitialize();
3119
3120
            return;
3121
        }
3122
3123
        if (owner->GetTypeId() == TYPEID_PLAYER)
3124
            owner->ToPlayer()->RemovePet(OldSummon, (OldSummon->getPetType() == HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT), false);
3125
        else
3126
            return;
3127
    }
3128
3129
    float x, y, z;
3130
    owner->GetClosePoint(x, y, z, owner->GetObjectSize());
3131
    Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0);
3132
    if (!pet)
3133
        return;
3134
3135
    if (m_caster->GetTypeId() == TYPEID_UNIT)
3136
    {
3137
        if (m_caster->ToCreature()->isTotem())
3138
            pet->SetReactState(REACT_AGGRESSIVE);
3139
        else
3140
            pet->SetReactState(REACT_DEFENSIVE);
3141
    }
3142
3143
    pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3144
3145
    // generate new name for summon pet
3146
    std::string new_name=sObjectMgr->GeneratePetName(petentry);
3147
    if (!new_name.empty())
3148
        pet->SetName(new_name);
3149
3150
    ExecuteLogEffectSummonObject(effIndex, pet);
3151
}
3152
3153
void Spell::EffectLearnPetSpell(SpellEffIndex effIndex)
3154
{
3155
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
3156
        return;
3157
3158
    if (!unitTarget)
3159
        return;
3160
3161
    if (unitTarget->ToPlayer())
3162
    {
3163
        EffectLearnSpell(effIndex);
3164
        return;
3165
    }
3166
    Pet* pet = unitTarget->ToPet();
3167
    if (!pet)
3168
        return;
3169
3170
    SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].TriggerSpell);
3171
    if (!learn_spellproto)
3172
        return;
3173
3174
    pet->learnSpell(learn_spellproto->Id);
3175
    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3176
    pet->GetOwner()->PetSpellInitialize();
3177
}
3178
3179
void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
3180
{
3181
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
3182
        return;
3183
3184
    if (!unitTarget)
3185
        return;
3186
3187
    // this effect use before aura Taunt apply for prevent taunt already attacking target
3188
    // for spell as marked "non effective at already attacking target"
3189
    if (!unitTarget || !unitTarget->CanHaveThreatList()
3190
        || unitTarget->getVictim() == m_caster)
3191
    {
3192
        SendCastResult(SPELL_FAILED_DONT_REPORT);
3193
        return;
3194
    }
3195
3196
    if (m_spellInfo->Id == 62124)
3197
        m_caster->CastSpell(unitTarget, 67485, true);
3198
3199
    // Also use this effect to set the taunter's threat to the taunted creature's highest value
3200
    if (unitTarget->getThreatManager().getCurrentVictim())
3201
    {
3202
        float myThreat = unitTarget->getThreatManager().getThreat(m_caster);
3203
        float itsThreat = unitTarget->getThreatManager().getCurrentVictim()->getThreat();
3204
        if (itsThreat > myThreat)
3205
            unitTarget->getThreatManager().addThreat(m_caster, itsThreat - myThreat);
3206
    }
3207
3208
    //Set aggro victim to caster
3209
    if (!unitTarget->getThreatManager().getOnlineContainer().empty())
3210
        if (HostileReference* forcedVictim = unitTarget->getThreatManager().getOnlineContainer().getReferenceByTarget(m_caster))
3211
            unitTarget->getThreatManager().setCurrentVictim(forcedVictim);
3212
3213
    if (unitTarget->ToCreature()->IsAIEnabled && !unitTarget->ToCreature()->HasReactState(REACT_PASSIVE))
3214
        unitTarget->ToCreature()->AI()->AttackStart(m_caster);
3215
}
3216
3217
void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
3218
{
3219
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
3220
        return;
3221
3222
    if (!unitTarget || !unitTarget->isAlive())
3223
        return;
3224
3225
    // multiple weapon dmg effect workaround
3226
    // execute only the last weapon damage
3227
    // and handle all effects at once
3228
    for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
3229
    {
3230
        switch (m_spellInfo->Effects[j].Effect)
3231
        {
3232
            case SPELL_EFFECT_WEAPON_DAMAGE:
3233
            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
3234
            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
3235
            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
3236
                return;     // we must calculate only at last weapon effect
3237
            break;
3238
        }
3239
    }
3240
3241
    // some spell specific modifiers
3242
    float totalDamagePercentMod  = 1.0f;                    // applied to final bonus+weapon damage
3243
    int32 fixed_bonus = 0;
3244
    int32 spell_bonus = 0;                                  // bonus specific for spell
3245
3246
    switch (m_spellInfo->SpellFamilyName)
3247
    {
3248
        case SPELLFAMILY_GENERIC:
3249
        {
3250
            switch (m_spellInfo->Id)
3251
            {
3252
                case 69055:     // Saber Lash
3253
                case 70814:     // Saber Lash
3254
                {
3255
                    uint32 count = 0;
3256
                    for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3257
                        if (ihit->effectMask & (1 << effIndex))
3258
                            ++count;
3259
3260
                    totalDamagePercentMod /= count;
3261
                    break;
3262
                }
3263
            }
3264
            break;
3265
        }
3266
        case SPELLFAMILY_WARRIOR:
3267
        {
3268
            // Devastate (player ones)
3269
            if (m_spellInfo->SpellFamilyFlags[1] & 0x40)
3270
            {
3271
                // Player can apply only 58567 Sunder Armor effect.
3272
                bool needCast = !unitTarget->HasAura(58567, m_caster->GetGUID());
3273
                if (needCast)
3274
                    m_caster->CastSpell(unitTarget, 58567, true);
3275
3276
                if (Aura* aur = unitTarget->GetAura(58567, m_caster->GetGUID()))
3277
                {
3278
                    // 58388 - Glyph of Devastate dummy aura.
3279
                    if (int32 num = (needCast ? 0 : 1) + (m_caster->HasAura(58388) ? 1 : 0))
3280
                        aur->ModStackAmount(num);
3281
                    fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(2, unitTarget);
3282
                }
3283
            }
3284
            if (m_spellInfo->SpellFamilyFlags[0] & 0x8000000) // Mocking Blow
3285
            {
3286
                if (unitTarget->IsImmunedToSpellEffect(m_spellInfo,EFFECT_1) || unitTarget->GetTypeId() == TYPEID_PLAYER)
3287
                {
3288
                    m_damage = 0;
3289
                    return;
3290
                }
3291
            }
3292
            break;
3293
        }
3294
        case SPELLFAMILY_ROGUE:
3295
        {
3296
            // Fan of Knives, Hemorrhage, Ghostly Strike
3297
            if ((m_spellInfo->SpellFamilyFlags[1] & 0x40000)
3298
                || (m_spellInfo->SpellFamilyFlags[0] & 0x6000000))
3299
            {
3300
                // Hemorrhage
3301
                if (m_spellInfo->SpellFamilyFlags[0] & 0x2000000)
3302
                {
3303
                    if (m_caster->GetTypeId() == TYPEID_PLAYER)
3304
                        m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
3305
                }
3306
                // 50% more damage with daggers
3307
                if (m_caster->GetTypeId() == TYPEID_PLAYER)
3308
                    if (Item* item = m_caster->ToPlayer()->GetWeaponForAttack(m_attackType, true))
3309
                        if (item->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
3310
                            totalDamagePercentMod *= 1.5f;
3311
            }
3312
            // Mutilate (for each hand)
3313
            else if (m_spellInfo->SpellFamilyFlags[1] & 0x6)
3314
            {
3315
                bool found = false;
3316
                // fast check
3317
                if (unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON, m_spellInfo, m_caster))
3318
                    found = true;
3319
                // full aura scan
3320
                else
3321
                {
3322
                    Unit::AuraApplicationMap const& auras = unitTarget->GetAppliedAuras();
3323
                    for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3324
                    {
3325
                        if (itr->second->GetBase()->GetSpellInfo()->Dispel == DISPEL_POISON)
3326
                        {
3327
                            found = true;
3328
                            break;
3329
                        }
3330
                    }
3331
                }
3332
3333
                if (found)
3334
                    totalDamagePercentMod *= 1.2f;          // 120% if poisoned
3335
            }
3336
            break;
3337
        }
3338
        case SPELLFAMILY_PALADIN:
3339
        {
3340
            // Seal of Command Unleashed
3341
            if (m_spellInfo->Id == 20467)
3342
            {
3343
                spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
3344
                spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
3345
            }
3346
            break;
3347
        }
3348
        case SPELLFAMILY_SHAMAN:
3349
        {
3350
            // Skyshatter Harness item set bonus
3351
            // Stormstrike
3352
            if (AuraEffect* aurEff = m_caster->IsScriptOverriden(m_spellInfo, 5634))
3353
                m_caster->CastSpell(m_caster, 38430, true, NULL, aurEff);
3354
            break;
3355
        }
3356
        case SPELLFAMILY_DRUID:
3357
        {
3358
            // Mangle (Cat): CP
3359
            if (m_spellInfo->SpellFamilyFlags[1] & 0x400)
3360
            {
3361
                if (m_caster->GetTypeId() == TYPEID_PLAYER)
3362
                    m_caster->ToPlayer()->AddComboPoints(unitTarget, 1, this);
3363
            }
3364
            // Shred, Maul - Rend and Tear
3365
            else if (m_spellInfo->SpellFamilyFlags[0] & 0x00008800 && unitTarget->HasAuraState(AURA_STATE_BLEEDING))
3366
            {
3367
                if (AuraEffect const* rendAndTear = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 0))
3368
                    AddPct(totalDamagePercentMod, rendAndTear->GetAmount());
3369
            }
3370
            break;
3371
        }
3372
        case SPELLFAMILY_HUNTER:
3373
        {
3374
            // Kill Shot - bonus damage from Ranged Attack Power
3375
            if (m_spellInfo->SpellFamilyFlags[1] & 0x800000)
3376
                spell_bonus += int32(0.4f * m_caster->GetTotalAttackPowerValue(RANGED_ATTACK));
3377
            break;
3378
        }
3379
        case SPELLFAMILY_DEATHKNIGHT:
3380
        {
3381
            // Plague Strike
3382
            if (m_spellInfo->SpellFamilyFlags[0] & 0x1)
3383
            {
3384
                // Glyph of Plague Strike
3385
                if (AuraEffect const* aurEff = m_caster->GetAuraEffect(58657, EFFECT_0))
3386
                    AddPct(totalDamagePercentMod, aurEff->GetAmount());
3387
                break;
3388
            }
3389
            // Blood Strike
3390
            if (m_spellInfo->SpellFamilyFlags[0] & 0x400000)
3391
            {
3392
                float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f;
3393
                // Death Knight T8 Melee 4P Bonus
3394
                if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
3395
                    AddPct(bonusPct, aurEff->GetAmount());
3396
                AddPct(totalDamagePercentMod, bonusPct);
3397
3398
                // Glyph of Blood Strike
3399
                if (m_caster->GetAuraEffect(59332, EFFECT_0))
3400
                    if (unitTarget->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED))
3401
                       AddPct(totalDamagePercentMod, 20);
3402
                break;
3403
            }
3404
            // Death Strike
3405
            if (m_spellInfo->SpellFamilyFlags[0] & 0x10)
3406
            {
3407
                // Glyph of Death Strike
3408
                if (AuraEffect const* aurEff = m_caster->GetAuraEffect(59336, EFFECT_0))
3409
                    if (uint32 runic = std::min<uint32>(m_caster->GetPower(POWER_RUNIC_POWER), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()))
3410
                        AddPct(totalDamagePercentMod, runic);
3411
                break;
3412
            }
3413
            // Obliterate (12.5% more damage per disease)
3414
            if (m_spellInfo->SpellFamilyFlags[1] & 0x20000)
3415
            {
3416
                bool consumeDiseases = true;
3417
                // Annihilation
3418
                if (AuraEffect const* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2710, EFFECT_0))
3419
                    // Do not consume diseases if roll sucesses
3420
                    if (roll_chance_i(aurEff->GetAmount()))
3421
                        consumeDiseases = false;
3422
3423
                float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), consumeDiseases) / 2.0f;
3424
                // Death Knight T8 Melee 4P Bonus
3425
                if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
3426
                    AddPct(bonusPct, aurEff->GetAmount());
3427
                AddPct(totalDamagePercentMod, bonusPct);
3428
                break;
3429
            }
3430
            // Blood-Caked Strike - Blood-Caked Blade
3431
            if (m_spellInfo->SpellIconID == 1736)
3432
            {
3433
                AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) * 12.5f);
3434
                break;
3435
            }
3436
            // Heart Strike
3437
            if (m_spellInfo->SpellFamilyFlags[0] & 0x1000000)
3438
            {
3439
                float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID());
3440
                // Death Knight T8 Melee 4P Bonus
3441
                if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0))
3442
                    AddPct(bonusPct, aurEff->GetAmount());
3443
3444
                AddPct(totalDamagePercentMod, bonusPct);
3445
                break;
3446
            }
3447
            break;
3448
        }
3449
    }
3450
3451
    bool normalized = false;
3452
    float weaponDamagePercentMod = 1.0f;
3453
    for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
3454
    {
3455
        switch (m_spellInfo->Effects[j].Effect)
3456
        {
3457
            case SPELL_EFFECT_WEAPON_DAMAGE:
3458
            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
3459
                fixed_bonus += CalculateDamage(j, unitTarget);
3460
                break;
3461
            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
3462
                fixed_bonus += CalculateDamage(j, unitTarget);
3463
                normalized = true;
3464
                break;
3465
            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
3466
                ApplyPct(weaponDamagePercentMod, CalculateDamage(j, unitTarget));
3467
                break;
3468
            default:
3469
                break;                                      // not weapon damage effect, just skip
3470
        }
3471
    }
3472
3473
    // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
3474
    if (fixed_bonus || spell_bonus)
3475
    {
3476
        UnitMods unitMod;
3477
        switch (m_attackType)
3478
        {
3479
            default:
3480
            case BASE_ATTACK:   unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
3481
            case OFF_ATTACK:    unitMod = UNIT_MOD_DAMAGE_OFFHAND;  break;
3482
            case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED;   break;
3483
        }
3484
3485
        float weapon_total_pct = 1.0f;
3486
        if (m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NORMAL)
3487
             weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
3488
3489
        if (fixed_bonus)
3490
            fixed_bonus = int32(fixed_bonus * weapon_total_pct);
3491
        if (spell_bonus)
3492
            spell_bonus = int32(spell_bonus * weapon_total_pct);
3493
    }
3494
3495
    int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true);
3496
3497
    // Sequence is important
3498
    for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
3499
    {
3500
        // We assume that a spell have at most one fixed_bonus
3501
        // and at most one weaponDamagePercentMod
3502
        switch (m_spellInfo->Effects[j].Effect)
3503
        {
3504
            case SPELL_EFFECT_WEAPON_DAMAGE:
3505
            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
3506
            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
3507
                weaponDamage += fixed_bonus;
3508
                break;
3509
            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
3510
                weaponDamage = int32(weaponDamage* weaponDamagePercentMod);
3511
            default:
3512
                break;                                      // not weapon damage effect, just skip
3513
        }
3514
    }
3515
3516
    if (spell_bonus)
3517
        weaponDamage += spell_bonus;
3518
3519
    if (totalDamagePercentMod != 1.0f)
3520
        weaponDamage = int32(weaponDamage* totalDamagePercentMod);
3521
3522
    // prevent negative damage
3523
    uint32 eff_damage(std::max(weaponDamage, 0));
3524
3525
    // Add melee damage bonuses (also check for negative)
3526
    uint32 damage = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo);
3527
3528
    m_damage += unitTarget->MeleeDamageBonusTaken(m_caster, damage, m_attackType, m_spellInfo);
3529
}
3530
3531
void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
3532
{
3533
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
3534
        return;
3535
3536
    if (!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
3537
        return;
3538
3539
    if (!unitTarget->CanHaveThreatList())
3540
        return;
3541
3542
    unitTarget->AddThreat(m_caster, float(damage));
3543
}
3544
3545
void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
3546
{
3547
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
3548
        return;
3549
3550
    if (!unitTarget || !unitTarget->isAlive())
3551
        return;
3552
3553
    int32 addhealth = 0;
3554
3555
    // damage == 0 - heal for caster max health
3556
    if (damage == 0)
3557
        addhealth = m_caster->GetMaxHealth();
3558
    else
3559
        addhealth = unitTarget->GetMaxHealth() - unitTarget->GetHealth();
3560
3561
    m_healing += addhealth;
3562
}
3563
3564
void Spell::EffectInterruptCast(SpellEffIndex effIndex)
3565
{
3566
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
3567
        return;
3568
3569
    if (!unitTarget || !unitTarget->isAlive())
3570
        return;
3571
3572
    // TODO: not all spells that used this effect apply cooldown at school spells
3573
    // also exist case: apply cooldown to interrupted cast only and to all spells
3574
    // there is no CURRENT_AUTOREPEAT_SPELL spells that can be interrupted
3575
    for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_AUTOREPEAT_SPELL; ++i)
3576
    {
3577
        if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i)))
3578
        {
3579
            SpellInfo const* curSpellInfo = spell->m_spellInfo;
3580
            // check if we can interrupt spell
3581
            if ((spell->getState() == SPELL_STATE_CASTING
3582
                || (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastTime() > 0.0f))
3583
                && curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3584
                && ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT)
3585
                || (i == CURRENT_CHANNELED_SPELL && curSpellInfo->ChannelInterruptFlags & CHANNEL_INTERRUPT_FLAG_INTERRUPT)))
3586
            {
3587
                if (m_originalCaster)
3588
                {
3589
                    int32 duration = m_spellInfo->GetDuration();
3590
                    unitTarget->ProhibitSpellSchool(curSpellInfo->GetSchoolMask(), unitTarget->ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1 << effIndex));
3591
                }
3592
                ExecuteLogEffectInterruptCast(effIndex, unitTarget, curSpellInfo->Id);
3593
                unitTarget->InterruptSpell(CurrentSpellTypes(i), false);
3594
            }
3595
        }
3596
    }
3597
}
3598
3599
void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
3600
{
3601
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
3602
        return;
3603
3604
    uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue;
3605
3606
    GameObject* pGameObj = new GameObject;
3607
3608
    WorldObject* target = focusObject;
3609
    if (!target)
3610
        target = m_caster;
3611
3612
    float x, y, z;
3613
    if (m_targets.HasDst())
3614
        destTarget->GetPosition(x, y, z);
3615
    else
3616
        m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
3617
3618
    Map* map = target->GetMap();
3619
3620
    if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
3621
        m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
3622
    {
3623
        delete pGameObj;
3624
        return;
3625
    }
3626
3627
    int32 duration = m_spellInfo->GetDuration();
3628
3629
    pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
3630
    pGameObj->SetSpellId(m_spellInfo->Id);
3631
3632
    ExecuteLogEffectSummonObject(effIndex, pGameObj);
3633
3634
    // Wild object not have owner and check clickable by players
3635
    map->AddToMap(pGameObj);
3636
3637
    if (pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)
3638
        if (Player* player = m_caster->ToPlayer())
3639
            if (Battleground* bg = player->GetBattleground())
3640
                bg->SetDroppedFlagGUID(pGameObj->GetGUID(), player->GetTeam() == ALLIANCE ? TEAM_HORDE: TEAM_ALLIANCE);
3641
3642
    if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
3643
    {
3644
        GameObject* linkedGO = new GameObject;
3645
        if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
3646
            m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
3647
        {
3648
            linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
3649
            linkedGO->SetSpellId(m_spellInfo->Id);
3650
3651
            ExecuteLogEffectSummonObject(effIndex, linkedGO);
3652
3653
            // Wild object not have owner and check clickable by players
3654
            map->AddToMap(linkedGO);
3655
        }
3656
        else
3657
        {
3658
            delete linkedGO;
3659
            linkedGO = NULL;
3660
            return;
3661
        }
3662
    }
3663
}
3664
3665
void Spell::EffectScriptEffect(SpellEffIndex effIndex)
3666
{
3667
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
3668
        return;
3669
3670
    // TODO: we must implement hunter pet summon at login there (spell 6962)
3671
3672
    switch (m_spellInfo->SpellFamilyName)
3673
    {
3674
        case SPELLFAMILY_GENERIC:
3675
        {
3676
            switch (m_spellInfo->Id)
3677
            {
3678
                // Glyph of Backstab
3679
                case 63975:
3680
                {
3681
                    // search our Rupture aura on target
3682
                    if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00100000, 0, 0, m_caster->GetGUID()))
3683
                    {
3684
                        uint32 countMin = aurEff->GetBase()->GetMaxDuration();
3685
                        uint32 countMax = 12000; // this can be wrong, duration should be based on combo-points
3686
                        countMax += m_caster->HasAura(56801) ? 4000 : 0;
3687
3688
                        if (countMin < countMax)
3689
                        {
3690
                            aurEff->GetBase()->SetDuration(uint32(aurEff->GetBase()->GetDuration() + 3000));
3691
                            aurEff->GetBase()->SetMaxDuration(countMin + 2000);
3692
                        }
3693
3694
                    }
3695
                    return;
3696
                }
3697
                // Glyph of Scourge Strike
3698
                case 69961:
3699
                {
3700
                    Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE);
3701
                    for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
3702
                    {
3703
                        AuraEffect const* aurEff = *i;
3704
                        SpellInfo const* spellInfo = aurEff->GetSpellInfo();
3705
                        // search our Blood Plague and Frost Fever on target
3706
                        if (spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && spellInfo->SpellFamilyFlags[2] & 0x2 &&
3707
                            aurEff->GetCasterGUID() == m_caster->GetGUID())
3708
                        {
3709
                            uint32 countMin = aurEff->GetBase()->GetMaxDuration();
3710
                            uint32 countMax = spellInfo->GetMaxDuration();
3711
3712
                            // this Glyph
3713
                            countMax += 9000;
3714
                            // talent Epidemic
3715
                            if (AuraEffect const* epidemic = m_caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_DEATHKNIGHT, 234, EFFECT_0))
3716
                                countMax += epidemic->GetAmount();
3717
3718
                            if (countMin < countMax)
3719
                            {
3720
                                aurEff->GetBase()->SetDuration(aurEff->GetBase()->GetDuration() + 3000);
3721
                                aurEff->GetBase()->SetMaxDuration(countMin + 3000);
3722
                            }
3723
                        }
3724
                    }
3725
                    return;
3726
                }
3727
                case 45204: // Clone Me!
3728
                    m_caster->CastSpell(unitTarget, damage, true);
3729
                    break;
3730
                case 55693:                                 // Remove Collapsing Cave Aura
3731
                    if (!unitTarget)
3732
                        return;
3733
                    unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].CalcValue());
3734
                    break;
3735
                // PX-238 Winter Wondervolt TRAP
3736
                case 26275:
3737
                {
3738
                    uint32 spells[4] = { 26272, 26157, 26273, 26274 };
3739
3740
                    // check presence
3741
                    for (uint8 j = 0; j < 4; ++j)
3742
                        if (unitTarget->HasAuraEffect(spells[j], 0))
3743
                            return;
3744
3745
                    // select spell
3746
                    uint32 iTmpSpellId = spells[urand(0, 3)];
3747
3748
                    // cast
3749
                    unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
3750
                    return;
3751
                }
3752
                // Bending Shinbone
3753
                case 8856:
3754
                {
3755
                    if (!itemTarget && m_caster->GetTypeId() != TYPEID_PLAYER)
3756
                        return;
3757
3758
                    uint32 spell_id = roll_chance_i(20) ? 8854 : 8855;
3759
3760
                    m_caster->CastSpell(m_caster, spell_id, true, NULL);
3761
                    return;
3762
                }
3763
                // Brittle Armor - need remove one 24575 Brittle Armor aura
3764
                case 24590:
3765
                    unitTarget->RemoveAuraFromStack(24575);
3766
                    return;
3767
                // Mercurial Shield - need remove one 26464 Mercurial Shield aura
3768
                case 26465:
3769
                    unitTarget->RemoveAuraFromStack(26464);
3770
                    return;
3771
                // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
3772
                case 22539:
3773
                case 22972:
3774
                case 22975:
3775
                case 22976:
3776
                case 22977:
3777
                case 22978:
3778
                case 22979:
3779
                case 22980:
3780
                case 22981:
3781
                case 22982:
3782
                case 22983:
3783
                case 22984:
3784
                case 22985:
3785
                {
3786
                    if (!unitTarget || !unitTarget->isAlive())
3787
                        return;
3788
3789
                    // Onyxia Scale Cloak
3790
                    if (unitTarget->HasAura(22683))
3791
                        return;
3792
3793
                    // Shadow Flame
3794
                    m_caster->CastSpell(unitTarget, 22682, true);
3795
                    return;
3796
                }
3797
                // Piccolo of the Flaming Fire
3798
                case 17512:
3799
                {
3800
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3801
                        return;
3802
                    unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
3803
                    return;
3804
                }
3805
                // Decimate
3806
                case 28374:
3807
                case 54426:
3808
                    if (unitTarget)
3809
                    {
3810
                        int32 damage = int32(unitTarget->GetHealth()) - int32(unitTarget->CountPctFromMaxHealth(5));
3811
                        if (damage > 0)
3812
                            m_caster->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, damage, unitTarget);
3813
                    }
3814
                    return;
3815
                // Mirren's Drinking Hat
3816
                case 29830:
3817
                {
3818
                    uint32 item = 0;
3819
                    switch (urand(1, 6))
3820
                    {
3821
                        case 1:
3822
                        case 2:
3823
                        case 3:
3824
                            item = 23584; break;            // Loch Modan Lager
3825
                        case 4:
3826
                        case 5:
3827
                            item = 23585; break;            // Stouthammer Lite
3828
                        case 6:
3829
                            item = 23586; break;            // Aerie Peak Pale Ale
3830
                    }
3831
                    if (item)
3832
                        DoCreateItem(effIndex, item);
3833
                    break;
3834
                }
3835
                case 20589: // Escape artist
3836
                case 30918: // Improved Sprint
3837
                {
3838
                    // Removes snares and roots.
3839
                    unitTarget->RemoveMovementImpairingAuras();
3840
                    break;
3841
                }
3842
                // Plant Warmaul Ogre Banner
3843
                case 32307:
3844
                    if (Player* caster = m_caster->ToPlayer())
3845
                    {
3846
                        caster->RewardPlayerAndGroupAtEvent(18388, unitTarget);
3847
                        if (Creature* target = unitTarget->ToCreature())
3848
                        {
3849
                            target->setDeathState(CORPSE);
3850
                            target->RemoveCorpse();
3851
                        }
3852
                    }
3853
                    break;
3854
                // Mug Transformation
3855
                case 41931:
3856
                {
3857
                    if (m_caster->GetTypeId() != TYPEID_PLAYER)
3858
                        return;
3859
3860
                    uint8 bag = 19;
3861
                    uint8 slot = 0;
3862
                    Item* item = NULL;
3863
3864
                    while (bag) // 256 = 0 due to var type
3865
                    {
3866
                        item = m_caster->ToPlayer()->GetItemByPos(bag, slot);
3867
                        if (item && item->GetEntry() == 38587)
3868
                            break;
3869
3870
                        ++slot;
3871
                        if (slot == 39)
3872
                        {
3873
                            slot = 0;
3874
                            ++bag;
3875
                        }
3876
                    }
3877
                    if (bag)
3878
                    {
3879
                        if (m_caster->ToPlayer()->GetItemByPos(bag, slot)->GetCount() == 1) m_caster->ToPlayer()->RemoveItem(bag, slot, true);
3880
                        else m_caster->ToPlayer()->GetItemByPos(bag, slot)->SetCount(m_caster->ToPlayer()->GetItemByPos(bag, slot)->GetCount()-1);
3881
                        // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
3882
                        m_caster->CastSpell(m_caster, 42518, true);
3883
                        return;
3884
                    }
3885
                    break;
3886
                }
3887
                // Brutallus - Burn
3888
                case 45141:
3889
                case 45151:
3890
                {
3891
                    //Workaround for Range ... should be global for every ScriptEffect
3892
                    float radius = m_spellInfo->Effects[effIndex].CalcRadius();
3893
                    if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->GetDistance(m_caster) >= radius && !unitTarget->HasAura(46394) && unitTarget != m_caster)
3894
                        unitTarget->CastSpell(unitTarget, 46394, true);
3895
3896
                    break;
3897
                }
3898
                // Goblin Weather Machine
3899
                case 46203:
3900
                {
3901
                    if (!unitTarget)
3902
                        return;
3903
3904
                    uint32 spellId = 0;
3905
                    switch (rand() % 4)
3906
                    {
3907
                        case 0: spellId = 46740; break;
3908
                        case 1: spellId = 46739; break;
3909
                        case 2: spellId = 46738; break;
3910
                        case 3: spellId = 46736; break;
3911
                    }
3912
                    unitTarget->CastSpell(unitTarget, spellId, true);
3913
                    break;
3914
                }
3915
                // 5, 000 Gold
3916
                case 46642:
3917
                {
3918
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3919
                        return;
3920
3921
                    unitTarget->ToPlayer()->ModifyMoney(5000 * GOLD);
3922
3923
                    break;
3924
                }
3925
                // Roll Dice - Decahedral Dwarven Dice
3926
                case 47770:
3927
                {
3928
                    char buf[128];
3929
                    const char *gender = "his";
3930
                    if (m_caster->getGender() > 0)
3931
                        gender = "her";
3932
                    sprintf(buf, "%s rubs %s [Decahedral Dwarven Dice] between %s hands and rolls. One %u and one %u.", m_caster->GetName().c_str(), gender, gender, urand(1, 10), urand(1, 10));
3933
                    m_caster->MonsterTextEmote(buf, 0);
3934
                    break;
3935
                }
3936
                // Roll 'dem Bones - Worn Troll Dice
3937
                case 47776:
3938
                {
3939
                    char buf[128];
3940
                    const char *gender = "his";
3941
                    if (m_caster->getGender() > 0)
3942
                        gender = "her";
3943
                    sprintf(buf, "%s causually tosses %s [Worn Troll Dice]. One %u and one %u.", m_caster->GetName().c_str(), gender, urand(1, 6), urand(1, 6));
3944
                    m_caster->MonsterTextEmote(buf, 0);
3945
                    break;
3946
                }
3947
                // Vigilance
3948
                case 50725:
3949
                {
3950
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3951
                        return;
3952
3953
                    // Remove Taunt cooldown
3954
                    unitTarget->ToPlayer()->RemoveSpellCooldown(355, true);
3955
3956
                    return;
3957
                }
3958
                // Death Knight Initiate Visual
3959
                case 51519:
3960
                {
3961
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
3962
                        return;
3963
3964
                    uint32 iTmpSpellId = 0;
3965
                    switch (unitTarget->GetDisplayId())
3966
                    {
3967
                        case 25369: iTmpSpellId = 51552; break; // bloodelf female
3968
                        case 25373: iTmpSpellId = 51551; break; // bloodelf male
3969
                        case 25363: iTmpSpellId = 51542; break; // draenei female
3970
                        case 25357: iTmpSpellId = 51541; break; // draenei male
3971
                        case 25361: iTmpSpellId = 51537; break; // dwarf female
3972
                        case 25356: iTmpSpellId = 51538; break; // dwarf male
3973
                        case 25372: iTmpSpellId = 51550; break; // forsaken female
3974
                        case 25367: iTmpSpellId = 51549; break; // forsaken male
3975
                        case 25362: iTmpSpellId = 51540; break; // gnome female
3976
                        case 25359: iTmpSpellId = 51539; break; // gnome male
3977
                        case 25355: iTmpSpellId = 51534; break; // human female
3978
                        case 25354: iTmpSpellId = 51520; break; // human male
3979
                        case 25360: iTmpSpellId = 51536; break; // nightelf female
3980
                        case 25358: iTmpSpellId = 51535; break; // nightelf male
3981
                        case 25368: iTmpSpellId = 51544; break; // orc female
3982
                        case 25364: iTmpSpellId = 51543; break; // orc male
3983
                        case 25371: iTmpSpellId = 51548; break; // tauren female
3984
                        case 25366: iTmpSpellId = 51547; break; // tauren male
3985
                        case 25370: iTmpSpellId = 51545; break; // troll female
3986
                        case 25365: iTmpSpellId = 51546; break; // troll male
3987
                        default: return;
3988
                    }
3989
3990
                    unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
3991
                    Creature* npc = unitTarget->ToCreature();
3992
                    npc->LoadEquipment(npc->GetEquipmentId());
3993
                    return;
3994
                }
3995
                // Emblazon Runeblade
3996
                case 51770:
3997
                {
3998
                    if (!m_originalCaster)
3999
                        return;
4000
4001
                    m_originalCaster->CastSpell(m_originalCaster, damage, false);
4002
                    break;
4003
                }
4004
                // Deathbolt from Thalgran Blightbringer
4005
                // reflected by Freya's Ward
4006
                // Retribution by Sevenfold Retribution
4007
                case 51854:
4008
                {
4009
                    if (!unitTarget)
4010
                        return;
4011
                    if (unitTarget->HasAura(51845))
4012
                        unitTarget->CastSpell(m_caster, 51856, true);
4013
                    else
4014
                        m_caster->CastSpell(unitTarget, 51855, true);
4015
                    break;
4016
                }
4017
                // Summon Ghouls On Scarlet Crusade
4018
                case 51904:
4019
                {
4020
                    if (!m_targets.HasDst())
4021
                        return;
4022
4023
                    float x, y, z;
4024
                    float radius = m_spellInfo->Effects[effIndex].CalcRadius();
4025
                    for (uint8 i = 0; i < 15; ++i)
4026
                    {
4027
                        m_caster->GetRandomPoint(*destTarget, radius, x, y, z);
4028
                        m_caster->CastSpell(x, y, z, 54522, true);
4029
                    }
4030
                    break;
4031
                }
4032
                case 52173: // Coyote Spirit Despawn
4033
                case 60243: // Blood Parrot Despawn
4034
                    if (unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->ToCreature()->isSummon())
4035
                        unitTarget->ToTempSummon()->UnSummon();
4036
                    return;
4037
                case 52479: // Gift of the Harvester
4038
                    if (unitTarget && m_originalCaster)
4039
                        m_originalCaster->CastSpell(unitTarget, urand(0, 1) ? damage : 52505, true);
4040
                    return;
4041
                case 53110: // Devour Humanoid
4042
                    if (unitTarget)
4043
                        unitTarget->CastSpell(m_caster, damage, true);
4044
                    return;
4045
                case 57347: // Retrieving (Wintergrasp RP-GG pickup spell)
4046
                {
4047
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
4048
                        return;
4049
4050
                    unitTarget->ToCreature()->DespawnOrUnsummon();
4051
4052
                    return;
4053
                }
4054
                case 57349: // Drop RP-GG (Wintergrasp RP-GG at death drop spell)
4055
                {
4056
                    if (m_caster->GetTypeId() != TYPEID_PLAYER)
4057
                        return;
4058
4059
                    // Delete item from inventory at death
4060
                    m_caster->ToPlayer()->DestroyItemCount(damage, 5, true);
4061
4062
                    return;
4063
                }
4064
                case 58418:                                 // Portal to Orgrimmar
4065
                case 58420:                                 // Portal to Stormwind
4066
                {
4067
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex != 0)
4068
                        return;
4069
4070
                    uint32 spellID = m_spellInfo->Effects[EFFECT_0].CalcValue();
4071
                    uint32 questID = m_spellInfo->Effects[EFFECT_1].CalcValue();
4072
4073
                    if (unitTarget->ToPlayer()->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE)
4074
                        unitTarget->CastSpell(unitTarget, spellID, true);
4075
4076
                    return;
4077
                }
4078
                case 58941:                                 // Rock Shards
4079
                    if (unitTarget && m_originalCaster)
4080
                    {
4081
                        for (uint32 i = 0; i < 3; ++i)
4082
                        {
4083
                            m_originalCaster->CastSpell(unitTarget, 58689, true);
4084
                            m_originalCaster->CastSpell(unitTarget, 58692, true);
4085
                        }
4086
                        if (((InstanceMap*)m_originalCaster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY)
4087
                        {
4088
                            m_originalCaster->CastSpell(unitTarget, 58695, true);
4089
                            m_originalCaster->CastSpell(unitTarget, 58696, true);
4090
                        }
4091
                        else
4092
                        {
4093
                            m_originalCaster->CastSpell(unitTarget, 60883, true);
4094
                            m_originalCaster->CastSpell(unitTarget, 60884, true);
4095
                        }
4096
                    }
4097
                    return;
4098
                case 58983: // Big Blizzard Bear
4099
                {
4100
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4101
                        return;
4102
4103
                    // Prevent stacking of mounts and client crashes upon dismounting
4104
                    unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED);
4105
4106
                    // Triggered spell id dependent on riding skill
4107
                    if (uint16 skillval = unitTarget->ToPlayer()->GetSkillValue(SKILL_RIDING))
4108
                    {
4109
                        if (skillval >= 150)
4110
                            unitTarget->CastSpell(unitTarget, 58999, true);
4111
                        else
4112
                            unitTarget->CastSpell(unitTarget, 58997, true);
4113
                    }
4114
                    return;
4115
                }
4116
                case 63845: // Create Lance
4117
                {
4118
                    if (m_caster->GetTypeId() != TYPEID_PLAYER)
4119
                        return;
4120
4121
                    if (m_caster->ToPlayer()->GetTeam() == ALLIANCE)
4122
                        m_caster->CastSpell(m_caster, 63914, true);
4123
                    else
4124
                        m_caster->CastSpell(m_caster, 63919, true);
4125
                    return;
4126
                }
4127
                case 59317:                                 // Teleporting
4128
                {
4129
4130
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4131
                        return;
4132
4133
                    // return from top
4134
                    if (unitTarget->ToPlayer()->GetAreaId() == 4637)
4135
                        unitTarget->CastSpell(unitTarget, 59316, true);
4136
                    // teleport atop
4137
                    else
4138
                        unitTarget->CastSpell(unitTarget, 59314, true);
4139
4140
                    return;
4141
                }
4142
                case 62482: // Grab Crate
4143
                {
4144
                    if (unitTarget)
4145
                    {
4146
                        if (Unit* seat = m_caster->GetVehicleBase())
4147
                        {
4148
                            if (Unit* parent = seat->GetVehicleBase())
4149
                            {
4150
                                // TODO: a hack, range = 11, should after some time cast, otherwise too far
4151
                                m_caster->CastSpell(parent, 62496, true);
4152
                                unitTarget->CastSpell(parent, m_spellInfo->Effects[EFFECT_0].CalcValue());
4153
                            }
4154
                        }
4155
                    }
4156
                    return;
4157
                }
4158
                case 60123: // Lightwell
4159
                {
4160
                    if (m_caster->GetTypeId() != TYPEID_UNIT || !m_caster->ToCreature()->isSummon())
4161
                        return;
4162
4163
                    uint32 spell_heal;
4164
4165
                    switch (m_caster->GetEntry())
4166
                    {
4167
                        case 31897: spell_heal = 7001; break;
4168
                        case 31896: spell_heal = 27873; break;
4169
                        case 31895: spell_heal = 27874; break;
4170
                        case 31894: spell_heal = 28276; break;
4171
                        case 31893: spell_heal = 48084; break;
4172
                        case 31883: spell_heal = 48085; break;
4173
                        default:
4174
                            sLog->outError(LOG_FILTER_SPELLS_AURAS, "Unknown Lightwell spell caster %u", m_caster->GetEntry());
4175
                            return;
4176
                    }
4177
4178
                    // proc a spellcast
4179
                    if (Aura* chargesAura = m_caster->GetAura(59907))
4180
                    {
4181
                        m_caster->CastSpell(unitTarget, spell_heal, true, NULL, NULL, m_caster->ToTempSummon()->GetSummonerGUID());
4182
                        if (chargesAura->ModCharges(-1))
4183
                            m_caster->ToTempSummon()->UnSummon();
4184
                    }
4185
4186
                    return;
4187
                }
4188
                // Stoneclaw Totem
4189
                case 55328: // Rank 1
4190
                case 55329: // Rank 2
4191
                case 55330: // Rank 3
4192
                case 55332: // Rank 4
4193
                case 55333: // Rank 5
4194
                case 55335: // Rank 6
4195
                case 55278: // Rank 7
4196
                case 58589: // Rank 8
4197
                case 58590: // Rank 9
4198
                case 58591: // Rank 10
4199
                {
4200
                    int32 basepoints0 = damage;
4201
                    // Cast Absorb on totems
4202
                    for (uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot)
4203
                    {
4204
                        if (!unitTarget->m_SummonSlot[slot])
4205
                            continue;
4206
4207
                        Creature* totem = unitTarget->GetMap()->GetCreature(unitTarget->m_SummonSlot[slot]);
4208
                        if (totem && totem->isTotem())
4209
                        {
4210
                            m_caster->CastCustomSpell(totem, 55277, &basepoints0, NULL, NULL, true);
4211
                        }
4212
                    }
4213
                    // Glyph of Stoneclaw Totem
4214
                    if (AuraEffect* aur=unitTarget->GetAuraEffect(63298, 0))
4215
                    {
4216
                        basepoints0 *= aur->GetAmount();
4217
                        m_caster->CastCustomSpell(unitTarget, 55277, &basepoints0, NULL, NULL, true);
4218
                    }
4219
                    break;
4220
                }
4221
                case 66545: //Summon Memory
4222
                {
4223
                    uint8 uiRandom = urand(0, 25);
4224
                    uint32 uiSpells[26] = {66704, 66705, 66706, 66707, 66709, 66710, 66711, 66712, 66713, 66714, 66715, 66708, 66708, 66691, 66692, 66694, 66695, 66696, 66697, 66698, 66699, 66700, 66701, 66702, 66703, 66543};
4225
4226
                    m_caster->CastSpell(m_caster, uiSpells[uiRandom], true);
4227
                    break;
4228
                }
4229
                case 45668:                                 // Ultra-Advanced Proto-Typical Shortening Blaster
4230
                {
4231
                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
4232
                        return;
4233
4234
                    if (roll_chance_i(50))                  // chance unknown, using 50
4235
                        return;
4236
4237
                    static uint32 const spellPlayer[5] =
4238
                    {
4239
                        45674,                            // Bigger!
4240
                        45675,                            // Shrunk
4241
                        45678,                            // Yellow
4242
                        45682,                            // Ghost
4243
                        45684                             // Polymorph
4244
                    };
4245
4246
                    static uint32 const spellTarget[5] =
4247
                    {
4248
                        45673,                            // Bigger!
4249
                        45672,                            // Shrunk
4250
                        45677,                            // Yellow
4251
                        45681,                            // Ghost
4252
                        45683                             // Polymorph
4253
                    };
4254
4255
                    m_caster->CastSpell(m_caster, spellPlayer[urand(0, 4)], true);
4256
                    unitTarget->CastSpell(unitTarget, spellTarget[urand(0, 4)], true);
4257
                    break;
4258
                }
4259
            }
4260
            break;
4261
        }
4262
        case SPELLFAMILY_PALADIN:
4263
        {
4264
            // Judgement (seal trigger)
4265
            if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
4266
            {
4267
                if (!unitTarget || !unitTarget->isAlive())
4268
                    return;
4269
                uint32 spellId1 = 0;
4270
                uint32 spellId2 = 0;
4271
4272
                // Judgement self add switch
4273
                switch (m_spellInfo->Id)
4274
                {
4275
                    case 53407: spellId1 = 20184; break;    // Judgement of Justice
4276
                    case 20271:                             // Judgement of Light
4277
                    case 57774: spellId1 = 20185; break;    // Judgement of Light
4278
                    case 53408: spellId1 = 20186; break;    // Judgement of Wisdom
4279
                    default:
4280
                        sLog->outError(LOG_FILTER_SPELLS_AURAS, "Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect", m_spellInfo->Id);
4281
                        return;
4282
                }
4283
                // all seals have aura dummy in 2 effect
4284
                Unit::AuraApplicationMap & sealAuras = m_caster->GetAppliedAuras();
4285
                for (Unit::AuraApplicationMap::iterator iter = sealAuras.begin(); iter != sealAuras.end();)
4286
                {
4287
                    Aura* aura = iter->second->GetBase();
4288
                    if (aura->GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_SEAL)
4289
                    {
4290
                        if (AuraEffect* aureff = aura->GetEffect(2))
4291
                            if (aureff->GetAuraType() == SPELL_AURA_DUMMY)
4292
                            {
4293
                                if (sSpellMgr->GetSpellInfo(aureff->GetAmount()))
4294
                                    spellId2 = aureff->GetAmount();
4295
                                break;
4296
                            }
4297
                        if (!spellId2)
4298
                        {
4299
                            switch (iter->first)
4300
                            {
4301
                                // Seal of light, Seal of wisdom, Seal of justice
4302
                                case 20165:
4303
                                case 20166:
4304
                                case 20164:
4305
                                    spellId2 = 54158;
4306
                            }
4307
                        }
4308
                        break;
4309
                    }
4310
                    else
4311
                        ++iter;
4312
                }
4313
                if (spellId1)
4314
                    m_caster->CastSpell(unitTarget, spellId1, true);
4315
                if (spellId2)
4316
                    m_caster->CastSpell(unitTarget, spellId2, true);
4317
                return;
4318
            }
4319
        }
4320
        case SPELLFAMILY_POTION:
4321
        {
4322
            switch (m_spellInfo->Id)
4323
            {
4324
                // Netherbloom
4325
                case 28702:
4326
                {
4327
                    if (!unitTarget)
4328
                        return;
4329
                    // 25% chance of casting a random buff
4330
                    if (roll_chance_i(75))
4331
                        return;
4332
4333
                    // triggered spells are 28703 to 28707
4334
                    // Note: some sources say, that there was the possibility of
4335
                    //       receiving a debuff. However, this seems to be removed by a patch.
4336
                    const uint32 spellid = 28703;
4337
4338
                    // don't overwrite an existing aura
4339
                    for (uint8 i = 0; i < 5; ++i)
4340
                        if (unitTarget->HasAura(spellid + i))
4341
                            return;
4342
                    unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
4343
                    break;
4344
                }
4345
4346
                // Nightmare Vine
4347
                case 28720:
4348
                {
4349
                    if (!unitTarget)
4350
                        return;
4351
                    // 25% chance of casting Nightmare Pollen
4352
                    if (roll_chance_i(75))
4353
                        return;
4354
                    unitTarget->CastSpell(unitTarget, 28721, true);
4355
                    break;
4356
                }
4357
            }
4358
            break;
4359
        }
4360
        case SPELLFAMILY_DEATHKNIGHT:
4361
        {
4362
            // Pestilence
4363
            if (m_spellInfo->SpellFamilyFlags[1]&0x10000)
4364
            {
4365
                // Get diseases on target of spell
4366
                if (m_targets.GetUnitTarget() &&  // Glyph of Disease - cast on unit target too to refresh aura
4367
                    (m_targets.GetUnitTarget() != unitTarget || m_caster->GetAura(63334)))
4368
                {
4369
                    // And spread them on target
4370
                    // Blood Plague
4371
                    if (m_targets.GetUnitTarget()->GetAura(55078))
4372
                        m_caster->CastSpell(unitTarget, 55078, true);
4373
                    // Frost Fever
4374
                    if (m_targets.GetUnitTarget()->GetAura(55095))
4375
                        m_caster->CastSpell(unitTarget, 55095, true);
4376
                }
4377
            }
4378
            break;
4379
        }
4380
        case SPELLFAMILY_WARRIOR:
4381
        {
4382
            // Shattering Throw
4383
            if (m_spellInfo->SpellFamilyFlags[1] & 0x00400000)
4384
            {
4385
                if (!unitTarget)
4386
                    return;
4387
                // remove shields, will still display immune to damage part
4388
                unitTarget->RemoveAurasWithMechanic(1<<MECHANIC_IMMUNE_SHIELD, AURA_REMOVE_BY_ENEMY_SPELL);
4389
                return;
4390
            }
4391
            break;
4392
        }
4393
    }
4394
4395
    // normal DB scripted effect
4396
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell ScriptStart spellid %u in EffectScriptEffect(%u)", m_spellInfo->Id, effIndex);
4397
    m_caster->GetMap()->ScriptsStart(sSpellScripts, uint32(m_spellInfo->Id | (effIndex << 24)), m_caster, unitTarget);
4398
}
4399
4400
void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
4401
{
4402
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4403
        return;
4404
4405
    if (!unitTarget)
4406
        return;
4407
4408
    unitTarget->getHostileRefManager().UpdateVisibility();
4409
4410
    Unit::AttackerSet const& attackers = unitTarget->getAttackers();
4411
    for (Unit::AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end();)
4412
    {
4413
        if (!(*itr)->canSeeOrDetect(unitTarget))
4414
            (*(itr++))->AttackStop();
4415
        else
4416
            ++itr;
4417
    }
4418
4419
    unitTarget->m_lastSanctuaryTime = getMSTime();
4420
4421
    // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4422
    if (m_caster->GetTypeId() == TYPEID_PLAYER
4423
        && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
4424
        && (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VANISH))
4425
    {
4426
        m_caster->ToPlayer()->RemoveAurasByType(SPELL_AURA_MOD_ROOT);
4427
        // Overkill
4428
        if (m_caster->ToPlayer()->HasSpell(58426))
4429
           m_caster->CastSpell(m_caster, 58427, true);
4430
    }
4431
}
4432
4433
void Spell::EffectAddComboPoints(SpellEffIndex /*effIndex*/)
4434
{
4435
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4436
        return;
4437
4438
    if (!unitTarget)
4439
        return;
4440
4441
    if (!m_caster->m_movedPlayer)
4442
        return;
4443
4444
    if (damage <= 0)
4445
        return;
4446
4447
    m_caster->m_movedPlayer->AddComboPoints(unitTarget, damage, this);
4448
}
4449
4450
void Spell::EffectDuel(SpellEffIndex effIndex)
4451
{
4452
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4453
        return;
4454
4455
    if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
4456
        return;
4457
4458
    Player* caster = m_caster->ToPlayer();
4459
    Player* target = unitTarget->ToPlayer();
4460
4461
    // caster or target already have requested duel
4462
    if (caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()))
4463
        return;
4464
4465
    // Players can only fight a duel in zones with this flag
4466
    AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetAreaId());
4467
    if (casterAreaEntry && !(casterAreaEntry->flags & AREA_FLAG_ALLOW_DUELS))
4468
    {
4469
        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
4470
        return;
4471
    }
4472
4473
    AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetAreaId());
4474
    if (targetAreaEntry && !(targetAreaEntry->flags & AREA_FLAG_ALLOW_DUELS))
4475
    {
4476
        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
4477
        return;
4478
    }
4479
4480
    //CREATE DUEL FLAG OBJECT
4481
    GameObject* pGameObj = new GameObject;
4482
4483
    uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue;
4484
4485
    Map* map = m_caster->GetMap();
4486
    if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id,
4487
        map, m_caster->GetPhaseMask(),
4488
        m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2,
4489
        m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2,
4490
        m_caster->GetPositionZ(),
4491
        m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
4492
    {
4493
        delete pGameObj;
4494
        return;
4495
    }
4496
4497
    pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction());
4498
    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1);
4499
    int32 duration = m_spellInfo->GetDuration();
4500
    pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
4501
    pGameObj->SetSpellId(m_spellInfo->Id);
4502
4503
    ExecuteLogEffectSummonObject(effIndex, pGameObj);
4504
4505
    m_caster->AddGameObject(pGameObj);
4506
    map->AddToMap(pGameObj);
4507
    //END
4508
4509
    // Send request
4510
    WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8);
4511
    data << uint64(pGameObj->GetGUID());
4512
    data << uint64(caster->GetGUID());
4513
    caster->GetSession()->SendPacket(&data);
4514
    target->GetSession()->SendPacket(&data);
4515
4516
    // create duel-info
4517
    DuelInfo* duel   = new DuelInfo;
4518
    duel->initiator  = caster;
4519
    duel->opponent   = target;
4520
    duel->startTime  = 0;
4521
    duel->startTimer = 0;
4522
    duel->isMounted  = (GetSpellInfo()->Id == 62875); // Mounted Duel
4523
    caster->duel     = duel;
4524
4525
    DuelInfo* duel2   = new DuelInfo;
4526
    duel2->initiator  = caster;
4527
    duel2->opponent   = caster;
4528
    duel2->startTime  = 0;
4529
    duel2->startTimer = 0;
4530
    duel2->isMounted  = (GetSpellInfo()->Id == 62875); // Mounted Duel
4531
    target->duel      = duel2;
4532
4533
    caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
4534
    target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID());
4535
4536
    sScriptMgr->OnPlayerDuelRequest(target, caster);
4537
}
4538
4539
void Spell::EffectStuck(SpellEffIndex /*effIndex*/)
4540
{
4541
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
4542
        return;
4543
4544
    if (!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
4545
        return;
4546
4547
    if (!sWorld->getBoolConfig(CONFIG_CAST_UNSTUCK))
4548
        return;
4549
4550
    Player* target = (Player*)m_caster;
4551
4552
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell Effect: Stuck");
4553
    sLog->outInfo(LOG_FILTER_SPELLS_AURAS, "Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", target->GetName().c_str(), target->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
4554
4555
    if (target->isInFlight())
4556
        return;
4557
4558
    target->TeleportTo(target->GetStartPosition(), TELE_TO_SPELL);
4559
    // homebind location is loaded always
4560
    // target->TeleportTo(target->m_homebindMapId, target->m_homebindX, target->m_homebindY, target->m_homebindZ, target->GetOrientation(), (m_caster == m_caster ? TELE_TO_SPELL : 0));
4561
4562
    // Stuck spell trigger Hearthstone cooldown
4563
    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(8690);
4564
    if (!spellInfo)
4565
        return;
4566
    Spell spell(target, spellInfo, TRIGGERED_FULL_MASK);
4567
    spell.SendSpellCooldown();
4568
}
4569
4570
void Spell::EffectSummonPlayer(SpellEffIndex /*effIndex*/)
4571
{
4572
    // workaround - this effect should not use target map
4573
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4574
        return;
4575
4576
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4577
        return;
4578
4579
    // Evil Twin (ignore player summon, but hide this for summoner)
4580
    if (unitTarget->HasAura(23445))
4581
        return;
4582
4583
    float x, y, z;
4584
    m_caster->GetPosition(x, y, z);
4585
4586
    unitTarget->ToPlayer()->SetSummonPoint(m_caster->GetMapId(), x, y, z);
4587
4588
    WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
4589
    data << uint64(m_caster->GetGUID());                    // summoner guid
4590
    data << uint32(m_caster->GetZoneId());                  // summoner zone
4591
    data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILLISECONDS); // auto decline after msecs
4592
    unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
4593
}
4594
4595
void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/)
4596
{
4597
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4598
        return;
4599
4600
    if (!gameObjTarget)
4601
        return;
4602
4603
    ScriptInfo activateCommand;
4604
    activateCommand.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
4605
4606
    // int32 unk = m_spellInfo->Effects[effIndex].MiscValue; // This is set for EffectActivateObject spells; needs research
4607
4608
    gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, 0, m_caster, gameObjTarget);
4609
}
4610
4611
void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
4612
{
4613
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
4614
        return;
4615
4616
    if (m_caster->GetTypeId() != TYPEID_PLAYER || m_glyphIndex >= MAX_GLYPH_SLOT_INDEX)
4617
        return;
4618
4619
    Player* player = (Player*)m_caster;
4620
4621
    // glyph sockets level requirement
4622
    uint8 minLevel = 0;
4623
    switch (m_glyphIndex)
4624
    {
4625
        case 0:
4626
        case 1: minLevel = 15; break;
4627
        case 2: minLevel = 50; break;
4628
        case 3: minLevel = 30; break;
4629
        case 4: minLevel = 70; break;
4630
        case 5: minLevel = 80; break;
4631
    }
4632
    if (minLevel && m_caster->getLevel() < minLevel)
4633
    {
4634
        SendCastResult(SPELL_FAILED_GLYPH_SOCKET_LOCKED);
4635
        return;
4636
    }
4637
4638
    // apply new one
4639
    if (uint32 glyph = m_spellInfo->Effects[effIndex].MiscValue)
4640
    {
4641
        if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
4642
        {
4643
            if (GlyphSlotEntry const* gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
4644
            {
4645
                if (gp->TypeFlags != gs->TypeFlags)
4646
                {
4647
                    SendCastResult(SPELL_FAILED_INVALID_GLYPH);
4648
                    return;                                 // glyph slot mismatch
4649
                }
4650
            }
4651
4652
            // remove old glyph
4653
            if (uint32 oldglyph = player->GetGlyph(m_glyphIndex))
4654
            {
4655
                if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
4656
                {
4657
                    player->RemoveAurasDueToSpell(old_gp->SpellId);
4658
                    player->SetGlyph(m_glyphIndex, 0);
4659
                }
4660
            }
4661
4662
            player->CastSpell(m_caster, gp->SpellId, true);
4663
            player->SetGlyph(m_glyphIndex, glyph);
4664
            player->SendTalentsInfoData(false);
4665
        }
4666
    }
4667
}
4668
4669
void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex)
4670
{
4671
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4672
        return;
4673
4674
    // this is only item spell effect applied to main-hand weapon of target player (players in area)
4675
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4676
        return;
4677
4678
    Player* item_owner = (Player*)unitTarget;
4679
    Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
4680
4681
    if (!item)
4682
        return;
4683
4684
    // must be equipped
4685
    if (!item->IsEquipped())
4686
        return;
4687
4688
    if (m_spellInfo->Effects[effIndex].MiscValue)
4689
    {
4690
        uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
4691
        int32 duration = m_spellInfo->GetDuration();          //Try duration index first ..
4692
        if (!duration)
4693
            duration = damage;//+1;            //Base points after ..
4694
        if (!duration)
4695
            duration = 10;                                  //10 seconds for enchants which don't have listed duration
4696
4697
        SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4698
        if (!pEnchant)
4699
            return;
4700
4701
        // Always go to temp enchantment slot
4702
        EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
4703
4704
        // Enchantment will not be applied if a different one already exists
4705
        if (item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
4706
            return;
4707
4708
        // Apply the temporary enchantment
4709
        item->SetEnchantment(slot, enchant_id, duration*IN_MILLISECONDS, 0);
4710
        item_owner->ApplyEnchantment(item, slot, true);
4711
    }
4712
}
4713
4714
void Spell::EffectDisEnchant(SpellEffIndex /*effIndex*/)
4715
{
4716
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4717
        return;
4718
4719
    if (!itemTarget || !itemTarget->GetTemplate()->DisenchantID)
4720
        return;
4721
4722
    if (Player* caster = m_caster->ToPlayer())
4723
    {
4724
        caster->UpdateCraftSkill(m_spellInfo->Id);
4725
        caster->SendLoot(itemTarget->GetGUID(), LOOT_DISENCHANTING);
4726
    }
4727
4728
    // item will be removed at disenchanting end
4729
}
4730
4731
void Spell::EffectInebriate(SpellEffIndex /*effIndex*/)
4732
{
4733
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4734
        return;
4735
4736
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4737
        return;
4738
4739
    Player* player = unitTarget->ToPlayer();
4740
    uint8 currentDrunk = player->GetDrunkValue();
4741
    uint8 drunkMod = damage;
4742
    if (currentDrunk + drunkMod > 100)
4743
    {
4744
        currentDrunk = 100;
4745
        if (rand_chance() < 25.0f)
4746
            player->CastSpell(player, 67468, false);    // Drunken Vomit
4747
    }
4748
    else
4749
        currentDrunk += drunkMod;
4750
4751
    player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0);
4752
}
4753
4754
void Spell::EffectFeedPet(SpellEffIndex effIndex)
4755
{
4756
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4757
        return;
4758
4759
    Player* player = m_caster->ToPlayer();
4760
    if (!player)
4761
        return;
4762
4763
    Item* foodItem = itemTarget;
4764
    if (!foodItem)
4765
        return;
4766
4767
    Pet* pet = player->GetPet();
4768
    if (!pet)
4769
        return;
4770
4771
    if (!pet->isAlive())
4772
        return;
4773
4774
    int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetTemplate()->ItemLevel);
4775
    if (benefit <= 0)
4776
        return;
4777
4778
    ExecuteLogEffectDestroyItem(effIndex, foodItem->GetEntry());
4779
4780
    uint32 count = 1;
4781
    player->DestroyItemCount(foodItem, count, true);
4782
    // TODO: fix crash when a spell has two effects, both pointed at the same item target
4783
4784
    m_caster->CastCustomSpell(pet, m_spellInfo->Effects[effIndex].TriggerSpell, &benefit, NULL, NULL, true);
4785
}
4786
4787
void Spell::EffectDismissPet(SpellEffIndex effIndex)
4788
{
4789
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4790
        return;
4791
4792
    if (!unitTarget || !unitTarget->isPet())
4793
        return;
4794
4795
    Pet* pet = unitTarget->ToPet();
4796
4797
    ExecuteLogEffectUnsummonObject(effIndex, pet);
4798
    pet->GetOwner()->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
4799
}
4800
4801
void Spell::EffectSummonObject(SpellEffIndex effIndex)
4802
{
4803
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
4804
        return;
4805
4806
    uint32 go_id = m_spellInfo->Effects[effIndex].MiscValue;
4807
4808
    uint8 slot = 0;
4809
    switch (m_spellInfo->Effects[effIndex].Effect)
4810
    {
4811
        case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
4812
        case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
4813
        case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
4814
        case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
4815
        default: return;
4816
    }
4817
4818
    uint64 guid = m_caster->m_ObjectSlot[slot];
4819
    if (guid != 0)
4820
    {
4821
        GameObject* obj = NULL;
4822
        if (m_caster)
4823
            obj = m_caster->GetMap()->GetGameObject(guid);
4824
4825
        if (obj)
4826
        {
4827
            // Recast case - null spell id to make auras not be removed on object remove from world
4828
            if (m_spellInfo->Id == obj->GetSpellId())
4829
                obj->SetSpellId(0);
4830
            m_caster->RemoveGameObject(obj, true);
4831
        }
4832
        m_caster->m_ObjectSlot[slot] = 0;
4833
    }
4834
4835
    GameObject* pGameObj = new GameObject;
4836
4837
    float x, y, z;
4838
    // If dest location if present
4839
    if (m_targets.HasDst())
4840
        destTarget->GetPosition(x, y, z);
4841
    // Summon in random point all other units if location present
4842
    else
4843
        m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
4844
4845
    Map* map = m_caster->GetMap();
4846
    if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map,
4847
        m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
4848
    {
4849
        delete pGameObj;
4850
        return;
4851
    }
4852
4853
    //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
4854
    int32 duration = m_spellInfo->GetDuration();
4855
    pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
4856
    pGameObj->SetSpellId(m_spellInfo->Id);
4857
    m_caster->AddGameObject(pGameObj);
4858
4859
    ExecuteLogEffectSummonObject(effIndex, pGameObj);
4860
4861
    map->AddToMap(pGameObj);
4862
4863
    m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
4864
}
4865
4866
void Spell::EffectResurrect(SpellEffIndex effIndex)
4867
{
4868
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4869
        return;
4870
4871
    if (!unitTarget)
4872
        return;
4873
    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
4874
        return;
4875
4876
    if (unitTarget->isAlive())
4877
        return;
4878
    if (!unitTarget->IsInWorld())
4879
        return;
4880
4881
    switch (m_spellInfo->Id)
4882
    {
4883
        // Defibrillate (Goblin Jumper Cables) have 33% chance on success
4884
        case 8342:
4885
            if (roll_chance_i(67))
4886
            {
4887
                m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
4888
                return;
4889
            }
4890
            break;
4891
        // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
4892
        case 22999:
4893
            if (roll_chance_i(50))
4894
            {
4895
                m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
4896
                return;
4897
            }
4898
            break;
4899
        // Defibrillate (Gnomish Army Knife) have 67% chance on success_list
4900
        case 54732:
4901
            if (roll_chance_i(33))
4902
            {
4903
                return;
4904
            }
4905
            break;
4906
        default:
4907
            break;
4908
    }
4909
4910
    Player* target = unitTarget->ToPlayer();
4911
4912
    if (target->isRessurectRequested())       // already have one active request
4913
        return;
4914
4915
    uint32 health = target->CountPctFromMaxHealth(damage);
4916
    uint32 mana   = CalculatePct(target->GetMaxPower(POWER_MANA), damage);
4917
4918
    ExecuteLogEffectResurrect(effIndex, target);
4919
4920
    target->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
4921
    SendResurrectRequest(target);
4922
}
4923
4924
void Spell::EffectAddExtraAttacks(SpellEffIndex effIndex)
4925
{
4926
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4927
        return;
4928
4929
    if (!unitTarget || !unitTarget->isAlive() || !unitTarget->getVictim())
4930
        return;
4931
4932
    if (unitTarget->m_extraAttacks)
4933
        return;
4934
4935
    unitTarget->m_extraAttacks = damage;
4936
4937
    ExecuteLogEffectExtraAttacks(effIndex, unitTarget->getVictim(), damage);
4938
}
4939
4940
void Spell::EffectParry(SpellEffIndex /*effIndex*/)
4941
{
4942
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
4943
        return;
4944
4945
    if (m_caster->GetTypeId() == TYPEID_PLAYER)
4946
        m_caster->ToPlayer()->SetCanParry(true);
4947
}
4948
4949
void Spell::EffectBlock(SpellEffIndex /*effIndex*/)
4950
{
4951
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
4952
        return;
4953
4954
    if (m_caster->GetTypeId() == TYPEID_PLAYER)
4955
        m_caster->ToPlayer()->SetCanBlock(true);
4956
}
4957
4958
void Spell::EffectLeap(SpellEffIndex /*effIndex*/)
4959
{
4960
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4961
        return;
4962
4963
    if (!unitTarget || unitTarget->isInFlight())
4964
        return;
4965
4966
    if (!m_targets.HasDst())
4967
        return;
4968
4969
    Position pos;
4970
    destTarget->GetPosition(&pos);
4971
    unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetDistance(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + 2.0f), 0.0f);
4972
    unitTarget->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), unitTarget == m_caster);
4973
}
4974
4975
void Spell::EffectReputation(SpellEffIndex effIndex)
4976
{
4977
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
4978
        return;
4979
4980
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4981
        return;
4982
4983
    Player* player = unitTarget->ToPlayer();
4984
4985
    int32  rep_change = damage;
4986
4987
	uint32 faction_id = m_spellInfo->Effects[effIndex].MiscValue;
4988
    FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
4989
4990
    if (!factionEntry)
4991
        return;
4992
4993
    if (RepRewardRate const* repData = sObjectMgr->GetRepRewardRate(faction_id))
4994
  {
4995
       rep_change = int32((float)rep_change * repData->spell_rate);
4996
    }
4997
  // Bonus from spells that increase reputation gain
4998
 float bonus = rep_change * player->GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN) / 100.0f; // 10%
4999
    rep_change += (int32)bonus;
5000
5001
    player->GetReputationMgr().ModifyReputation(factionEntry, rep_change);
5002
}
5003
5004
void Spell::EffectQuestComplete(SpellEffIndex effIndex)
5005
{
5006
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5007
        return;
5008
5009
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5010
        return;
5011
    Player* player = unitTarget->ToPlayer();
5012
5013
    uint32 questId = m_spellInfo->Effects[effIndex].MiscValue;
5014
    if (questId)
5015
    {
5016
        Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
5017
        if (!quest)
5018
            return;
5019
5020
        uint16 logSlot = player->FindQuestSlot(questId);
5021
        if (logSlot < MAX_QUEST_LOG_SIZE)
5022
            player->AreaExploredOrEventHappens(questId);
5023
        else if (player->CanTakeQuest(quest, false))    // never rewarded before
5024
            player->CompleteQuest(questId);             // quest not in log - for internal use
5025
    }
5026
}
5027
5028
void Spell::EffectForceDeselect(SpellEffIndex /*effIndex*/)
5029
{
5030
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
5031
        return;
5032
5033
    WorldPacket data(SMSG_CLEAR_TARGET, 8);
5034
    data << uint64(m_caster->GetGUID());
5035
    m_caster->SendMessageToSet(&data, true);
5036
}
5037
5038
void Spell::EffectSelfResurrect(SpellEffIndex effIndex)
5039
{
5040
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
5041
        return;
5042
5043
    if (!m_caster || m_caster->isAlive())
5044
        return;
5045
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
5046
        return;
5047
    if (!m_caster->IsInWorld())
5048
        return;
5049
5050
    uint32 health = 0;
5051
    uint32 mana = 0;
5052
5053
    // flat case
5054
    if (damage < 0)
5055
    {
5056
        health = uint32(-damage);
5057
        mana = m_spellInfo->Effects[effIndex].MiscValue;
5058
    }
5059
    // percent case
5060
    else
5061
    {
5062
        health = m_caster->CountPctFromMaxHealth(damage);
5063
        if (m_caster->GetMaxPower(POWER_MANA) > 0)
5064
            mana = CalculatePct(m_caster->GetMaxPower(POWER_MANA), damage);
5065
    }
5066
5067
    Player* player = m_caster->ToPlayer();
5068
    player->ResurrectPlayer(0.0f);
5069
5070
    player->SetHealth(health);
5071
    player->SetPower(POWER_MANA, mana);
5072
    player->SetPower(POWER_RAGE, 0);
5073
    player->SetPower(POWER_ENERGY, player->GetMaxPower(POWER_ENERGY));
5074
5075
    player->SpawnCorpseBones();
5076
}
5077
5078
void Spell::EffectSkinning(SpellEffIndex /*effIndex*/)
5079
{
5080
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5081
        return;
5082
5083
    if (unitTarget->GetTypeId() != TYPEID_UNIT)
5084
        return;
5085
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
5086
        return;
5087
5088
    Creature* creature = unitTarget->ToCreature();
5089
    int32 targetLevel = creature->getLevel();
5090
5091
    uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();
5092
5093
    m_caster->ToPlayer()->SendLoot(creature->GetGUID(), LOOT_SKINNING);
5094
    creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5095
5096
    int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5097
5098
    int32 skillValue = m_caster->ToPlayer()->GetPureSkillValue(skill);
5099
5100
    // Double chances for elites
5101
    m_caster->ToPlayer()->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1);
5102
}
5103
5104
void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
5105
{
5106
    if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
5107
    {
5108
        if (!unitTarget)
5109
            return;
5110
5111
        float angle = unitTarget->GetRelativeAngle(m_caster);
5112
        Position pos;
5113
5114
        unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
5115
        unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetObjectSize(), angle);
5116
5117
        m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ + unitTarget->GetObjectSize());
5118
    }
5119
5120
    if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET)
5121
    {
5122
        if (!unitTarget)
5123
            return;
5124
5125
        // not all charge effects used in negative spells
5126
        if (!m_spellInfo->IsPositive() && m_caster->GetTypeId() == TYPEID_PLAYER)
5127
            m_caster->Attack(unitTarget, true);
5128
    }
5129
}
5130
5131
void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/)
5132
{
5133
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
5134
        return;
5135
5136
    if (m_targets.HasDst())
5137
    {
5138
        Position pos;
5139
        destTarget->GetPosition(&pos);
5140
        float angle = m_caster->GetRelativeAngle(pos.GetPositionX(), pos.GetPositionY());
5141
        float dist = m_caster->GetDistance(pos);
5142
        m_caster->GetFirstCollisionPosition(pos, dist, angle);
5143
5144
        m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
5145
    }
5146
}
5147
5148
void Spell::EffectKnockBack(SpellEffIndex effIndex)
5149
{
5150
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5151
        return;
5152
5153
    if (!unitTarget)
5154
        return;
5155
5156
    if (Creature* creatureTarget = unitTarget->ToCreature())
5157
        if (creatureTarget->isWorldBoss() || creatureTarget->IsDungeonBoss())
5158
            return;
5159
5160
    // Spells with SPELL_EFFECT_KNOCK_BACK(like Thunderstorm) can't knoback target if target has ROOT/STUN
5161
    if (unitTarget->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
5162
        return;
5163
5164
    // Typhoon
5165
    if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x01000000)
5166
    {
5167
        // Glyph of Typhoon
5168
        if (m_caster->HasAura(62135))
5169
            return;
5170
    }
5171
5172
    // Thunderstorm
5173
    if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[1] & 0x00002000)
5174
    {
5175
        // Glyph of Thunderstorm
5176
        if (m_caster->HasAura(62132))
5177
            return;
5178
    }
5179
5180
    // Instantly interrupt non melee spells being casted
5181
    if (unitTarget->IsNonMeleeSpellCasted(true))
5182
        unitTarget->InterruptNonMeleeSpells(true);
5183
5184
    float ratio = 0.1f;
5185
    float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue) * ratio;
5186
    float speedz = float(damage) * ratio;
5187
    if (speedxy < 0.1f && speedz < 0.1f)
5188
        return;
5189
5190
    float x, y;
5191
    if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_KNOCK_BACK_DEST)
5192
    {
5193
        if (m_targets.HasDst())
5194
            destTarget->GetPosition(x, y);
5195
        else
5196
            return;
5197
    }
5198
    else //if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_KNOCK_BACK)
5199
    {
5200
        m_caster->GetPosition(x, y);
5201
    }
5202
5203
    unitTarget->KnockbackFrom(x, y, speedxy, speedz);
5204
}
5205
5206
void Spell::EffectLeapBack(SpellEffIndex effIndex)
5207
{
5208
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
5209
        return;
5210
5211
    if (!unitTarget)
5212
        return;
5213
5214
    float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue)/10;
5215
    float speedz = float(damage/10);
5216
    //1891: Disengage
5217
    m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellIconID != 1891);
5218
}
5219
5220
void Spell::EffectQuestClear(SpellEffIndex effIndex)
5221
{
5222
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5223
        return;
5224
5225
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5226
        return;
5227
    Player* player = unitTarget->ToPlayer();
5228
5229
    uint32 quest_id = m_spellInfo->Effects[effIndex].MiscValue;
5230
5231
    Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id);
5232
5233
    if (!quest)
5234
        return;
5235
5236
    // Player has never done this quest
5237
    if (player->GetQuestStatus(quest_id) == QUEST_STATUS_NONE)
5238
        return;
5239
5240
    // remove all quest entries for 'entry' from quest log
5241
    for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
5242
    {
5243
        uint32 logQuest = player->GetQuestSlotQuestId(slot);
5244
        if (logQuest == quest_id)
5245
        {
5246
            player->SetQuestSlot(slot, 0);
5247
5248
            // we ignore unequippable quest items in this case, it's still be equipped
5249
            player->TakeQuestSourceItem(logQuest, false);
5250
        }
5251
    }
5252
5253
    player->RemoveActiveQuest(quest_id);
5254
    player->RemoveRewardedQuest(quest_id);
5255
}
5256
5257
void Spell::EffectSendTaxi(SpellEffIndex effIndex)
5258
{
5259
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5260
        return;
5261
5262
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5263
        return;
5264
5265
    unitTarget->ToPlayer()->ActivateTaxiPathTo(m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id);
5266
}
5267
5268
void Spell::EffectPullTowards(SpellEffIndex effIndex)
5269
{
5270
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5271
        return;
5272
5273
    if (!unitTarget)
5274
        return;
5275
5276
    float speedZ = (float)(m_spellInfo->Effects[effIndex].CalcValue() / 10);
5277
    float speedXY = (float)(m_spellInfo->Effects[effIndex].MiscValue/10);
5278
    Position pos;
5279
    if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_PULL_TOWARDS_DEST)
5280
    {
5281
        if (m_targets.HasDst())
5282
            pos.Relocate(*destTarget);
5283
        else
5284
            return;
5285
    }
5286
    else //if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_PULL_TOWARDS)
5287
    {
5288
        pos.Relocate(m_caster);
5289
    }
5290
5291
    unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ);
5292
}
5293
5294
void Spell::EffectDispelMechanic(SpellEffIndex effIndex)
5295
{
5296
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5297
        return;
5298
5299
    if (!unitTarget)
5300
        return;
5301
5302
    uint32 mechanic = m_spellInfo->Effects[effIndex].MiscValue;
5303
5304
    std::queue < std::pair < uint32, uint64 > > dispel_list;
5305
5306
    Unit::AuraMap const& auras = unitTarget->GetOwnedAuras();
5307
    for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
5308
    {
5309
        Aura* aura = itr->second;
5310
        if (!aura->GetApplicationOfTarget(unitTarget->GetGUID()))
5311
            continue;
5312
        if (roll_chance_i(aura->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster))))
5313
            if ((aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << mechanic)))
5314
                dispel_list.push(std::make_pair(aura->GetId(), aura->GetCasterGUID()));
5315
    }
5316
5317
    for (; dispel_list.size(); dispel_list.pop())
5318
    {
5319
        unitTarget->RemoveAura(dispel_list.front().first, dispel_list.front().second, 0, AURA_REMOVE_BY_ENEMY_SPELL);
5320
    }
5321
}
5322
5323
void Spell::EffectSummonDeadPet(SpellEffIndex /*effIndex*/)
5324
{
5325
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
5326
        return;
5327
5328
    Player* player = m_caster->ToPlayer();
5329
    if (!player)
5330
        return;
5331
5332
    Pet* pet = player->GetPet();
5333
    if (pet && pet->isAlive())
5334
        return;
5335
5336
    if (damage < 0)
5337
        return;
5338
5339
    float x, y, z;
5340
    player->GetPosition(x, y, z);
5341
    if (!pet)
5342
    {
5343
        player->SummonPet(0, x, y, z, player->GetOrientation(), SUMMON_PET, 0);
5344
        pet = player->GetPet();
5345
    }
5346
    if (!pet)
5347
        return;
5348
5349
    player->GetMap()->CreatureRelocation(pet, x, y, z, player->GetOrientation());
5350
5351
    pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
5352
    pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5353
    pet->setDeathState(ALIVE);
5354
    pet->ClearUnitState(uint32(UNIT_STATE_ALL_STATE));
5355
    pet->SetHealth(pet->CountPctFromMaxHealth(damage));
5356
5357
    //pet->AIM_Initialize();
5358
    //player->PetSpellInitialize();
5359
    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5360
}
5361
5362
void Spell::EffectDestroyAllTotems(SpellEffIndex /*effIndex*/)
5363
{
5364
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
5365
        return;
5366
5367
    int32 mana = 0;
5368
    for (uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot)
5369
    {
5370
        if (!m_caster->m_SummonSlot[slot])
5371
            continue;
5372
5373
        Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_SummonSlot[slot]);
5374
        if (totem && totem->isTotem())
5375
        {
5376
            uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
5377
            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
5378
            if (spellInfo)
5379
            {
5380
                mana += spellInfo->ManaCost;
5381
                mana += int32(CalculatePct(m_caster->GetCreateMana(), spellInfo->ManaCostPercentage));
5382
            }
5383
            totem->ToTotem()->UnSummon();
5384
        }
5385
    }
5386
    ApplyPct(mana, damage);
5387
    if (mana)
5388
        m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true);
5389
}
5390
5391
void Spell::EffectDurabilityDamage(SpellEffIndex effIndex)
5392
{
5393
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5394
        return;
5395
5396
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5397
        return;
5398
5399
    int32 slot = m_spellInfo->Effects[effIndex].MiscValue;
5400
5401
    // -1 means all player equipped items and -2 all items
5402
    if (slot < 0)
5403
    {
5404
        unitTarget->ToPlayer()->DurabilityPointsLossAll(damage, (slot < -1));
5405
        ExecuteLogEffectDurabilityDamage(effIndex, unitTarget, -1, -1);
5406
        return;
5407
    }
5408
5409
    // invalid slot value
5410
    if (slot >= INVENTORY_SLOT_BAG_END)
5411
        return;
5412
5413
    if (Item* item = unitTarget->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
5414
    {
5415
        unitTarget->ToPlayer()->DurabilityPointsLoss(item, damage);
5416
        ExecuteLogEffectDurabilityDamage(effIndex, unitTarget, item->GetEntry(), slot);
5417
    }
5418
}
5419
5420
void Spell::EffectDurabilityDamagePCT(SpellEffIndex effIndex)
5421
{
5422
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5423
        return;
5424
5425
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5426
        return;
5427
5428
    int32 slot = m_spellInfo->Effects[effIndex].MiscValue;
5429
5430
    // FIXME: some spells effects have value -1/-2
5431
    // Possibly its mean -1 all player equipped items and -2 all items
5432
    if (slot < 0)
5433
    {
5434
        unitTarget->ToPlayer()->DurabilityLossAll(float(damage) / 100.0f, (slot < -1));
5435
        return;
5436
    }
5437
5438
    // invalid slot value
5439
    if (slot >= INVENTORY_SLOT_BAG_END)
5440
        return;
5441
5442
    if (damage <= 0)
5443
        return;
5444
5445
    if (Item* item = unitTarget->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
5446
        unitTarget->ToPlayer()->DurabilityLoss(item, float(damage) / 100.0f);
5447
}
5448
5449
void Spell::EffectModifyThreatPercent(SpellEffIndex /*effIndex*/)
5450
{
5451
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5452
        return;
5453
5454
    if (!unitTarget)
5455
        return;
5456
5457
    unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
5458
}
5459
5460
void Spell::EffectTransmitted(SpellEffIndex effIndex)
5461
{
5462
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
5463
        return;
5464
5465
    uint32 name_id = m_spellInfo->Effects[effIndex].MiscValue;
5466
5467
    GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id);
5468
5469
    if (!goinfo)
5470
    {
5471
        sLog->outError(LOG_FILTER_SQL, "Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast", name_id, m_spellInfo->Id);
5472
        return;
5473
    }
5474
5475
    float fx, fy, fz;
5476
5477
    if (m_targets.HasDst())
5478
        destTarget->GetPosition(fx, fy, fz);
5479
    //FIXME: this can be better check for most objects but still hack
5480
    else if (m_spellInfo->Effects[effIndex].HasRadius() && m_spellInfo->Speed == 0)
5481
    {
5482
        float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_originalCaster);
5483
        m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
5484
    }
5485
    else
5486
    {
5487
        //GO is always friendly to it's creator, get range for friends
5488
        float min_dis = m_spellInfo->GetMinRange(true);
5489
        float max_dis = m_spellInfo->GetMaxRange(true);
5490
        float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
5491
5492
        m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
5493
    }
5494
5495
    Map* cMap = m_caster->GetMap();
5496
    if (goinfo->type == GAMEOBJECT_TYPE_FISHINGNODE || goinfo->type == GAMEOBJECT_TYPE_FISHINGHOLE)
5497
    {
5498
        LiquidData liqData;
5499
        if (!cMap->IsInWater(fx, fy, fz + 1.f/* -0.5f */, &liqData))             // Hack to prevent fishing bobber from failing to land on fishing hole
5500
        { // but this is not proper, we really need to ignore not materialized objects
5501
            SendCastResult(SPELL_FAILED_NOT_HERE);
5502
            SendChannelUpdate(0);
5503
            return;
5504
        }
5505
5506
        // replace by water level in this case
5507
        //fz = cMap->GetWaterLevel(fx, fy);
5508
        fz = liqData.level;
5509
    }
5510
    // if gameobject is summoning object, it should be spawned right on caster's position
5511
    else if (goinfo->type == GAMEOBJECT_TYPE_SUMMONING_RITUAL)
5512
    {
5513
        m_caster->GetPosition(fx, fy, fz);
5514
    }
5515
5516
    GameObject* pGameObj = new GameObject;
5517
5518
    if (!pGameObj->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
5519
        m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
5520
    {
5521
        delete pGameObj;
5522
        return;
5523
    }
5524
5525
    int32 duration = m_spellInfo->GetDuration();
5526
5527
    switch (goinfo->type)
5528
    {
5529
        case GAMEOBJECT_TYPE_FISHINGNODE:
5530
        {
5531
            m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pGameObj->GetGUID());
5532
            m_caster->AddGameObject(pGameObj);              // will removed at spell cancel
5533
5534
            // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
5535
            // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
5536
            int32 lastSec = 0;
5537
            switch (urand(0, 3))
5538
            {
5539
                case 0: lastSec =  3; break;
5540
                case 1: lastSec =  7; break;
5541
                case 2: lastSec = 13; break;
5542
                case 3: lastSec = 17; break;
5543
            }
5544
5545
            duration = duration - lastSec*IN_MILLISECONDS + FISHING_BOBBER_READY_TIME*IN_MILLISECONDS;
5546
            break;
5547
        }
5548
        case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
5549
        {
5550
            if (m_caster->GetTypeId() == TYPEID_PLAYER)
5551
            {
5552
                pGameObj->AddUniqueUse(m_caster->ToPlayer());
5553
                m_caster->AddGameObject(pGameObj);      // will be removed at spell cancel
5554
            }
5555
            break;
5556
        }
5557
        case GAMEOBJECT_TYPE_DUEL_ARBITER: // 52991
5558
            m_caster->AddGameObject(pGameObj);
5559
            break;
5560
        case GAMEOBJECT_TYPE_FISHINGHOLE:
5561
        case GAMEOBJECT_TYPE_CHEST:
5562
        default:
5563
            break;
5564
    }
5565
5566
    pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
5567
5568
    pGameObj->SetOwnerGUID(m_caster->GetGUID());
5569
5570
    //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
5571
    pGameObj->SetSpellId(m_spellInfo->Id);
5572
5573
    ExecuteLogEffectSummonObject(effIndex, pGameObj);
5574
5575
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AddObject at SpellEfects.cpp EffectTransmitted");
5576
    //m_caster->AddGameObject(pGameObj);
5577
    //m_ObjToDel.push_back(pGameObj);
5578
5579
    cMap->AddToMap(pGameObj);
5580
5581
    if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
5582
    {
5583
        GameObject* linkedGO = new GameObject;
5584
        if (linkedGO->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
5585
            m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
5586
        {
5587
            linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
5588
            //linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
5589
            linkedGO->SetSpellId(m_spellInfo->Id);
5590
            linkedGO->SetOwnerGUID(m_caster->GetGUID());
5591
5592
            ExecuteLogEffectSummonObject(effIndex, linkedGO);
5593
5594
            linkedGO->GetMap()->AddToMap(linkedGO);
5595
        }
5596
        else
5597
        {
5598
            delete linkedGO;
5599
            linkedGO = NULL;
5600
            return;
5601
        }
5602
    }
5603
}
5604
5605
void Spell::EffectProspecting(SpellEffIndex /*effIndex*/)
5606
{
5607
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5608
        return;
5609
5610
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
5611
        return;
5612
5613
    Player* p_caster = (Player*)m_caster;
5614
    if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_PROTO_FLAG_PROSPECTABLE))
5615
        return;
5616
5617
    if (itemTarget->GetCount() < 5)
5618
        return;
5619
5620
    if (sWorld->getBoolConfig(CONFIG_SKILL_PROSPECTING))
5621
    {
5622
        uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
5623
        uint32 reqSkillValue = itemTarget->GetTemplate()->RequiredSkillRank;
5624
        p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
5625
    }
5626
5627
    m_caster->ToPlayer()->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
5628
}
5629
5630
void Spell::EffectMilling(SpellEffIndex /*effIndex*/)
5631
{
5632
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5633
        return;
5634
5635
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
5636
        return;
5637
5638
    Player* p_caster = (Player*)m_caster;
5639
    if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_PROTO_FLAG_MILLABLE))
5640
        return;
5641
5642
    if (itemTarget->GetCount() < 5)
5643
        return;
5644
5645
    if (sWorld->getBoolConfig(CONFIG_SKILL_MILLING))
5646
    {
5647
        uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
5648
        uint32 reqSkillValue = itemTarget->GetTemplate()->RequiredSkillRank;
5649
        p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
5650
    }
5651
5652
    m_caster->ToPlayer()->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
5653
}
5654
5655
void Spell::EffectSkill(SpellEffIndex /*effIndex*/)
5656
{
5657
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
5658
        return;
5659
5660
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "WORLD: SkillEFFECT");
5661
}
5662
5663
/* There is currently no need for this effect. We handle it in Battleground.cpp
5664
   If we would handle the resurrection here, the spiritguide would instantly disappear as the
5665
   player revives, and so we wouldn't see the spirit heal visual effect on the npc.
5666
   This is why we use a half sec delay between the visual effect and the resurrection itself */
5667
void Spell::EffectSpiritHeal(SpellEffIndex /*effIndex*/)
5668
{
5669
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5670
        return;
5671
5672
    /*
5673
    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
5674
        return;
5675
    if (!unitTarget->IsInWorld())
5676
        return;
5677
5678
    //m_spellInfo->Effects[i].BasePoints; == 99 (percent?)
5679
    //unitTarget->ToPlayer()->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
5680
    unitTarget->ToPlayer()->ResurrectPlayer(1.0f);
5681
    unitTarget->ToPlayer()->SpawnCorpseBones();
5682
    */
5683
}
5684
5685
// remove insignia spell effect
5686
void Spell::EffectSkinPlayerCorpse(SpellEffIndex /*effIndex*/)
5687
{
5688
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5689
        return;
5690
5691
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Effect: SkinPlayerCorpse");
5692
    if ((m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()))
5693
        return;
5694
5695
    unitTarget->ToPlayer()->RemovedInsignia((Player*)m_caster);
5696
}
5697
5698
void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
5699
{
5700
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5701
        return;
5702
5703
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Effect: StealBeneficialBuff");
5704
5705
    if (!unitTarget || unitTarget == m_caster)                 // can't steal from self
5706
        return;
5707
5708
    DispelChargesList steal_list;
5709
5710
    // Create dispel mask by dispel type
5711
    uint32 dispelMask  = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[effIndex].MiscValue));
5712
    Unit::AuraMap const& auras = unitTarget->GetOwnedAuras();
5713
    for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
5714
    {
5715
        Aura* aura = itr->second;
5716
        AuraApplication * aurApp = aura->GetApplicationOfTarget(unitTarget->GetGUID());
5717
        if (!aurApp)
5718
            continue;
5719
5720
        if ((aura->GetSpellInfo()->GetDispelMask()) & dispelMask)
5721
        {
5722
            // Need check for passive? this
5723
            if (!aurApp->IsPositive() || aura->IsPassive() || aura->GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_NOT_STEALABLE)
5724
                continue;
5725
5726
            // The charges / stack amounts don't count towards the total number of auras that can be dispelled.
5727
            // Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
5728
            // Polymorph instead of 1 / (5 + 1) -> 16%.
5729
            bool dispel_charges = aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES;
5730
            uint8 charges = dispel_charges ? aura->GetCharges() : aura->GetStackAmount();
5731
            if (charges > 0)
5732
                steal_list.push_back(std::make_pair(aura, charges));
5733
        }
5734
    }
5735
5736
    if (steal_list.empty())
5737
        return;
5738
5739
    // Ok if exist some buffs for dispel try dispel it
5740
    uint32 failCount = 0;
5741
    DispelList success_list;
5742
    WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4);
5743
    // dispel N = damage buffs (or while exist buffs for dispel)
5744
    for (int32 count = 0; count < damage && !steal_list.empty();)
5745
    {
5746
        // Random select buff for dispel
5747
        DispelChargesList::iterator itr = steal_list.begin();
5748
        std::advance(itr, urand(0, steal_list.size() - 1));
5749
5750
        int32 chance = itr->first->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster));
5751
        // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
5752
        if (!chance)
5753
        {
5754
            steal_list.erase(itr);
5755
            continue;
5756
        }
5757
        else
5758
        {
5759
            if (roll_chance_i(chance))
5760
            {
5761
                success_list.push_back(std::make_pair(itr->first->GetId(), itr->first->GetCasterGUID()));
5762
                --itr->second;
5763
                if (itr->second <= 0)
5764
                    steal_list.erase(itr);
5765
            }
5766
            else
5767
            {
5768
                if (!failCount)
5769
                {
5770
                    // Failed to dispell
5771
                    dataFail << uint64(m_caster->GetGUID());            // Caster GUID
5772
                    dataFail << uint64(unitTarget->GetGUID());          // Victim GUID
5773
                    dataFail << uint32(m_spellInfo->Id);                // dispel spell id
5774
                }
5775
                ++failCount;
5776
                dataFail << uint32(itr->first->GetId());                         // Spell Id
5777
            }
5778
            ++count;
5779
        }
5780
    }
5781
5782
    if (failCount)
5783
        m_caster->SendMessageToSet(&dataFail, true);
5784
5785
    if (success_list.empty())
5786
        return;
5787
5788
    WorldPacket dataSuccess(SMSG_SPELLSTEALLOG, 8+8+4+1+4+damage*5);
5789
    dataSuccess.append(unitTarget->GetPackGUID());  // Victim GUID
5790
    dataSuccess.append(m_caster->GetPackGUID());    // Caster GUID
5791
    dataSuccess << uint32(m_spellInfo->Id);         // dispel spell id
5792
    dataSuccess << uint8(0);                        // not used
5793
    dataSuccess << uint32(success_list.size());     // count
5794
    for (DispelList::iterator itr = success_list.begin(); itr!=success_list.end(); ++itr)
5795
    {
5796
        dataSuccess << uint32(itr->first);          // Spell Id
5797
        dataSuccess << uint8(0);                    // 0 - steals !=0 transfers
5798
        unitTarget->RemoveAurasDueToSpellBySteal(itr->first, itr->second, m_caster);
5799
    }
5800
    m_caster->SendMessageToSet(&dataSuccess, true);
5801
}
5802
5803
void Spell::EffectKillCreditPersonal(SpellEffIndex effIndex)
5804
{
5805
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5806
        return;
5807
5808
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5809
        return;
5810
5811
    unitTarget->ToPlayer()->KilledMonsterCredit(m_spellInfo->Effects[effIndex].MiscValue, 0);
5812
}
5813
5814
void Spell::EffectKillCredit(SpellEffIndex effIndex)
5815
{
5816
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5817
        return;
5818
5819
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5820
        return;
5821
5822
    int32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
5823
    if (!creatureEntry)
5824
    {
5825
        if (m_spellInfo->Id == 42793) // Burn Body
5826
            creatureEntry = 24008; // Fallen Combatant
5827
    }
5828
5829
    if (creatureEntry)
5830
        unitTarget->ToPlayer()->RewardPlayerAndGroupAtEvent(creatureEntry, unitTarget);
5831
}
5832
5833
void Spell::EffectQuestFail(SpellEffIndex effIndex)
5834
{
5835
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5836
        return;
5837
5838
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5839
        return;
5840
5841
    unitTarget->ToPlayer()->FailQuest(m_spellInfo->Effects[effIndex].MiscValue);
5842
}
5843
5844
void Spell::EffectQuestStart(SpellEffIndex effIndex)
5845
{
5846
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5847
        return;
5848
5849
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5850
        return;
5851
5852
    Player* player = unitTarget->ToPlayer();
5853
    if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(m_spellInfo->Effects[effIndex].MiscValue))
5854
    {
5855
        if (player->CanTakeQuest(qInfo, false) && player->CanAddQuest(qInfo, false))
5856
        {
5857
            player->AddQuest(qInfo, NULL);
5858
        }
5859
    }
5860
}
5861
5862
void Spell::EffectActivateRune(SpellEffIndex effIndex)
5863
{
5864
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
5865
        return;
5866
5867
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
5868
        return;
5869
5870
    Player* player = m_caster->ToPlayer();
5871
5872
    if (player->getClass() != CLASS_DEATH_KNIGHT)
5873
        return;
5874
5875
    // needed later
5876
    m_runesState = m_caster->ToPlayer()->GetRunesState();
5877
5878
    uint32 count = damage;
5879
    if (count == 0) count = 1;
5880
    for (uint32 j = 0; j < MAX_RUNES && count > 0; ++j)
5881
    {
5882
        if (player->GetRuneCooldown(j) && player->GetCurrentRune(j) == RuneType(m_spellInfo->Effects[effIndex].MiscValue))
5883
        {
5884
            if (m_spellInfo->Id == 45529)
5885
                if (player->GetBaseRune(j) != RuneType(m_spellInfo->Effects[effIndex].MiscValueB))
5886
                    continue;
5887
            player->SetRuneCooldown(j, 0);
5888
            --count;
5889
        }
5890
    }
5891
5892
    // Blood Tap
5893
    if (m_spellInfo->Id == 45529 && count > 0)
5894
    {
5895
        for (uint32 l = 0; l < MAX_RUNES && count > 0; ++l)
5896
        {
5897
            // Check if both runes are on cd as that is the only time when this needs to come into effect
5898
            if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)))
5899
            {
5900
                // Should always update the rune with the lowest cd
5901
                if (player->GetRuneCooldown(l) >= player->GetRuneCooldown(l+1))
5902
                    l++;
5903
                player->SetRuneCooldown(l, 0);
5904
                --count;
5905
                // is needed to push through to the client that the rune is active
5906
                player->ResyncRunes(MAX_RUNES);
5907
            }
5908
            else
5909
                break;
5910
        }
5911
    }
5912
5913
    // Empower rune weapon
5914
    if (m_spellInfo->Id == 47568)
5915
    {
5916
        // Need to do this just once
5917
        if (effIndex != 0)
5918
            return;
5919
5920
        for (uint32 i = 0; i < MAX_RUNES; ++i)
5921
        {
5922
            if (player->GetRuneCooldown(i) && (player->GetCurrentRune(i) == RUNE_FROST ||  player->GetCurrentRune(i) == RUNE_DEATH))
5923
                player->SetRuneCooldown(i, 0);
5924
        }
5925
    }
5926
}
5927
5928
void Spell::EffectCreateTamedPet(SpellEffIndex effIndex)
5929
{
5930
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5931
        return;
5932
5933
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->GetPetGUID() || unitTarget->getClass() != CLASS_HUNTER)
5934
        return;
5935
5936
    uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
5937
    Pet* pet = unitTarget->CreateTamedPetFrom(creatureEntry, m_spellInfo->Id);
5938
    if (!pet)
5939
        return;
5940
5941
    // add to world
5942
    pet->GetMap()->AddToMap(pet->ToCreature());
5943
5944
    // unitTarget has pet now
5945
    unitTarget->SetMinion(pet, true);
5946
5947
    pet->InitTalentForLevel();
5948
5949
    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
5950
    {
5951
        pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5952
        unitTarget->ToPlayer()->PetSpellInitialize();
5953
    }
5954
}
5955
5956
void Spell::EffectDiscoverTaxi(SpellEffIndex effIndex)
5957
{
5958
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5959
        return;
5960
5961
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5962
        return;
5963
    uint32 nodeid = m_spellInfo->Effects[effIndex].MiscValue;
5964
    if (sTaxiNodesStore.LookupEntry(nodeid))
5965
        unitTarget->ToPlayer()->GetSession()->SendDiscoverNewTaxiNode(nodeid);
5966
}
5967
5968
void Spell::EffectTitanGrip(SpellEffIndex /*effIndex*/)
5969
{
5970
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
5971
        return;
5972
5973
    if (m_caster->GetTypeId() == TYPEID_PLAYER)
5974
        m_caster->ToPlayer()->SetCanTitanGrip(true);
5975
}
5976
5977
void Spell::EffectRedirectThreat(SpellEffIndex /*effIndex*/)
5978
{
5979
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5980
        return;
5981
5982
    if (unitTarget)
5983
        m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID());
5984
}
5985
5986
void Spell::EffectGameObjectDamage(SpellEffIndex /*effIndex*/)
5987
{
5988
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
5989
        return;
5990
5991
    if (!gameObjTarget)
5992
        return;
5993
5994
    Unit* caster = m_originalCaster;
5995
    if (!caster)
5996
        return;
5997
5998
    FactionTemplateEntry const* casterFaction = caster->getFactionTemplateEntry();
5999
    FactionTemplateEntry const* targetFaction = sFactionTemplateStore.LookupEntry(gameObjTarget->GetUInt32Value(GAMEOBJECT_FACTION));
6000
    // Do not allow to damage GO's of friendly factions (ie: Wintergrasp Walls/Ulduar Storm Beacons)
6001
    if ((casterFaction && targetFaction && !casterFaction->IsFriendlyTo(*targetFaction)) || !targetFaction)
6002
        gameObjTarget->ModifyHealth(-damage, caster, GetSpellInfo()->Id);
6003
}
6004
6005
void Spell::EffectGameObjectRepair(SpellEffIndex /*effIndex*/)
6006
{
6007
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6008
        return;
6009
6010
    if (!gameObjTarget)
6011
        return;
6012
6013
    gameObjTarget->ModifyHealth(damage, m_caster);
6014
}
6015
6016
void Spell::EffectGameObjectSetDestructionState(SpellEffIndex effIndex)
6017
{
6018
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6019
        return;
6020
6021
    if (!gameObjTarget || !m_originalCaster)
6022
        return;
6023
6024
    Player* player = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself();
6025
    gameObjTarget->SetDestructibleState(GameObjectDestructibleState(m_spellInfo->Effects[effIndex].MiscValue), player, true);
6026
}
6027
6028
void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numGuardians)
6029
{
6030
    Unit* caster = m_originalCaster;
6031
    if (!caster)
6032
        return;
6033
6034
    if (caster->isTotem())
6035
        caster = caster->ToTotem()->GetOwner();
6036
6037
    // in another case summon new
6038
    uint8 level = caster->getLevel();
6039
6040
    // level of pet summoned using engineering item based at engineering skill level
6041
    if (m_CastItem && caster->GetTypeId() == TYPEID_PLAYER)
6042
        if (ItemTemplate const* proto = m_CastItem->GetTemplate())
6043
            if (proto->RequiredSkill == SKILL_ENGINEERING)
6044
                if (uint16 skill202 = caster->ToPlayer()->GetSkillValue(SKILL_ENGINEERING))
6045
                    level = skill202 / 5;
6046
6047
    float radius = 5.0f;
6048
    int32 duration = m_spellInfo->GetDuration();
6049
6050
    if (Player* modOwner = m_originalCaster->GetSpellModOwner())
6051
        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
6052
6053
    //TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
6054
    Map* map = caster->GetMap();
6055
6056
    for (uint32 count = 0; count < numGuardians; ++count)
6057
    {
6058
        Position pos;
6059
        if (count == 0)
6060
            pos = *destTarget;
6061
        else
6062
            // randomize position for multiple summons
6063
            m_caster->GetRandomPoint(*destTarget, radius, pos);
6064
6065
        TempSummon* summon = map->SummonCreature(entry, pos, properties, duration, caster, m_spellInfo->Id);
6066
        if (!summon)
6067
            return;
6068
        if (summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
6069
            ((Guardian*)summon)->InitStatsForLevel(level);
6070
6071
        if (properties && properties->Category == SUMMON_CATEGORY_ALLY)
6072
            summon->setFaction(caster->getFaction());
6073
6074
        if (summon->HasUnitTypeMask(UNIT_MASK_MINION) && m_targets.HasDst())
6075
            ((Minion*)summon)->SetFollowAngle(m_caster->GetAngle(summon));
6076
6077
        if (summon->GetEntry() == 27893)
6078
        {
6079
            if (uint32 weapon = m_caster->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID))
6080
            {
6081
                summon->SetDisplayId(11686);
6082
                summon->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, weapon);
6083
            }
6084
            else
6085
                summon->SetDisplayId(1126);
6086
        }
6087
6088
        summon->AI()->EnterEvadeMode();
6089
6090
        ExecuteLogEffectSummonObject(i, summon);
6091
    }
6092
}
6093
6094
void Spell::EffectRenamePet(SpellEffIndex /*effIndex*/)
6095
{
6096
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6097
        return;
6098
6099
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
6100
        !unitTarget->ToCreature()->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
6101
        return;
6102
6103
    unitTarget->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
6104
}
6105
6106
void Spell::EffectPlayMusic(SpellEffIndex effIndex)
6107
{
6108
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6109
        return;
6110
6111
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6112
        return;
6113
6114
    uint32 soundid = m_spellInfo->Effects[effIndex].MiscValue;
6115
6116
    if (!sSoundEntriesStore.LookupEntry(soundid))
6117
    {
6118
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectPlayMusic: Sound (Id: %u) not exist in spell %u.", soundid, m_spellInfo->Id);
6119
        return;
6120
    }
6121
6122
    WorldPacket data(SMSG_PLAY_MUSIC, 4);
6123
    data << uint32(soundid);
6124
    unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
6125
}
6126
6127
void Spell::EffectSpecCount(SpellEffIndex /*effIndex*/)
6128
{
6129
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6130
        return;
6131
6132
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6133
        return;
6134
6135
    unitTarget->ToPlayer()->UpdateSpecCount(damage);
6136
}
6137
6138
void Spell::EffectActivateSpec(SpellEffIndex /*effIndex*/)
6139
{
6140
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6141
        return;
6142
6143
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6144
        return;
6145
6146
    unitTarget->ToPlayer()->ActivateSpec(damage-1);  // damage is 1 or 2, spec is 0 or 1
6147
}
6148
6149
void Spell::EffectPlayerNotification(SpellEffIndex effIndex)
6150
{
6151
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6152
        return;
6153
6154
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6155
        return;
6156
6157
    switch (m_spellInfo->Id)
6158
    {
6159
        case 58730: // Restricted Flight Area
6160
        case 58600: // Restricted Flight Area
6161
            unitTarget->ToPlayer()->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE);
6162
            unitTarget->PlayDirectSound(9417); // Fel Reaver sound
6163
            break;
6164
    }
6165
6166
    uint32 soundid = m_spellInfo->Effects[effIndex].MiscValue;
6167
6168
    if (!sSoundEntriesStore.LookupEntry(soundid))
6169
    {
6170
        sLog->outError(LOG_FILTER_SPELLS_AURAS, "EffectPlayerNotification: Sound (Id: %u) not exist in spell %u.", soundid, m_spellInfo->Id);
6171
        return;
6172
    }
6173
6174
    WorldPacket data(SMSG_PLAY_SOUND, 4);
6175
    data << uint32(soundid);
6176
    unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
6177
}
6178
6179
void Spell::EffectRemoveAura(SpellEffIndex effIndex)
6180
{
6181
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6182
        return;
6183
6184
    if (!unitTarget)
6185
        return;
6186
    // there may be need of specifying casterguid of removed auras
6187
    unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].TriggerSpell);
6188
}
6189
6190
void Spell::EffectCastButtons(SpellEffIndex effIndex)
6191
{
6192
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
6193
        return;
6194
6195
    if (m_caster->GetTypeId() != TYPEID_PLAYER)
6196
        return;
6197
6198
    Player* p_caster = m_caster->ToPlayer();
6199
    uint32 button_id = m_spellInfo->Effects[effIndex].MiscValue + 132;
6200
    uint32 n_buttons = m_spellInfo->Effects[effIndex].MiscValueB;
6201
6202
    for (; n_buttons; --n_buttons, ++button_id)
6203
    {
6204
        ActionButton const* ab = p_caster->GetActionButton(button_id);
6205
        if (!ab || ab->GetType() != ACTION_BUTTON_SPELL)
6206
            continue;
6207
6208
        //! Action button data is unverified when it's set so it can be "hacked"
6209
        //! to contain invalid spells, so filter here.
6210
        uint32 spell_id = ab->GetAction();
6211
        if (!spell_id)
6212
            continue;
6213
6214
        SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
6215
        if (!spellInfo)
6216
            continue;
6217
6218
        if (!p_caster->HasSpell(spell_id) || p_caster->HasSpellCooldown(spell_id))
6219
            continue;
6220
6221
        if (!(spellInfo->AttributesEx7 & SPELL_ATTR7_SUMMON_PLAYER_TOTEM))
6222
            continue;
6223
6224
        uint32 cost = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
6225
        if (m_caster->GetPower(POWER_MANA) < cost)
6226
            continue;
6227
6228
        TriggerCastFlags triggerFlags = TriggerCastFlags(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY);
6229
        m_caster->CastSpell(m_caster, spell_id, triggerFlags);
6230
    }
6231
}
6232
6233
void Spell::EffectRechargeManaGem(SpellEffIndex /*effIndex*/)
6234
{
6235
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6236
        return;
6237
6238
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6239
        return;
6240
6241
    Player* player = m_caster->ToPlayer();
6242
6243
    if (!player)
6244
        return;
6245
6246
    uint32 item_id = m_spellInfo->Effects[EFFECT_0].ItemType;
6247
6248
    ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id);
6249
    if (!pProto)
6250
    {
6251
        player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
6252
        return;
6253
    }
6254
6255
    if (Item* pItem = player->GetItemByEntry(item_id))
6256
    {
6257
        for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
6258
            pItem->SetSpellCharges(x, pProto->Spells[x].SpellCharges);
6259
        pItem->SetState(ITEM_CHANGED, player);
6260
    }
6261
}
6262
6263
void Spell::EffectBind(SpellEffIndex effIndex)
6264
{
6265
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6266
        return;
6267
6268
    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6269
        return;
6270
6271
    Player* player = unitTarget->ToPlayer();
6272
6273
    WorldLocation homeLoc;
6274
    uint32 areaId = player->GetAreaId();
6275
6276
    if (m_spellInfo->Effects[effIndex].MiscValue)
6277
        areaId = m_spellInfo->Effects[effIndex].MiscValue;
6278
6279
    if (m_targets.HasDst())
6280
        homeLoc.WorldRelocate(*destTarget);
6281
    else
6282
    {
6283
        player->GetPosition(&homeLoc);
6284
        homeLoc.m_mapId = player->GetMapId();
6285
    }
6286
6287
    player->SetHomebind(homeLoc, areaId);
6288
6289
    // binding
6290
    WorldPacket data(SMSG_BINDPOINTUPDATE, (4+4+4+4+4));
6291
    data << float(homeLoc.GetPositionX());
6292
    data << float(homeLoc.GetPositionY());
6293
    data << float(homeLoc.GetPositionZ());
6294
    data << uint32(homeLoc.GetMapId());
6295
    data << uint32(areaId);
6296
    player->SendDirectMessage(&data);
6297
6298
    sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "EffectBind: New homebind X: %f, Y: %f, Z: %f, MapId: %u, AreaId: %u",
6299
        homeLoc.GetPositionX(), homeLoc.GetPositionY(), homeLoc.GetPositionZ(), homeLoc.GetMapId(), areaId);
6300
6301
    // zone update
6302
    data.Initialize(SMSG_PLAYERBOUND, 8+4);
6303
    data << uint64(player->GetGUID());
6304
    data << uint32(areaId);
6305
    player->SendDirectMessage(&data);
6306
}
6307
6308
void Spell::EffectSummonRaFFriend(SpellEffIndex effIndex)
6309
{
6310
    if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
6311
        return;
6312
6313
    if (m_caster->GetTypeId() != TYPEID_PLAYER || !unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6314
        return;
6315
6316
    m_caster->CastSpell(unitTarget, m_spellInfo->Effects[effIndex].TriggerSpell, true);
6317
}