[6922] Whitespace and newline fixes
[getmangos.git] / src / game / SpellAuras.cpp
bloba0a93c0791e06f69eb9b2ebc2428e32a7e9dc6fa
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "Opcodes.h"
24 #include "Log.h"
25 #include "UpdateMask.h"
26 #include "World.h"
27 #include "ObjectMgr.h"
28 #include "SpellMgr.h"
29 #include "Player.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "SpellAuras.h"
33 #include "DynamicObject.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "Policies/SingletonImp.h"
39 #include "Totem.h"
40 #include "Creature.h"
41 #include "Formulas.h"
42 #include "BattleGround.h"
43 #include "CreatureAI.h"
44 #include "Util.h"
45 #include "GridNotifiers.h"
46 #include "GridNotifiersImpl.h"
47 #include "CellImpl.h"
49 #define NULL_AURA_SLOT 0xFF
51 pAuraHandler AuraHandler[TOTAL_AURAS]=
53 &Aura::HandleNULL, // 0 SPELL_AURA_NONE
54 &Aura::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT
55 &Aura::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS
56 &Aura::HandlePeriodicDamage, // 3 SPELL_AURA_PERIODIC_DAMAGE
57 &Aura::HandleAuraDummy, // 4 SPELL_AURA_DUMMY
58 &Aura::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE
59 &Aura::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM
60 &Aura::HandleModFear, // 7 SPELL_AURA_MOD_FEAR
61 &Aura::HandlePeriodicHeal, // 8 SPELL_AURA_PERIODIC_HEAL
62 &Aura::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED
63 &Aura::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT
64 &Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT
65 &Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN
66 &Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE
67 &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
68 &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage
69 &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH
70 &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT
71 &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY
72 &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION
73 &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH
74 &Aura::HandleAuraModTotalManaPercentRegen, // 21 SPELL_AURA_OBS_MOD_MANA
75 &Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE
76 &Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL
77 &Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE
78 &Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY
79 &Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT
80 &Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE
81 &Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult
82 &Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT
83 &Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL
84 &Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED
85 &Aura::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED
86 &Aura::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED
87 &Aura::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH
88 &Aura::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY
89 &Aura::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT
90 &Aura::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY
91 &Aura::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY
92 &Aura::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY
93 &Aura::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY
94 &Aura::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY
95 &Aura::HandleAuraProcTriggerSpell, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell
96 &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor
97 &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES
98 &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES
99 &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete?
100 &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT
101 &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete?
102 &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT
103 &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete?
104 &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT
105 &Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT
106 &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH
107 &Aura::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE
108 &Aura::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE
109 &Aura::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM
110 &Aura::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE
111 &Aura::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED
112 &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
113 &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
114 &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
115 &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
116 &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete?
117 &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH
118 &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED
119 &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
120 &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM
121 &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED
122 &Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
123 &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect
124 &Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
125 &Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
126 &Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL
127 &Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult
128 &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE
129 &Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT
130 &Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY
131 &Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED
132 &Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
133 &Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT
134 &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT
135 &Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING
136 &Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE
137 &Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN
138 &Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN
139 &Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM
140 &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
141 &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT
142 &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
143 &Aura::HandleUnused, // 90 SPELL_AURA_MOD_RESIST_CHANCE Useless
144 &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
145 &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING
146 &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE
147 &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll
148 &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST
149 &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget
150 &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist
151 &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT
152 &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER
153 &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now
154 &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT
155 &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
156 &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT
157 &Aura::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK
158 &Aura::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL
159 &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER
160 &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER
161 &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER
162 &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER
163 &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT
164 &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER
165 &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
166 &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
167 &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
168 &Aura::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim
169 &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
170 &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
171 &Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus
172 &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless
173 &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
174 &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
175 &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
176 &Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE
177 &Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER
178 &Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
179 &Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
180 &Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
181 &Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET
182 &Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS
183 &Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
184 &Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
185 &Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT
186 &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
187 &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
188 &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE
189 &Aura::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus
190 &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
191 &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE
192 &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
193 &Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
194 &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
195 &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
196 &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
197 &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
198 &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete?
199 &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete?
200 &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
201 &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
202 &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK
203 &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
204 &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
205 &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
206 &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
207 &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL
208 &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
209 &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
210 &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
211 &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
212 &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
213 &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
214 &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
215 &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA
216 &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE
217 &Aura::HandleUnused, //164 useless, only one test spell
218 &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
219 &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
220 &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
221 &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
222 &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
223 &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell
224 &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
225 &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
226 &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
227 &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT)
228 &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
229 &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
230 &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM
231 &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
232 &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
233 &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
234 &Aura::HandleUnused, //181 SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS unused
235 &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
236 &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT
237 &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
238 &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
239 &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult
240 &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
241 &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
242 &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING
243 &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
244 &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
245 &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
246 &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
247 &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT)
248 &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT)
249 &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
250 &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
251 &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
252 &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
253 &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP
254 &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
255 &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
256 &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::DoAttackDamage
257 &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::DoAttackDamage
258 &Aura::HandleNULL, //205 vulnerable to school dmg?
259 &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED
260 &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
261 &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive)
262 &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS
263 &Aura::HandleNULL, //210 Commentator's Command
264 &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
265 &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
266 &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
267 &Aura::HandleNULL, //214 Tamed Pet Passive
268 &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
269 &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
270 &Aura::HandleUnused, //217 unused
271 &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
272 &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
273 &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT
274 &Aura::HandleNULL, //221 ignored
275 &Aura::HandleUnused, //222 unused
276 &Aura::HandleNULL, //223 Cold Stare
277 &Aura::HandleUnused, //224 unused
278 &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING
279 &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY
280 &Aura::HandleNULL, //227 periodic trigger spell
281 &Aura::HandleNoImmediateEffect, //228 stealth detection
282 &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
283 &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
284 &Aura::HandleNULL, //231
285 &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
286 &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
287 &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
288 &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
289 &Aura::HandleUnused, //236 unused
290 &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus
291 &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
292 &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
293 &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE
294 &Aura::HandleForceMoveForward, //241 Forces the player to move forward
295 &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING
296 &Aura::HandleUnused, //243 used by two test spells
297 &Aura::HandleComprehendLanguage, //244 Comprehend language
298 &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS
299 &Aura::HandleUnused, //246 unused
300 &Aura::HandleUnused, //247 unused
301 &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
302 &Aura::HandleNULL, //249
303 &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
304 &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE
305 &Aura::HandleUnused, //252 unused
306 &Aura::HandleUnused, //253 unused
307 &Aura::HandleUnused, //254 unused
308 &Aura::HandleUnused, //255 unused
309 &Aura::HandleUnused, //256 unused
310 &Aura::HandleUnused, //257 unused
311 &Aura::HandleUnused, //258 unused
312 &Aura::HandleUnused, //259 unused
313 &Aura::HandleUnused, //260 unused
314 &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell)
317 Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
318 m_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target),
319 m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS),
320 m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false),
321 m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false),
322 m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
324 assert(target);
326 assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
328 m_spellProto = spellproto;
330 m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff];
332 m_isPassive = IsPassiveSpell(GetId());
333 m_positive = IsPositiveEffect(GetId(), m_effIndex);
335 m_applyTime = time(NULL);
337 int32 damage;
338 if(!caster)
340 m_caster_guid = target->GetGUID();
341 damage = m_currentBasePoints+1; // stored value-1
342 m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target);
344 else
346 m_caster_guid = caster->GetGUID();
348 damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target);
349 m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target);
351 if (!damage && castItem && castItem->GetItemSuffixFactor())
353 ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
354 if(item_rand_suffix)
356 for (int k=0; k<3; k++)
358 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
359 if(pEnchant)
361 for (int t=0; t<3; t++)
362 if(pEnchant->spellid[t] == m_spellProto->Id)
364 damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 );
365 break;
369 if(damage)
370 break;
376 if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0)
377 m_permanent = true;
379 Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
381 if(!m_permanent && modOwner)
382 modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration);
384 m_duration = m_maxduration;
386 if(modOwner)
387 modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
389 sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage);
391 m_effIndex = eff;
392 SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
394 m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
396 if(m_spellProto->procCharges)
398 m_procCharges = m_spellProto->procCharges;
400 if(modOwner)
401 modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
403 else
404 m_procCharges = -1;
406 m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances &&
407 !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000));
410 Aura::~Aura()
414 AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
415 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
417 m_isAreaAura = true;
419 // caster==NULL in constructor args if target==caster in fact
420 Unit* caster_ptr = caster ? caster : target;
422 m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex]));
423 if(Player* modOwner = caster_ptr->GetSpellModOwner())
424 modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius);
426 switch(spellproto->Effect[eff])
428 case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
429 m_areaAuraType = AREA_AURA_PARTY;
430 if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
431 m_modifier.m_auraname = SPELL_AURA_NONE;
432 break;
433 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
434 m_areaAuraType = AREA_AURA_FRIEND;
435 break;
436 case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
437 m_areaAuraType = AREA_AURA_ENEMY;
438 if(target == caster_ptr)
439 m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self
440 break;
441 case SPELL_EFFECT_APPLY_AREA_AURA_PET:
442 m_areaAuraType = AREA_AURA_PET;
443 break;
444 case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
445 m_areaAuraType = AREA_AURA_OWNER;
446 if(target == caster_ptr)
447 m_modifier.m_auraname = SPELL_AURA_NONE;
448 break;
449 default:
450 sLog.outError("Wrong spell effect in AreaAura constructor");
451 ASSERT(false);
452 break;
456 AreaAura::~AreaAura()
460 PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
461 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
463 m_isPersistent = true;
466 PersistentAreaAura::~PersistentAreaAura()
470 SingleEnemyTargetAura::SingleEnemyTargetAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
471 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
473 if (caster)
474 m_casters_target_guid = caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)caster)->GetSelection() : caster->GetUInt64Value(UNIT_FIELD_TARGET);
475 else
476 m_casters_target_guid = 0;
479 SingleEnemyTargetAura::~SingleEnemyTargetAura()
483 Unit* SingleEnemyTargetAura::GetTriggerTarget() const
485 return ObjectAccessor::GetUnit(*m_target, m_casters_target_guid);
488 Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem)
490 if (IsAreaAuraEffect(spellproto->Effect[eff]))
491 return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem);
493 uint32 triggeredSpellId = spellproto->EffectTriggerSpell[eff];
495 if(SpellEntry const* triggeredSpellInfo = sSpellStore.LookupEntry(triggeredSpellId))
496 for (int i = 0; i < 3; ++i)
497 if (triggeredSpellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_ENEMY)
498 return new SingleEnemyTargetAura(spellproto, eff, currentBasePoints, target, caster, castItem);
500 return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem);
503 Unit* Aura::GetCaster() const
505 if(m_caster_guid==m_target->GetGUID())
506 return m_target;
508 //return ObjectAccessor::GetUnit(*m_target,m_caster_guid);
509 //must return caster even if it's in another grid/map
510 Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL);
511 return unit && unit->IsInWorld() ? unit : NULL;
514 void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
516 m_modifier.m_auraname = t;
517 m_modifier.m_amount = a;
518 m_modifier.m_miscvalue = miscValue;
519 m_modifier.periodictime = pt;
522 void Aura::Update(uint32 diff)
524 if (m_duration > 0)
526 m_duration -= diff;
527 if (m_duration < 0)
528 m_duration = 0;
529 m_timeCla -= diff;
531 // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras
532 // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0
533 if(GetEffIndex()==0 && m_timeCla <= 0)
535 if(Unit* caster = GetCaster())
537 Powers powertype = Powers(m_spellProto->powerType);
538 int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel();
539 m_timeCla = 1000;
540 if (manaPerSecond)
542 if(powertype==POWER_HEALTH)
543 caster->ModifyHealth(-manaPerSecond);
544 else
545 caster->ModifyPower(powertype,-manaPerSecond);
551 // Channeled aura required check distance from caster
552 if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID())
554 Unit* caster = GetCaster();
555 if(!caster)
557 m_target->RemoveAura(GetId(),GetEffIndex());
558 return;
561 // Get spell range
562 float radius;
563 SpellModOp mod;
564 if (m_spellProto->EffectRadiusIndex[GetEffIndex()])
566 radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()]));
567 mod = SPELLMOD_RADIUS;
569 else
571 radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
572 mod = SPELLMOD_RANGE;
575 if(Player* modOwner = caster->GetSpellModOwner())
576 modOwner->ApplySpellMod(GetId(), mod, radius,NULL);
578 if(!caster->IsWithinDistInMap(m_target,radius))
580 m_target->RemoveAura(GetId(),GetEffIndex());
581 return;
585 if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
587 m_periodicTimer -= diff;
588 if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
590 if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN ||
591 m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN ||
592 // Cannibalize, eating items and other spells
593 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH ||
594 // Eating items and other spells
595 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA )
597 ApplyModifier(true);
598 return;
600 // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
601 m_periodicTimer += m_modifier.periodictime;
603 if(m_isTrigger)
604 TriggerSpell();
605 else
606 PeriodicTick();
611 void AreaAura::Update(uint32 diff)
613 // update for the caster of the aura
614 if(m_caster_guid == m_target->GetGUID())
616 Unit* caster = m_target;
618 if( !caster->hasUnitState(UNIT_STAT_ISOLATED) )
620 Unit* owner = caster->GetCharmerOrOwner();
621 if (!owner)
622 owner = caster;
623 std::list<Unit *> targets;
625 switch(m_areaAuraType)
627 case AREA_AURA_PARTY:
629 Group *pGroup = NULL;
631 if (owner->GetTypeId() == TYPEID_PLAYER)
632 pGroup = ((Player*)owner)->GetGroup();
634 if( pGroup)
636 uint8 subgroup = ((Player*)owner)->GetSubGroup();
637 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
639 Player* Target = itr->getSource();
640 if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target))
642 if(caster->IsWithinDistInMap(Target, m_radius))
643 targets.push_back(Target);
644 Pet *pet = Target->GetPet();
645 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
646 targets.push_back(pet);
650 else
652 // add owner
653 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
654 targets.push_back(owner);
655 // add caster's pet
656 Unit* pet = caster->GetPet();
657 if( pet && caster->IsWithinDistInMap(pet, m_radius))
658 targets.push_back(pet);
660 break;
662 case AREA_AURA_FRIEND:
664 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
665 Cell cell(p);
666 cell.data.Part.reserved = ALL_DISTRICT;
667 cell.SetNoCreate();
669 MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius);
670 MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
671 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
672 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
673 CellLock<GridReadGuard> cell_lock(cell, p);
674 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
675 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
676 break;
678 case AREA_AURA_ENEMY:
680 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
681 Cell cell(p);
682 cell.data.Part.reserved = ALL_DISTRICT;
683 cell.SetNoCreate();
685 MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
686 MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);
687 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
688 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
689 CellLock<GridReadGuard> cell_lock(cell, p);
690 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
691 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
692 break;
694 case AREA_AURA_OWNER:
695 case AREA_AURA_PET:
697 if(owner != caster)
698 targets.push_back(owner);
699 break;
703 for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
705 if((*tIter)->HasAura(GetId(), m_effIndex))
706 continue;
708 if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
710 int32 actualBasePoints = m_currentBasePoints;
711 // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
712 if(actualSpellInfo != GetSpellProto())
713 actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
714 AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL);
715 (*tIter)->AddAura(aur);
719 Aura::Update(diff);
721 else // aura at non-caster
723 Unit * tmp_target = m_target;
724 Unit* caster = GetCaster();
725 uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
727 // WARNING: the aura may get deleted during the update
728 // DO NOT access its members after update!
729 Aura::Update(diff);
731 // remove aura if out-of-range from caster (after teleport for example)
732 // or caster is isolated or caster no longer has the aura
733 // or caster is (no longer) friendly
734 bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
735 if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
736 !caster->IsWithinDistInMap(tmp_target, m_radius) ||
737 !caster->HasAura(tmp_spellId, tmp_effIndex) ||
738 caster->IsFriendlyTo(tmp_target) != needFriendly
741 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
743 else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
745 // not check group if target == owner or target == pet
746 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
748 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
750 Group *pGroup = check ? check->GetGroup() : NULL;
751 if( pGroup )
753 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
754 if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
755 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
757 else
758 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
761 else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
763 if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
764 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
769 void PersistentAreaAura::Update(uint32 diff)
771 bool remove = false;
773 // remove the aura if its caster or the dynamic object causing it was removed
774 // or if the target moves too far from the dynamic object
775 Unit *caster = GetCaster();
776 if (caster)
778 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
779 if (dynObj)
781 if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius()))
782 remove = true;
784 else
785 remove = true;
787 else
788 remove = true;
790 Unit *tmp_target = m_target;
791 uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
793 // WARNING: the aura may get deleted during the update
794 // DO NOT access its members after update!
795 Aura::Update(diff);
797 if(remove)
798 tmp_target->RemoveAura(tmp_id, tmp_index);
801 void Aura::ApplyModifier(bool apply, bool Real)
803 AuraType aura = m_modifier.m_auraname;
805 m_in_use = true;
806 if(aura<TOTAL_AURAS)
807 (*this.*AuraHandler [aura])(apply,Real);
808 m_in_use = false;
811 void Aura::UpdateAuraDuration()
813 if(m_auraSlot >= MAX_AURAS || m_isPassive)
814 return;
816 if( m_target->GetTypeId() == TYPEID_PLAYER)
818 WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5);
819 data << (uint8)m_auraSlot << (uint32)m_duration;
820 ((Player*)m_target)->SendDirectMessage(&data);
822 data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4));
823 data.append(m_target->GetPackGUID());
824 data << uint8(m_auraSlot);
825 data << uint32(GetId());
826 data << uint32(GetAuraMaxDuration());
827 data << uint32(GetAuraDuration());
828 ((Player*)m_target)->SendDirectMessage(&data);
831 // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code
832 if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading())
833 return;
835 Unit* caster = GetCaster();
837 if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target)
838 SendAuraDurationForCaster((Player*)caster);
841 void Aura::SendAuraDurationForCaster(Player* caster)
843 WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4));
844 data.append(m_target->GetPackGUID());
845 data << uint8(m_auraSlot);
846 data << uint32(GetId());
847 data << uint32(GetAuraMaxDuration()); // full
848 data << uint32(GetAuraDuration()); // remain
849 caster->GetSession()->SendPacket(&data);
852 void Aura::_AddAura()
854 if (!GetId())
855 return;
856 if(!m_target)
857 return;
859 // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT
860 bool samespell = false;
861 bool secondaura = false;
862 uint8 slot = NULL_AURA_SLOT;
864 for(uint8 i = 0; i < 3; i++)
866 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
867 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
869 // allow use single slot only by auras from same caster
870 if(itr->second->GetCasterGUID()==GetCasterGUID())
872 samespell = true;
873 if (m_effIndex > itr->second->GetEffIndex())
874 secondaura = true;
875 slot = itr->second->GetAuraSlot();
876 break;
880 if(samespell)
881 break;
884 // not call total regen auras at adding
885 switch (m_modifier.m_auraname)
887 case SPELL_AURA_OBS_MOD_HEALTH:
888 case SPELL_AURA_OBS_MOD_MANA:
889 m_periodicTimer = m_modifier.periodictime;
890 break;
891 case SPELL_AURA_MOD_REGEN:
892 case SPELL_AURA_MOD_POWER_REGEN:
893 case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
894 m_periodicTimer = 5000;
895 break;
898 // register aura
899 if (getDiminishGroup() != DIMINISHING_NONE )
900 m_target->ApplyDiminishingAura(getDiminishGroup(),true);
902 Unit* caster = GetCaster();
904 // passive auras (except totem auras) do not get placed in the slots
905 // area auras with SPELL_AURA_NONE are not shown on target
906 if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
907 (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
909 if(!samespell) // new slot need
911 if (IsPositive()) // empty positive slot
913 for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++)
915 if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
917 slot = i;
918 break;
922 else // empty negative slot
924 for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++)
926 if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
928 slot = i;
929 break;
934 SetAuraSlot( slot );
936 // Not update fields for not first spell's aura, all data already in fields
937 if(!secondaura)
939 if(slot < MAX_AURAS) // slot found
941 SetAura(slot, false);
942 SetAuraFlag(slot, true);
943 SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
944 UpdateAuraCharges();
946 // update for out of range group members
947 m_target->UpdateAuraForGroup(slot);
950 UpdateAuraDuration();
953 else // use found slot
955 SetAuraSlot( slot );
956 // Not recalculate stack count for second aura of the same spell
957 if (!secondaura)
958 UpdateSlotCounterAndDuration(true);
961 // Update Seals information
962 if( IsSealSpell(GetSpellProto()) )
963 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
965 // Conflagrate aura state
966 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
967 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
969 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
970 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
972 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
977 void Aura::_RemoveAura()
979 // Remove all triggered by aura spells vs unlimited duration
980 // except same aura replace case
981 if(m_removeMode!=AURA_REMOVE_BY_STACK)
982 CleanupTriggeredSpells();
984 Unit* caster = GetCaster();
986 if(caster && IsPersistent())
988 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
989 if (dynObj)
990 dynObj->RemoveAffected(m_target);
993 // unregister aura
994 if (getDiminishGroup() != DIMINISHING_NONE )
995 m_target->ApplyDiminishingAura(getDiminishGroup(),false);
997 //passive auras do not get put in slots
998 // Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
999 //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
1000 // return;
1002 uint8 slot = GetAuraSlot();
1004 if(slot >= MAX_AURAS) // slot not set
1005 return;
1007 if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0)
1008 return;
1010 bool samespell = false;
1011 bool sameaura = false;
1013 // find other aura in same slot (current already removed from list)
1014 for(uint8 i = 0; i < 3; i++)
1016 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
1017 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
1019 if(itr->second->GetAuraSlot()==slot)
1021 samespell = true;
1023 if(GetEffIndex()==i)
1024 sameaura = true;
1026 break;
1029 if(samespell)
1030 break;
1033 // only remove icon when the last aura of the spell is removed (current aura already removed from list)
1034 if (!samespell)
1036 SetAura(slot, true);
1037 SetAuraFlag(slot, false);
1038 SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
1040 SetAuraApplication(slot, 0);
1041 // update for out of range group members
1042 m_target->UpdateAuraForGroup(slot);
1044 if( IsSealSpell(GetSpellProto()) )
1045 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
1047 // Conflagrate aura state
1048 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
1049 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false);
1051 // Swiftmend aura state
1052 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1053 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
1055 bool found = false;
1056 Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
1057 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
1059 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1060 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
1062 found = true;
1063 break;
1066 if(!found)
1067 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false);
1070 // reset cooldown state for spells
1071 if(caster && caster->GetTypeId() == TYPEID_PLAYER)
1073 if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
1074 ((Player*)caster)->SendCooldownEvent(GetSpellProto());
1077 else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove process.
1078 UpdateSlotCounterAndDuration(false);
1081 void Aura::SetAuraFlag(uint32 slot, bool add)
1083 uint32 index = slot / 4;
1084 uint32 byte = (slot % 4) * 8;
1085 uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index);
1086 val &= ~((uint32)AFLAG_MASK << byte);
1087 if(add)
1089 if (IsPositive())
1090 val |= ((uint32)AFLAG_POSITIVE << byte);
1091 else
1092 val |= ((uint32)AFLAG_NEGATIVE << byte);
1094 m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val);
1097 void Aura::SetAuraLevel(uint32 slot,uint32 level)
1099 uint32 index = slot / 4;
1100 uint32 byte = (slot % 4) * 8;
1101 uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index);
1102 val &= ~(0xFF << byte);
1103 val |= (level << byte);
1104 m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val);
1107 void Aura::SetAuraApplication(uint32 slot, int8 count)
1109 uint32 index = slot / 4;
1110 uint32 byte = (slot % 4) * 8;
1111 uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index);
1112 val &= ~(0xFF << byte);
1113 val |= ((uint8(count)) << byte);
1114 m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val);
1117 void Aura::UpdateSlotCounterAndDuration(bool add)
1119 uint8 slot = GetAuraSlot();
1120 if(slot >= MAX_AURAS)
1121 return;
1123 // calculate amount of similar auras by same effect index (similar different spells)
1124 int8 count = 0;
1126 // calculate auras and update durations in case aura adding
1127 Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname);
1128 for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i)
1130 if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex &&
1131 (*i)->GetCasterGUID()==GetCasterGUID() )
1133 ++count;
1135 if(add)
1136 (*i)->SetAuraDuration(GetAuraDuration());
1140 // at aura add aura not added yet, at aura remove aura already removed
1141 // in field stored (count-1)
1142 if(!add)
1143 --count;
1145 SetAuraApplication(slot, count);
1147 UpdateAuraDuration();
1150 /*********************************************************/
1151 /*** BASIC AURA FUNCTION ***/
1152 /*********************************************************/
1153 void Aura::HandleAddModifier(bool apply, bool Real)
1155 if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
1156 return;
1158 SpellEntry const *spellInfo = GetSpellProto();
1159 if(!spellInfo)
1160 return;
1162 if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
1163 return;
1165 if (apply)
1167 // Add custom charges for some mod aura
1168 switch (m_spellProto->Id)
1170 case 17941: // Shadow Trance
1171 case 22008: // Netherwind Focus
1172 case 34936: // Backlash
1173 m_procCharges = 1;
1174 break;
1177 SpellModifier *mod = new SpellModifier;
1178 mod->op = SpellModOp(m_modifier.m_miscvalue);
1179 mod->value = m_modifier.m_amount;
1180 mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
1181 mod->spellId = GetId();
1182 mod->effectId = m_effIndex;
1183 mod->lastAffected = NULL;
1185 uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex);
1187 if (spellAffectMask)
1188 mod->mask = spellAffectMask;
1189 else
1190 mod->mask = spellInfo->EffectItemType[m_effIndex];
1192 if (m_procCharges > 0)
1193 mod->charges = m_procCharges;
1194 else
1195 mod->charges = 0;
1197 m_spellmod = mod;
1200 uint64 spellFamilyMask = m_spellmod->mask;
1202 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
1204 // reapply some passive spells after add/remove related spellmods
1205 if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
1207 m_target->RemoveAurasDueToSpell(45471);
1209 if(apply)
1210 m_target->CastSpell(m_target,45471,true);
1214 void Aura::TriggerSpell()
1216 Unit* caster = GetCaster();
1217 Unit* target = GetTriggerTarget();
1219 if(!caster || !target)
1220 return;
1222 // generic casting code with custom spells and target/caster customs
1223 uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
1225 uint64 originalCasterGUID = GetCasterGUID();
1227 SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1228 SpellEntry const *auraSpellInfo = GetSpellProto();
1229 uint32 auraId = auraSpellInfo->Id;
1231 // specific code for cases with no trigger spell provided in field
1232 if (triggeredSpellInfo == NULL)
1234 switch(auraSpellInfo->SpellFamilyName)
1236 case SPELLFAMILY_GENERIC:
1238 switch(auraId)
1240 // Firestone Passive (1-5 ranks)
1241 case 758:
1242 case 17945:
1243 case 17947:
1244 case 17949:
1245 case 27252:
1247 if (caster->GetTypeId()!=TYPEID_PLAYER)
1248 return;
1249 Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
1250 if (!item)
1251 return;
1252 uint32 enchant_id = 0;
1253 switch (GetId())
1255 case 758: enchant_id = 1803; break; // Rank 1
1256 case 17945: enchant_id = 1823; break; // Rank 2
1257 case 17947: enchant_id = 1824; break; // Rank 3
1258 case 17949: enchant_id = 1825; break; // Rank 4
1259 case 27252: enchant_id = 2645; break; // Rank 5
1260 default:
1261 return;
1263 // remove old enchanting before applying new
1264 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1265 item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
1266 // add new enchanting
1267 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
1268 return;
1270 // // Periodic Mana Burn
1271 // case 812: break;
1272 // // Polymorphic Ray
1273 // case 6965: break;
1274 // // Fire Nova (1-7 ranks)
1275 // case 8350:
1276 // case 8508:
1277 // case 8509:
1278 // case 11312:
1279 // case 11313:
1280 // case 25540:
1281 // case 25544:
1282 // break;
1283 // Thaumaturgy Channel
1284 case 9712: trigger_spell_id = 21029; break;
1285 // // Egan's Blaster
1286 // case 17368: break;
1287 // // Haunted
1288 // case 18347: break;
1289 // // Ranshalla Waiting
1290 // case 18953: break;
1291 // // Inferno
1292 // case 19695: break;
1293 // // Frostwolf Muzzle DND
1294 // case 21794: break;
1295 // // Alterac Ram Collar DND
1296 // case 21866: break;
1297 // // Celebras Waiting
1298 // case 21916: break;
1299 // Brood Affliction: Bronze
1300 case 23170:
1302 m_target->CastSpell(m_target, 23171, true, 0, this);
1303 return;
1305 // // Mark of Frost
1306 // case 23184: break;
1307 // Restoration
1308 case 23493:
1310 int32 heal = caster->GetMaxHealth() / 10;
1311 caster->ModifyHealth( heal );
1312 caster->SendHealSpellLog(caster, 23493, heal);
1314 int32 mana = caster->GetMaxPower(POWER_MANA);
1315 if (mana)
1317 mana /= 10;
1318 caster->ModifyPower( POWER_MANA, mana );
1319 caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
1321 break;
1323 // // Stoneclaw Totem Passive TEST
1324 // case 23792: break;
1325 // // Axe Flurry
1326 // case 24018: break;
1327 // // Mark of Arlokk
1328 // case 24210: break;
1329 // // Restoration
1330 // case 24379: break;
1331 // // Happy Pet
1332 // case 24716: break;
1333 // // Dream Fog
1334 // case 24780: break;
1335 // // Cannon Prep
1336 // case 24832: break;
1337 // // Shadow Bolt Whirl
1338 // case 24834: break;
1339 // // Stink Trap
1340 // case 24918: break;
1341 // // Mark of Nature
1342 // case 25041: break;
1343 // // Agro Drones
1344 // case 25152: break;
1345 // // Consume
1346 // case 25371: break;
1347 // // Pain Spike
1348 // case 25572: break;
1349 // // Rotate 360
1350 // case 26009: break;
1351 // // Rotate -360
1352 // case 26136: break;
1353 // // Consume
1354 // case 26196: break;
1355 // // Berserk
1356 // case 26615: break;
1357 // // Defile
1358 // case 27177: break;
1359 // // Teleport: IF/UC
1360 // case 27601: break;
1361 // // Five Fat Finger Exploding Heart Technique
1362 // case 27673: break;
1363 // // Nitrous Boost
1364 // case 27746: break;
1365 // // Steam Tank Passive
1366 // case 27747: break;
1367 // // Frost Blast
1368 // case 27808: break;
1369 // // Detonate Mana
1370 // case 27819: break;
1371 // // Controller Timer
1372 // case 28095: break;
1373 // // Stalagg Chain
1374 // case 28096: break;
1375 // // Stalagg Tesla Passive
1376 // case 28097: break;
1377 // // Feugen Tesla Passive
1378 // case 28109: break;
1379 // // Feugen Chain
1380 // case 28111: break;
1381 // // Mark of Didier
1382 // case 28114: break;
1383 // // Communique Timer, camp
1384 // case 28346: break;
1385 // // Icebolt
1386 // case 28522: break;
1387 // // Silithyst
1388 // case 29519: break;
1389 // // Inoculate Nestlewood Owlkin
1390 case 29528: trigger_spell_id = 28713; break;
1391 // // Overload
1392 // case 29768: break;
1393 // // Return Fire
1394 // case 29788: break;
1395 // // Return Fire
1396 // case 29793: break;
1397 // // Return Fire
1398 // case 29794: break;
1399 // // Guardian of Icecrown Passive
1400 // case 29897: break;
1401 // Feed Captured Animal
1402 case 29917: trigger_spell_id = 29916; break;
1403 // // Flame Wreath
1404 // case 29946: break;
1405 // // Flame Wreath
1406 // case 29947: break;
1407 // // Mind Exhaustion Passive
1408 // case 30025: break;
1409 // // Nether Beam - Serenity
1410 // case 30401: break;
1411 // Extract Gas
1412 case 30427:
1414 // move loot to player inventory and despawn target
1415 if(caster->GetTypeId() ==TYPEID_PLAYER &&
1416 target->GetTypeId() == TYPEID_UNIT &&
1417 ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
1419 Player* player = (Player*)caster;
1420 Creature* creature = (Creature*)target;
1421 // missing lootid has been reported on startup - just return
1422 if (!creature->GetCreatureInfo()->SkinLootId)
1424 return;
1426 Loot *loot = &creature->loot;
1427 loot->clear();
1428 loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL);
1429 for(uint8 i=0;i<loot->items.size();i++)
1431 LootItem *item = loot->LootItemInSlot(i,player);
1432 ItemPosCountVec dest;
1433 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count );
1434 if ( msg == EQUIP_ERR_OK )
1436 Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId);
1438 player->SendNewItem(newitem, uint32(item->count), false, false, true);
1440 else
1441 player->SendEquipError( msg, NULL, NULL );
1443 creature->setDeathState(JUST_DIED);
1444 creature->RemoveCorpse();
1445 creature->SetHealth(0); // just for nice GM-mode view
1447 return;
1448 break;
1450 // Quake
1451 case 30576: trigger_spell_id = 30571; break;
1452 // // Burning Maul
1453 // case 30598: break;
1454 // // Regeneration
1455 // case 30799:
1456 // case 30800:
1457 // case 30801:
1458 // break;
1459 // // Despawn Self - Smoke cloud
1460 // case 31269: break;
1461 // // Time Rift Periodic
1462 // case 31320: break;
1463 // // Corrupt Medivh
1464 // case 31326: break;
1465 // Doom
1466 case 31347:
1468 m_target->CastSpell(m_target,31350,true);
1469 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
1470 return;
1472 // Spellcloth
1473 case 31373:
1475 // Summon Elemental after create item
1476 caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
1477 return;
1479 // // Bloodmyst Tesla
1480 // case 31611: break;
1481 // // Doomfire
1482 // case 31944: break;
1483 // // Teleport Test
1484 // case 32236: break;
1485 // // Earthquake
1486 // case 32686: break;
1487 // // Possess
1488 // case 33401: break;
1489 // // Draw Shadows
1490 // case 33563: break;
1491 // // Murmur's Touch
1492 // case 33711: break;
1493 // Flame Quills
1494 case 34229:
1496 // cast 24 spells 34269-34289, 34314-34316
1497 for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
1498 caster->CastSpell(m_target,spell_id,true);
1499 for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
1500 caster->CastSpell(m_target,spell_id,true);
1501 return;
1503 // // Gravity Lapse
1504 // case 34480: break;
1505 // // Tornado
1506 // case 34683: break;
1507 // // Frostbite Rotate
1508 // case 34748: break;
1509 // // Arcane Flurry
1510 // case 34821: break;
1511 // // Interrupt Shutdown
1512 // case 35016: break;
1513 // // Interrupt Shutdown
1514 // case 35176: break;
1515 // // Inferno
1516 // case 35268: break;
1517 // // Salaadin's Tesla
1518 // case 35515: break;
1519 // // Ethereal Channel (Red)
1520 // case 35518: break;
1521 // // Nether Vapor
1522 // case 35879: break;
1523 // // Dark Portal Storm
1524 // case 36018: break;
1525 // // Burning Maul
1526 // case 36056: break;
1527 // // Living Grove Defender Lifespan
1528 // case 36061: break;
1529 // // Professor Dabiri Talks
1530 // case 36064: break;
1531 // // Kael Gaining Power
1532 // case 36091: break;
1533 // // They Must Burn Bomb Aura
1534 // case 36344: break;
1535 // // They Must Burn Bomb Aura (self)
1536 // case 36350: break;
1537 // // Stolen Ravenous Ravager Egg
1538 // case 36401: break;
1539 // // Activated Cannon
1540 // case 36410: break;
1541 // // Stolen Ravenous Ravager Egg
1542 // case 36418: break;
1543 // // Enchanted Weapons
1544 // case 36510: break;
1545 // // Cursed Scarab Periodic
1546 // case 36556: break;
1547 // // Cursed Scarab Despawn Periodic
1548 // case 36561: break;
1549 // // Vision Guide
1550 // case 36573: break;
1551 // // Cannon Charging (platform)
1552 // case 36785: break;
1553 // // Cannon Charging (self)
1554 // case 36860: break;
1555 // Remote Toy
1556 case 37027: trigger_spell_id = 37029; break;
1557 // // Mark of Death
1558 // case 37125: break;
1559 // // Arcane Flurry
1560 // case 37268: break;
1561 // // Spout
1562 // case 37429: break;
1563 // // Spout
1564 // case 37430: break;
1565 // // Karazhan - Chess NPC AI, Snapshot timer
1566 // case 37440: break;
1567 // // Karazhan - Chess NPC AI, action timer
1568 // case 37504: break;
1569 // // Karazhan - Chess: Is Square OCCUPIED aura (DND)
1570 // case 39400: break;
1571 // // Banish
1572 // case 37546: break;
1573 // // Shriveling Gaze
1574 // case 37589: break;
1575 // // Fake Aggro Radius (2 yd)
1576 // case 37815: break;
1577 // // Corrupt Medivh
1578 // case 37853: break;
1579 // Eye of Grillok
1580 case 38495:
1582 m_target->CastSpell(m_target, 38530, true);
1583 return;
1585 // Absorb Eye of Grillok (Zezzak's Shard)
1586 case 38554:
1588 if(m_target->GetTypeId() != TYPEID_UNIT)
1589 return;
1591 caster->CastSpell(caster, 38495, true);
1593 Creature* creatureTarget = (Creature*)m_target;
1595 creatureTarget->setDeathState(JUST_DIED);
1596 creatureTarget->RemoveCorpse();
1597 creatureTarget->SetHealth(0); // just for nice GM-mode view
1598 return;
1600 // // Magic Sucker Device timer
1601 // case 38672: break;
1602 // // Tomb Guarding Charging
1603 // case 38751: break;
1604 // // Murmur's Touch
1605 // case 38794: break;
1606 // // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item)
1607 // case 39105: break;
1608 // // Drain World Tree Visual
1609 // case 39140: break;
1610 // // Quest - Dustin's Undead Dragon Visual aura
1611 // case 39259: break;
1612 // // Hellfire - The Exorcism, Jules releases darkness, aura
1613 // case 39306: break;
1614 // // Inferno
1615 // case 39346: break;
1616 // // Enchanted Weapons
1617 // case 39489: break;
1618 // // Shadow Bolt Whirl
1619 // case 39630: break;
1620 // // Shadow Bolt Whirl
1621 // case 39634: break;
1622 // // Shadow Inferno
1623 // case 39645: break;
1624 // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
1625 case 39857: trigger_spell_id = 39856; break;
1626 // // Soulgrinder Ritual Visual (Smashed)
1627 // case 39974: break;
1628 // // Simon Game Pre-game timer
1629 // case 40041: break;
1630 // // Knockdown Fel Cannon: The Aggro Check Aura
1631 // case 40113: break;
1632 // // Spirit Lance
1633 // case 40157: break;
1634 // // Demon Transform 2
1635 // case 40398: break;
1636 // // Demon Transform 1
1637 // case 40511: break;
1638 // // Ancient Flames
1639 // case 40657: break;
1640 // // Ethereal Ring Cannon: Cannon Aura
1641 // case 40734: break;
1642 // // Cage Trap
1643 // case 40760: break;
1644 // // Random Periodic
1645 // case 40867: break;
1646 // // Prismatic Shield
1647 // case 40879: break;
1648 // // Aura of Desire
1649 // case 41350: break;
1650 // // Dementia
1651 // case 41404: break;
1652 // // Chaos Form
1653 // case 41629: break;
1654 // // Alert Drums
1655 // case 42177: break;
1656 // // Spout
1657 // case 42581: break;
1658 // // Spout
1659 // case 42582: break;
1660 // // Return to the Spirit Realm
1661 // case 44035: break;
1662 // // Curse of Boundless Agony
1663 // case 45050: break;
1664 // // Earthquake
1665 // case 46240: break;
1666 // Personalized Weather
1667 case 46736: trigger_spell_id = 46737; break;
1668 // // Stay Submerged
1669 // case 46981: break;
1670 // // Dragonblight Ram
1671 // case 47015: break;
1672 // // Party G.R.E.N.A.D.E.
1673 // case 51510: break;
1674 default:
1675 break;
1677 break;
1679 case SPELLFAMILY_MAGE:
1681 switch(auraId)
1683 // Invisibility
1684 case 66:
1686 if(!m_duration)
1687 m_target->CastSpell(m_target, 32612, true, NULL, this);
1688 return;
1690 default:
1691 break;
1693 break;
1695 // case SPELLFAMILY_WARRIOR:
1696 // {
1697 // switch(auraId)
1698 // {
1699 // // Wild Magic
1700 // case 23410: break;
1701 // // Corrupted Totems
1702 // case 23425: break;
1703 // default:
1704 // break;
1705 // }
1706 // break;
1707 // }
1708 // case SPELLFAMILY_PRIEST:
1709 // {
1710 // switch(auraId)
1711 // {
1712 // // Blue Beam
1713 // case 32930: break;
1714 // // Fury of the Dreghood Elders
1715 // case 35460: break;
1716 // default:
1717 // break;
1718 // }
1719 // break;
1720 // }
1721 case SPELLFAMILY_DRUID:
1723 switch(auraId)
1725 // Cat Form
1726 // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while
1727 case 768:
1728 return;
1729 // Frenzied Regeneration
1730 case 22842:
1731 case 22895:
1732 case 22896:
1733 case 26999:
1735 int32 LifePerRage = GetModifier()->m_amount;
1737 int32 lRage = m_target->GetPower(POWER_RAGE);
1738 if(lRage > 100) // rage stored as rage*10
1739 lRage = 100;
1740 m_target->ModifyPower(POWER_RAGE, -lRage);
1741 int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10);
1742 m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this);
1743 return;
1745 default:
1746 break;
1748 break;
1751 // case SPELLFAMILY_HUNTER:
1752 // {
1753 // switch(auraId)
1754 // {
1755 // //Frost Trap Aura
1756 // case 13810:
1757 // return;
1758 // //Rizzle's Frost Trap
1759 // case 39900:
1760 // return;
1761 // // Tame spells
1762 // case 19597: // Tame Ice Claw Bear
1763 // case 19676: // Tame Snow Leopard
1764 // case 19677: // Tame Large Crag Boar
1765 // case 19678: // Tame Adult Plainstrider
1766 // case 19679: // Tame Prairie Stalker
1767 // case 19680: // Tame Swoop
1768 // case 19681: // Tame Dire Mottled Boar
1769 // case 19682: // Tame Surf Crawler
1770 // case 19683: // Tame Armored Scorpid
1771 // case 19684: // Tame Webwood Lurker
1772 // case 19685: // Tame Nightsaber Stalker
1773 // case 19686: // Tame Strigid Screecher
1774 // case 30100: // Tame Crazed Dragonhawk
1775 // case 30103: // Tame Elder Springpaw
1776 // case 30104: // Tame Mistbat
1777 // case 30647: // Tame Barbed Crawler
1778 // case 30648: // Tame Greater Timberstrider
1779 // case 30652: // Tame Nightstalker
1780 // return;
1781 // default:
1782 // break;
1783 // }
1784 // break;
1785 // }
1786 case SPELLFAMILY_SHAMAN:
1788 switch(auraId)
1790 // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
1791 case 28820:
1793 // Need remove self if Lightning Shield not active
1794 Unit::AuraMap const& auras = target->GetAuras();
1795 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1797 SpellEntry const* spell = itr->second->GetSpellProto();
1798 if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
1799 spell->SpellFamilyFlags & 0x0000000000000400L)
1800 return;
1802 target->RemoveAurasDueToSpell(28820);
1803 return;
1805 // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
1806 case 38443:
1808 bool all = true;
1809 for(int i = 0; i < MAX_TOTEM; ++i)
1811 if(!caster->m_TotemSlot[i])
1813 all = false;
1814 break;
1818 if(all)
1819 caster->CastSpell(caster,38437,true);
1820 else
1821 caster->RemoveAurasDueToSpell(38437);
1822 return;
1824 default:
1825 break;
1827 break;
1829 default:
1830 break;
1832 // Reget trigger spell proto
1833 triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1834 if(triggeredSpellInfo == NULL)
1836 sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
1837 return;
1840 else
1842 // Spell exist but require custom code
1843 switch(auraId)
1845 // Curse of Idiocy
1846 case 1010:
1848 // TODO: spell casted by result in correct way mostly
1849 // BUT:
1850 // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell
1851 // but must show affect apply like item casting
1852 // 2) maybe aura must be replace by new with accumulative stat mods instead stacking
1854 // prevent cast by triggered auras
1855 if(m_caster_guid == m_target->GetGUID())
1856 return;
1858 // stop triggering after each affected stats lost > 90
1859 int32 intelectLoss = 0;
1860 int32 spiritLoss = 0;
1862 Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT);
1863 for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
1865 if ((*i)->GetId() == 1010)
1867 switch((*i)->GetModifier()->m_miscvalue)
1869 case STAT_INTELLECT: intelectLoss += (*i)->GetModifier()->m_amount; break;
1870 case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
1871 default: break;
1876 if(intelectLoss <= -90 && spiritLoss <= -90)
1877 return;
1879 caster = target;
1880 originalCasterGUID = 0;
1881 break;
1883 // Mana Tide
1884 case 16191:
1886 caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID);
1887 return;
1891 // All ok cast by default case
1892 Spell *spell = new Spell(caster, triggeredSpellInfo, true, originalCasterGUID );
1894 SpellCastTargets targets;
1895 targets.setUnitTarget( target );
1897 // if spell create dynamic object extract area from it
1898 if(DynamicObject* dynObj = caster->GetDynObject(GetId()))
1899 targets.setDestination(dynObj->GetPositionX(),dynObj->GetPositionY(),dynObj->GetPositionZ());
1901 spell->prepare(&targets, this);
1904 /*********************************************************/
1905 /*** AURA EFFECTS ***/
1906 /*********************************************************/
1908 void Aura::HandleAuraDummy(bool apply, bool Real)
1910 // spells required only Real aura add/remove
1911 if(!Real)
1912 return;
1914 Unit* caster = GetCaster();
1916 // AT APPLY
1917 if(apply)
1919 switch(GetId())
1921 case 1515: // Tame beast
1922 // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
1923 if( caster && m_target->CanHaveThreatList())
1924 m_target->AddThreat(caster, 10.0f);
1925 return;
1926 case 13139: // net-o-matic
1927 // root to self part of (root_target->charge->root_self sequence
1928 if(caster)
1929 caster->CastSpell(caster,13138,true,NULL,this);
1930 return;
1931 case 39850: // Rocket Blast
1932 if(roll_chance_i(20)) // backfire stun
1933 m_target->CastSpell(m_target, 51581, true, NULL, this);
1934 return;
1935 case 43873: // Headless Horseman Laugh
1936 if(caster->GetTypeId() == TYPEID_PLAYER)
1937 ((Player*)caster)->PlaySound(11965, false);
1938 return;
1939 case 46354: // Blood Elf Illusion
1940 if(caster)
1942 switch(caster->getGender())
1944 case GENDER_FEMALE:
1945 caster->CastSpell(m_target,46356,true,NULL,this);
1946 break;
1947 case GENDER_MALE:
1948 caster->CastSpell(m_target,46355,true,NULL,this);
1949 break;
1950 default:
1951 break;
1954 return;
1955 case 46699: // Requires No Ammo
1956 if(m_target->GetTypeId()==TYPEID_PLAYER)
1957 ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
1958 return;
1961 // Earth Shield
1962 if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
1964 // prevent double apply bonuses
1965 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
1966 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
1967 return;
1970 // AT REMOVE
1971 else
1973 if( m_target->GetTypeId() == TYPEID_PLAYER &&
1974 ( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
1975 ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
1977 // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
1978 ((Player*)m_target)->SetFarSight(NULL);
1979 WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
1980 ((Player*)m_target)->GetSession()->SendPacket(&data);
1981 return;
1984 if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive())
1986 uint32 finalSpelId = 0;
1987 switch(GetId())
1989 case 19548: finalSpelId = 19597; break;
1990 case 19674: finalSpelId = 19677; break;
1991 case 19687: finalSpelId = 19676; break;
1992 case 19688: finalSpelId = 19678; break;
1993 case 19689: finalSpelId = 19679; break;
1994 case 19692: finalSpelId = 19680; break;
1995 case 19693: finalSpelId = 19684; break;
1996 case 19694: finalSpelId = 19681; break;
1997 case 19696: finalSpelId = 19682; break;
1998 case 19697: finalSpelId = 19683; break;
1999 case 19699: finalSpelId = 19685; break;
2000 case 19700: finalSpelId = 19686; break;
2001 case 30646: finalSpelId = 30647; break;
2002 case 30653: finalSpelId = 30648; break;
2003 case 30654: finalSpelId = 30652; break;
2004 case 30099: finalSpelId = 30100; break;
2005 case 30102: finalSpelId = 30103; break;
2006 case 30105: finalSpelId = 30104; break;
2009 if(finalSpelId)
2010 caster->CastSpell(m_target,finalSpelId,true,NULL,this);
2011 return;
2014 // Waiting to Resurrect
2015 if(GetId()==2584)
2017 // Waiting to resurrect spell cancel, we must remove player from resurrect queue
2018 if(m_target->GetTypeId() == TYPEID_PLAYER)
2019 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
2020 bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
2021 return;
2024 // Dark Fiend
2025 if(GetId()==45934)
2027 // Kill target if dispelled
2028 if (m_removeMode==AURA_REMOVE_BY_DISPEL)
2029 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2030 return;
2033 // Burning Winds
2034 if(GetId()==46308) // casted only at creatures at spawn
2036 m_target->CastSpell(m_target,47287,true,NULL,this);
2037 return;
2041 // AT APPLY & REMOVE
2043 switch(m_spellProto->SpellFamilyName)
2045 case SPELLFAMILY_GENERIC:
2047 // Unstable Power
2048 if( GetId()==24658 )
2050 uint32 spellId = 24659;
2051 if (apply)
2053 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2054 if (!spell)
2055 return;
2056 for (int i=0; i < spell->StackAmount; ++i)
2057 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2058 return;
2060 m_target->RemoveAurasDueToSpell(spellId);
2061 return;
2063 // Restless Strength
2064 if( GetId()==24661 )
2066 uint32 spellId = 24662;
2067 if (apply)
2069 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2070 if (!spell)
2071 return;
2072 for (int i=0; i < spell->StackAmount; ++i)
2073 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2074 return;
2076 m_target->RemoveAurasDueToSpell(spellId);
2077 return;
2079 // Victorious
2080 if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
2082 m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
2083 return;
2085 //Summon Fire Elemental
2086 if (GetId() == 40133 && caster)
2088 Unit *owner = caster->GetOwner();
2089 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2091 if(apply)
2092 owner->CastSpell(owner,8985,true);
2093 else
2094 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2096 return;
2099 //Summon Earth Elemental
2100 if (GetId() == 40132 && caster)
2102 Unit *owner = caster->GetOwner();
2103 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2105 if(apply)
2106 owner->CastSpell(owner,19704,true);
2107 else
2108 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2110 return;
2112 break;
2114 case SPELLFAMILY_MAGE:
2116 // Hypothermia
2117 if( GetId()==41425 )
2119 m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply);
2120 return;
2122 break;
2124 case SPELLFAMILY_DRUID:
2126 // Lifebloom
2127 if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
2129 if ( apply )
2131 if ( caster )
2132 // prevent double apply bonuses
2133 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2134 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2136 else
2138 // Final heal only on dispelled or duration end
2139 if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
2140 return;
2142 // have a look if there is still some other Lifebloom dummy aura
2143 Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2144 for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); ++itr)
2145 if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2146 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
2147 return;
2149 // final heal
2150 if(m_target->IsInWorld())
2151 m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
2153 return;
2156 // Predatory Strikes
2157 if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
2159 ((Player*)m_target)->UpdateAttackPowerAndDamage();
2160 return;
2162 // Idol of the Emerald Queen
2163 if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
2165 if(apply)
2167 SpellModifier *mod = new SpellModifier;
2168 mod->op = SPELLMOD_DOT;
2169 mod->value = m_modifier.m_amount/7;
2170 mod->type = SPELLMOD_FLAT;
2171 mod->spellId = GetId();
2172 mod->effectId = m_effIndex;
2173 mod->lastAffected = NULL;
2174 mod->mask = 0x001000000000LL;
2175 mod->charges = 0;
2177 m_spellmod = mod;
2180 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2181 return;
2183 break;
2185 case SPELLFAMILY_HUNTER:
2187 // Improved Aspect of the Viper
2188 if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
2190 if(apply)
2192 // + effect value for Aspect of the Viper
2193 SpellModifier *mod = new SpellModifier;
2194 mod->op = SPELLMOD_EFFECT1;
2195 mod->value = m_modifier.m_amount;
2196 mod->type = SPELLMOD_FLAT;
2197 mod->spellId = GetId();
2198 mod->effectId = m_effIndex;
2199 mod->lastAffected = NULL;
2200 mod->mask = 0x4000000000000LL;
2201 mod->charges = 0;
2203 m_spellmod = mod;
2206 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2207 return;
2209 break;
2211 case SPELLFAMILY_SHAMAN:
2213 // Improved Weapon Totems
2214 if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
2216 if(apply)
2218 SpellModifier *mod = new SpellModifier;
2219 mod->op = SPELLMOD_EFFECT1;
2220 mod->value = m_modifier.m_amount;
2221 mod->type = SPELLMOD_PCT;
2222 mod->spellId = GetId();
2223 mod->effectId = m_effIndex;
2224 mod->lastAffected = NULL;
2225 switch (m_effIndex)
2227 case 0:
2228 mod->mask = 0x00200000000LL; // Windfury Totem
2229 break;
2230 case 1:
2231 mod->mask = 0x00400000000LL; // Flametongue Totem
2232 break;
2234 mod->charges = 0;
2236 m_spellmod = mod;
2239 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2240 return;
2242 break;
2246 // pet auras
2247 if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
2249 if(apply)
2250 m_target->AddPetAura(petSpell);
2251 else
2252 m_target->RemovePetAura(petSpell);
2253 return;
2257 void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
2259 // spells required only Real aura add/remove
2260 if(!Real)
2261 return;
2263 SpellEntry const*spell = GetSpellProto();
2264 switch( spell->SpellFamilyName)
2266 case SPELLFAMILY_ROGUE:
2268 // Master of Subtlety
2269 if (spell->Id==31666 && !apply && Real)
2271 m_target->RemoveAurasDueToSpell(31665);
2272 break;
2274 break;
2276 case SPELLFAMILY_HUNTER:
2278 // Aspect of the Viper
2279 if (spell->SpellFamilyFlags&0x0004000000000000LL)
2281 // Update regen on remove
2282 if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
2283 ((Player*)m_target)->UpdateManaRegen();
2284 break;
2286 break;
2290 m_isPeriodic = apply;
2293 void Aura::HandleAuraMounted(bool apply, bool Real)
2295 // only at real add/remove aura
2296 if(!Real)
2297 return;
2299 if(apply)
2301 CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2302 if(!ci)
2304 sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
2305 return;
2308 uint32 team = 0;
2309 if (m_target->GetTypeId()==TYPEID_PLAYER)
2310 team = ((Player*)m_target)->GetTeam();
2312 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2313 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2314 if (minfo)
2315 display_id = minfo->modelid;
2317 m_target->Mount(display_id);
2319 else
2321 m_target->Unmount();
2325 void Aura::HandleAuraWaterWalk(bool apply, bool Real)
2327 // only at real add/remove aura
2328 if(!Real)
2329 return;
2331 WorldPacket data;
2332 if(apply)
2333 data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
2334 else
2335 data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
2336 data.append(m_target->GetPackGUID());
2337 data << uint32(0);
2338 m_target->SendMessageToSet(&data,true);
2341 void Aura::HandleAuraFeatherFall(bool apply, bool Real)
2343 // only at real add/remove aura
2344 if(!Real)
2345 return;
2347 WorldPacket data;
2348 if(apply)
2349 data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
2350 else
2351 data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
2352 data.append(m_target->GetPackGUID());
2353 data << (uint32)0;
2354 m_target->SendMessageToSet(&data,true);
2357 void Aura::HandleAuraHover(bool apply, bool Real)
2359 // only at real add/remove aura
2360 if(!Real)
2361 return;
2363 WorldPacket data;
2364 if(apply)
2365 data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
2366 else
2367 data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
2368 data.append(m_target->GetPackGUID());
2369 data << uint32(0);
2370 m_target->SendMessageToSet(&data,true);
2373 void Aura::HandleWaterBreathing(bool apply, bool Real)
2375 if(apply)
2376 m_target->waterbreath = true;
2377 else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
2379 m_target->waterbreath = false;
2381 // update for enable timer in case not moving target
2382 if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
2384 ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
2385 ((Player*)m_target)->HandleDrowning();
2390 void Aura::HandleAuraModShapeshift(bool apply, bool Real)
2392 if(!Real)
2393 return;
2395 uint32 modelid = 0;
2396 Powers PowerType = POWER_MANA;
2397 ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
2398 switch(form)
2400 case FORM_CAT:
2401 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2402 modelid = 892;
2403 else
2404 modelid = 8571;
2405 PowerType = POWER_ENERGY;
2406 break;
2407 case FORM_TRAVEL:
2408 modelid = 632;
2409 break;
2410 case FORM_AQUA:
2411 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2412 modelid = 2428;
2413 else
2414 modelid = 2428;
2415 break;
2416 case FORM_BEAR:
2417 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2418 modelid = 2281;
2419 else
2420 modelid = 2289;
2421 PowerType = POWER_RAGE;
2422 break;
2423 case FORM_GHOUL:
2424 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2425 modelid = 10045;
2426 break;
2427 case FORM_DIREBEAR:
2428 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2429 modelid = 2281;
2430 else
2431 modelid = 2289;
2432 PowerType = POWER_RAGE;
2433 break;
2434 case FORM_CREATUREBEAR:
2435 modelid = 902;
2436 break;
2437 case FORM_GHOSTWOLF:
2438 modelid = 4613;
2439 break;
2440 case FORM_FLIGHT:
2441 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2442 modelid = 20857;
2443 else
2444 modelid = 20872;
2445 break;
2446 case FORM_MOONKIN:
2447 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2448 modelid = 15374;
2449 else
2450 modelid = 15375;
2451 break;
2452 case FORM_FLIGHT_EPIC:
2453 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2454 modelid = 21243;
2455 else
2456 modelid = 21244;
2457 break;
2458 case FORM_AMBIENT:
2459 case FORM_SHADOW:
2460 case FORM_STEALTH:
2461 break;
2462 case FORM_TREE:
2463 modelid = 864;
2464 break;
2465 case FORM_BATTLESTANCE:
2466 case FORM_BERSERKERSTANCE:
2467 case FORM_DEFENSIVESTANCE:
2468 PowerType = POWER_RAGE;
2469 break;
2470 case FORM_SPIRITOFREDEMPTION:
2471 modelid = 16031;
2472 break;
2473 default:
2474 sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
2477 // remove polymorph before changing display id to keep new display id
2478 switch ( form )
2480 case FORM_CAT:
2481 case FORM_TREE:
2482 case FORM_TRAVEL:
2483 case FORM_AQUA:
2484 case FORM_BEAR:
2485 case FORM_DIREBEAR:
2486 case FORM_FLIGHT_EPIC:
2487 case FORM_FLIGHT:
2488 case FORM_MOONKIN:
2489 // remove movement affects
2490 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2491 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2493 // and polymorphic affects
2494 if(m_target->IsPolymorphed())
2495 m_target->RemoveAurasDueToSpell(m_target->getTransForm());
2496 break;
2497 default:
2498 break;
2501 if(apply)
2503 // remove other shapeshift before applying a new one
2504 if(m_target->m_ShapeShiftFormSpellId)
2505 m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
2507 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
2509 if(modelid > 0)
2510 m_target->SetDisplayId(modelid);
2512 if(PowerType != POWER_MANA)
2514 // reset power to default values only at power change
2515 if(m_target->getPowerType()!=PowerType)
2516 m_target->setPowerType(PowerType);
2518 switch(form)
2520 case FORM_CAT:
2521 case FORM_BEAR:
2522 case FORM_DIREBEAR:
2524 // get furor proc chance
2525 uint32 FurorChance = 0;
2526 Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2527 for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
2529 if ((*i)->GetSpellProto()->SpellIconID == 238)
2531 FurorChance = (*i)->GetModifier()->m_amount;
2532 break;
2536 if (m_modifier.m_miscvalue == FORM_CAT)
2538 m_target->SetPower(POWER_ENERGY,0);
2539 if(urand(1,100) <= FurorChance)
2540 m_target->CastSpell(m_target,17099,true,NULL,this);
2542 else
2544 m_target->SetPower(POWER_RAGE,0);
2545 if(urand(1,100) <= FurorChance)
2546 m_target->CastSpell(m_target,17057,true,NULL,this);
2548 break;
2550 case FORM_BATTLESTANCE:
2551 case FORM_DEFENSIVESTANCE:
2552 case FORM_BERSERKERSTANCE:
2554 uint32 Rage_val = 0;
2555 // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
2556 if(m_target->GetTypeId() == TYPEID_PLAYER)
2558 PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
2559 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2561 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
2562 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2563 if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
2564 Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
2568 if (m_target->GetPower(POWER_RAGE) > Rage_val)
2569 m_target->SetPower(POWER_RAGE,Rage_val);
2570 break;
2572 default:
2573 break;
2577 m_target->m_ShapeShiftFormSpellId = GetId();
2578 m_target->m_form = form;
2580 else
2582 if(modelid > 0)
2583 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2584 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
2585 if(m_target->getClass() == CLASS_DRUID)
2586 m_target->setPowerType(POWER_MANA);
2587 m_target->m_ShapeShiftFormSpellId = 0;
2588 m_target->m_form = FORM_NONE;
2590 switch(form)
2592 // Nordrassil Harness - bonus
2593 case FORM_BEAR:
2594 case FORM_DIREBEAR:
2595 case FORM_CAT:
2597 if(Aura* dummy = m_target->GetDummyAura(37315) )
2598 m_target->CastSpell(m_target,37316,true,NULL,dummy);
2599 break;
2601 // Nordrassil Regalia - bonus
2602 case FORM_MOONKIN:
2604 if(Aura* dummy = m_target->GetDummyAura(37324) )
2605 m_target->CastSpell(m_target,37325,true,NULL,dummy);
2606 break;
2611 // adding/removing linked auras
2612 // add/remove the shapeshift aura's boosts
2613 HandleShapeshiftBoosts(apply);
2615 if(m_target->GetTypeId()==TYPEID_PLAYER)
2616 ((Player*)m_target)->InitDataForForm();
2619 void Aura::HandleAuraTransform(bool apply, bool Real)
2621 if (apply)
2623 // special case (spell specific functionality)
2624 if(m_modifier.m_miscvalue==0)
2626 // player applied only
2627 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2628 return;
2630 switch(GetId())
2632 // Orb of Deception
2633 case 16739:
2635 uint32 orb_model = m_target->GetNativeDisplayId();
2636 switch(orb_model)
2638 // Troll Female
2639 case 1479: m_target->SetDisplayId(10134); break;
2640 // Troll Male
2641 case 1478: m_target->SetDisplayId(10135); break;
2642 // Tauren Male
2643 case 59: m_target->SetDisplayId(10136); break;
2644 // Human Male
2645 case 49: m_target->SetDisplayId(10137); break;
2646 // Human Female
2647 case 50: m_target->SetDisplayId(10138); break;
2648 // Orc Male
2649 case 51: m_target->SetDisplayId(10139); break;
2650 // Orc Female
2651 case 52: m_target->SetDisplayId(10140); break;
2652 // Dwarf Male
2653 case 53: m_target->SetDisplayId(10141); break;
2654 // Dwarf Female
2655 case 54: m_target->SetDisplayId(10142); break;
2656 // NightElf Male
2657 case 55: m_target->SetDisplayId(10143); break;
2658 // NightElf Female
2659 case 56: m_target->SetDisplayId(10144); break;
2660 // Undead Female
2661 case 58: m_target->SetDisplayId(10145); break;
2662 // Undead Male
2663 case 57: m_target->SetDisplayId(10146); break;
2664 // Tauren Female
2665 case 60: m_target->SetDisplayId(10147); break;
2666 // Gnome Male
2667 case 1563: m_target->SetDisplayId(10148); break;
2668 // Gnome Female
2669 case 1564: m_target->SetDisplayId(10149); break;
2670 // BloodElf Female
2671 case 15475: m_target->SetDisplayId(17830); break;
2672 // BloodElf Male
2673 case 15476: m_target->SetDisplayId(17829); break;
2674 // Dranei Female
2675 case 16126: m_target->SetDisplayId(17828); break;
2676 // Dranei Male
2677 case 16125: m_target->SetDisplayId(17827); break;
2678 default: break;
2680 break;
2682 // Murloc costume
2683 case 42365: m_target->SetDisplayId(21723); break;
2684 default: break;
2687 else
2689 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2690 if(!ci)
2692 //pig pink ^_^
2693 m_target->SetDisplayId(16358);
2694 sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
2696 else
2698 // Will use the default model here
2699 m_target->SetDisplayId(ci->DisplayID_A);
2701 // Dragonmaw Illusion (set mount model also)
2702 if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
2703 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
2705 m_target->setTransForm(GetId());
2708 // polymorph case
2709 if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
2711 // for players, start regeneration after 1s (in polymorph fast regeneration case)
2712 // only if caster is Player (after patch 2.4.2)
2713 if(IS_PLAYER_GUID(GetCasterGUID()) )
2714 ((Player*)m_target)->setRegenTimer(1000);
2716 //dismount polymorphed target (after patch 2.4.2)
2717 if (m_target->IsMounted())
2718 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2721 else
2723 Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
2724 if(otherTransforms.empty())
2726 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2727 m_target->setTransForm(0);
2729 else
2731 // look for other transform auras
2732 Aura* handledAura = *otherTransforms.begin();
2733 for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
2735 // negative auras are preferred
2736 if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
2738 handledAura = *i;
2739 break;
2742 handledAura->ApplyModifier(true);
2745 // Dragonmaw Illusion (restore mount model)
2746 if(GetId()==42016 && m_target->GetMountID()==16314)
2748 if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
2750 uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
2751 if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
2753 uint32 team = 0;
2754 if (m_target->GetTypeId()==TYPEID_PLAYER)
2755 team = ((Player*)m_target)->GetTeam();
2757 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2758 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2759 if (minfo)
2760 display_id = minfo->modelid;
2762 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
2769 void Aura::HandleForceReaction(bool apply, bool Real)
2771 if(m_target->GetTypeId() != TYPEID_PLAYER)
2772 return;
2774 if(!Real)
2775 return;
2777 Player* player = (Player*)m_target;
2779 uint32 faction_id = m_modifier.m_miscvalue;
2780 uint32 faction_rank = m_modifier.m_amount;
2782 if(apply)
2783 player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
2784 else
2785 player->m_forcedReactions.erase(faction_id);
2787 WorldPacket data;
2788 data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
2789 data << uint32(player->m_forcedReactions.size());
2790 for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
2792 data << uint32(itr->first); // faction_id (Faction.dbc)
2793 data << uint32(itr->second); // reputation rank
2795 player->SendDirectMessage(&data);
2798 void Aura::HandleAuraModSkill(bool apply, bool Real)
2800 if(m_target->GetTypeId() != TYPEID_PLAYER)
2801 return;
2803 uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
2804 int32 points = GetModifier()->m_amount;
2806 ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
2807 if(prot == SKILL_DEFENSE)
2808 ((Player*)m_target)->UpdateDefenseBonusesMod();
2811 void Aura::HandleChannelDeathItem(bool apply, bool Real)
2813 if(Real && !apply)
2815 Unit* caster = GetCaster();
2816 Unit* victim = GetTarget();
2817 if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
2818 return;
2820 SpellEntry const *spellInfo = GetSpellProto();
2821 if(spellInfo->EffectItemType[m_effIndex] == 0)
2822 return;
2824 // Soul Shard only from non-grey units
2825 if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
2826 (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
2827 victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
2828 return;
2829 ItemPosCountVec dest;
2830 uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
2831 if( msg != EQUIP_ERR_OK )
2833 ((Player*)caster)->SendEquipError( msg, NULL, NULL );
2834 return;
2837 Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
2838 ((Player*)caster)->SendNewItem(newitem, 1, true, false);
2842 void Aura::HandleBindSight(bool apply, bool Real)
2844 Unit* caster = GetCaster();
2845 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2846 return;
2848 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2851 void Aura::HandleFarSight(bool apply, bool Real)
2853 Unit* caster = GetCaster();
2854 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2855 return;
2857 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2860 void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
2862 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2863 return;
2865 if(apply)
2866 m_target->RemoveNoStackAurasDueToAura(this);
2867 m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
2870 void Aura::HandleAuraTrackResources(bool apply, bool Real)
2872 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2873 return;
2875 if(apply)
2876 m_target->RemoveNoStackAurasDueToAura(this);
2877 m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
2880 void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
2882 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2883 return;
2885 if(apply)
2886 m_target->RemoveNoStackAurasDueToAura(this);
2888 m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
2891 void Aura::HandleAuraModScale(bool apply, bool Real)
2893 m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
2896 void Aura::HandleModPossess(bool apply, bool Real)
2898 if(!Real)
2899 return;
2901 if(m_target->getLevel() > m_modifier.m_amount)
2902 return;
2904 // not possess yourself
2905 if(GetCasterGUID() == m_target->GetGUID())
2906 return;
2908 Unit* caster = GetCaster();
2909 if(!caster)
2910 return;
2912 if( apply )
2914 m_target->SetCharmerGUID(GetCasterGUID());
2915 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
2916 caster->SetCharm(m_target);
2918 m_target->CombatStop();
2919 m_target->DeleteThreatList();
2920 if(m_target->GetTypeId() == TYPEID_UNIT)
2922 m_target->StopMoving();
2923 m_target->GetMotionMaster()->Clear();
2924 m_target->GetMotionMaster()->MoveIdle();
2925 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
2926 charmInfo->InitPossessCreateSpells();
2929 if(caster->GetTypeId() == TYPEID_PLAYER)
2931 ((Player*)caster)->PossessSpellInitialize();
2934 else
2936 m_target->SetCharmerGUID(0);
2938 if(m_target->GetTypeId() == TYPEID_PLAYER)
2939 ((Player*)m_target)->setFactionForRace(m_target->getRace());
2940 else if(m_target->GetTypeId() == TYPEID_UNIT)
2942 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
2943 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
2946 caster->SetCharm(0);
2948 if(caster->GetTypeId() == TYPEID_PLAYER)
2950 WorldPacket data(SMSG_PET_SPELLS, 8);
2951 data << uint64(0);
2952 ((Player*)caster)->GetSession()->SendPacket(&data);
2954 if(m_target->GetTypeId() == TYPEID_UNIT)
2956 ((Creature*)m_target)->AIM_Initialize();
2958 if (((Creature*)m_target)->AI())
2959 ((Creature*)m_target)->AI()->AttackStart(caster);
2962 if(caster->GetTypeId() == TYPEID_PLAYER)
2963 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2966 void Aura::HandleModPossessPet(bool apply, bool Real)
2968 if(!Real)
2969 return;
2971 Unit* caster = GetCaster();
2972 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2973 return;
2974 if(caster->GetPet() != m_target)
2975 return;
2977 if(apply)
2979 caster->SetUInt64Value(PLAYER_FARSIGHT, m_target->GetGUID());
2980 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2982 else
2984 caster->SetUInt64Value(PLAYER_FARSIGHT, 0);
2985 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2989 void Aura::HandleModCharm(bool apply, bool Real)
2991 if(!Real)
2992 return;
2994 // not charm yourself
2995 if(GetCasterGUID() == m_target->GetGUID())
2996 return;
2998 Unit* caster = GetCaster();
2999 if(!caster)
3000 return;
3002 if(int32(m_target->getLevel()) <= m_modifier.m_amount)
3004 if( apply )
3006 m_target->SetCharmerGUID(GetCasterGUID());
3007 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
3008 m_target->CastStop(m_target==caster ? GetId() : 0);
3009 caster->SetCharm(m_target);
3011 m_target->CombatStop();
3012 m_target->DeleteThreatList();
3014 if(m_target->GetTypeId() == TYPEID_UNIT)
3016 ((Creature*)m_target)->AIM_Initialize();
3017 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3018 charmInfo->InitCharmCreateSpells();
3019 charmInfo->SetReactState( REACT_DEFENSIVE );
3021 if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
3023 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3024 if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
3026 //to prevent client crash
3027 m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
3028 //just to enable stat window
3029 charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
3030 //if charmed two demons the same session, the 2nd gets the 1st one's name
3031 m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
3036 if(caster->GetTypeId() == TYPEID_PLAYER)
3038 ((Player*)caster)->CharmSpellInitialize();
3041 else
3043 m_target->SetCharmerGUID(0);
3045 if(m_target->GetTypeId() == TYPEID_PLAYER)
3046 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3047 else
3049 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3051 // restore faction
3052 if(((Creature*)m_target)->isPet())
3054 if(Unit* owner = m_target->GetOwner())
3055 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
3056 else if(cinfo)
3057 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3059 else if(cinfo) // normal creature
3060 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3062 // restore UNIT_FIELD_BYTES_0
3063 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
3065 CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
3066 if(cainfo && cainfo->bytes0 != 0)
3067 m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
3068 else
3069 m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
3071 if(m_target->GetCharmInfo())
3072 m_target->GetCharmInfo()->SetPetNumber(0, true);
3073 else
3074 sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
3078 caster->SetCharm(0);
3080 if(caster->GetTypeId() == TYPEID_PLAYER)
3082 WorldPacket data(SMSG_PET_SPELLS, 8);
3083 data << uint64(0);
3084 ((Player*)caster)->GetSession()->SendPacket(&data);
3086 if(m_target->GetTypeId() == TYPEID_UNIT)
3088 ((Creature*)m_target)->AIM_Initialize();
3089 if (((Creature*)m_target)->AI())
3090 ((Creature*)m_target)->AI()->AttackStart(caster);
3096 void Aura::HandleModConfuse(bool apply, bool Real)
3098 if(!Real)
3099 return;
3101 m_target->SetConfused(apply, GetCasterGUID(), GetId());
3104 void Aura::HandleModFear(bool apply, bool Real)
3106 if (!Real)
3107 return;
3109 m_target->SetFeared(apply, GetCasterGUID(), GetId());
3112 void Aura::HandleFeignDeath(bool apply, bool Real)
3114 if(!Real)
3115 return;
3117 if(m_target->GetTypeId() != TYPEID_PLAYER)
3118 return;
3120 if( apply )
3123 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3124 data<<m_target->GetGUID();
3125 data<<uint8(0);
3126 m_target->SendMessageToSet(&data,true);
3128 // blizz like 2.0.x
3129 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3130 // blizz like 2.0.x
3131 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3132 // blizz like 2.0.x
3133 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3135 m_target->addUnitState(UNIT_STAT_DIED);
3136 m_target->CombatStop();
3138 // prevent interrupt message
3139 if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
3140 m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
3141 m_target->InterruptNonMeleeSpells(true);
3142 m_target->getHostilRefManager().deleteReferences();
3144 else
3147 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3148 data<<m_target->GetGUID();
3149 data<<uint8(1);
3150 m_target->SendMessageToSet(&data,true);
3152 // blizz like 2.0.x
3153 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3154 // blizz like 2.0.x
3155 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3156 // blizz like 2.0.x
3157 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3159 m_target->clearUnitState(UNIT_STAT_DIED);
3163 void Aura::HandleAuraModDisarm(bool apply, bool Real)
3165 if(!Real)
3166 return;
3168 if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
3169 return;
3171 // not sure for it's correctness
3172 if(apply)
3173 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3174 else
3175 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3177 // only at real add/remove aura
3178 if (m_target->GetTypeId() != TYPEID_PLAYER)
3179 return;
3181 // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
3182 if (((Player *)m_target)->IsInFeralForm())
3183 return;
3185 if (apply)
3186 m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
3187 else
3188 ((Player *)m_target)->SetRegularAttackTime();
3190 m_target->UpdateDamagePhysical(BASE_ATTACK);
3193 void Aura::HandleAuraModStun(bool apply, bool Real)
3195 if(!Real)
3196 return;
3198 if (apply)
3200 m_target->addUnitState(UNIT_STAT_STUNNED);
3201 m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
3203 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
3204 m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
3206 // Creature specific
3207 if(m_target->GetTypeId() != TYPEID_PLAYER)
3208 ((Creature*)m_target)->StopMoving();
3209 else
3210 m_target->SetUnitMovementFlags(0); //Clear movement flags
3212 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
3214 data.append(m_target->GetPackGUID());
3215 data << uint32(0);
3216 m_target->SendMessageToSet(&data,true);
3218 else
3220 // Real remove called after current aura remove from lists, check if other similar auras active
3221 if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
3222 return;
3224 m_target->clearUnitState(UNIT_STAT_STUNNED);
3225 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
3227 if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
3229 if(m_target->getVictim() && m_target->isAlive())
3230 m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3232 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
3233 data.append(m_target->GetPackGUID());
3234 data << uint32(0);
3235 m_target->SendMessageToSet(&data,true);
3238 // Wyvern Sting
3239 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
3241 Unit* caster = GetCaster();
3242 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
3243 return;
3245 uint32 spell_id = 0;
3247 switch(GetId())
3249 case 19386: spell_id = 24131; break;
3250 case 24132: spell_id = 24134; break;
3251 case 24133: spell_id = 24135; break;
3252 case 27068: spell_id = 27069; break;
3253 default:
3254 sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
3255 return;
3258 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
3260 if(!spellInfo)
3261 return;
3263 caster->CastSpell(m_target,spellInfo,true,NULL,this);
3264 return;
3269 void Aura::HandleModStealth(bool apply, bool Real)
3271 if(apply)
3273 // drop flag at stealth in bg
3274 if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
3275 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3276 bg->EventPlayerDroppedFlag((Player*)m_target);
3278 // only at real aura add
3279 if(Real)
3281 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
3282 if(m_target->GetTypeId()==TYPEID_PLAYER)
3283 m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
3285 // apply only if not in GM invisibility (and overwrite invisibility state)
3286 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3288 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3289 m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
3292 // for RACE_NIGHTELF stealth
3293 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3294 m_target->CastSpell(m_target, 21009, true, NULL, this);
3297 else
3299 // only at real aura remove
3300 if(Real)
3302 // for RACE_NIGHTELF stealth
3303 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3304 m_target->RemoveAurasDueToSpell(21009);
3306 // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
3307 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
3309 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
3310 if(m_target->GetTypeId()==TYPEID_PLAYER)
3311 m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
3313 // restore invisibility if any
3314 if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
3316 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3317 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3319 else
3320 m_target->SetVisibility(VISIBILITY_ON);
3325 // Master of Subtlety
3326 Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
3327 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
3329 if ((*i)->GetSpellProto()->SpellIconID == 2114)
3331 if (apply)
3333 int32 bp = (*i)->GetModifier()->m_amount;
3334 m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
3336 else
3337 m_target->CastSpell(m_target,31666,true);
3338 break;
3343 void Aura::HandleInvisibility(bool apply, bool Real)
3345 if(apply)
3347 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3349 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3351 // apply glow vision
3352 m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3354 // drop flag at invisible in bg
3355 if(((Player*)m_target)->InBattleGround())
3356 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3357 bg->EventPlayerDroppedFlag((Player*)m_target);
3360 // apply only if not in GM invisibility and not stealth
3361 if(m_target->GetVisibility()==VISIBILITY_ON)
3363 // Aura not added yet but visibility code expect temporary add aura
3364 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3365 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3368 else
3370 // recalculate value at modifier remove (current aura already removed)
3371 m_target->m_invisibilityMask = 0;
3372 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
3373 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3374 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3376 // only at real aura remove and if not have different invisibility auras.
3377 if(Real && m_target->m_invisibilityMask==0)
3379 // remove glow vision
3380 if(m_target->GetTypeId() == TYPEID_PLAYER)
3381 m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3383 // apply only if not in GM invisibility & not stealthed while invisible
3384 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3386 // if have stealth aura then already have stealth visibility
3387 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
3388 m_target->SetVisibility(VISIBILITY_ON);
3394 void Aura::HandleInvisibilityDetect(bool apply, bool Real)
3396 if(apply)
3398 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3400 else
3402 // recalculate value at modifier remove (current aura already removed)
3403 m_target->m_detectInvisibilityMask = 0;
3404 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
3405 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3406 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3408 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3409 ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
3412 void Aura::HandleAuraModRoot(bool apply, bool Real)
3414 // only at real add/remove aura
3415 if(!Real)
3416 return;
3418 uint32 apply_stat = UNIT_STAT_ROOT;
3419 if (apply)
3421 m_target->addUnitState(UNIT_STAT_ROOT);
3422 m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
3423 // probably wrong
3424 m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3426 //Save last orientation
3427 if( m_target->getVictim() )
3428 m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
3430 if(m_target->GetTypeId() == TYPEID_PLAYER)
3432 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
3433 data.append(m_target->GetPackGUID());
3434 data << (uint32)2;
3435 m_target->SendMessageToSet(&data,true);
3437 //Clear unit movement flags
3438 m_target->SetUnitMovementFlags(0);
3440 else
3441 ((Creature *)m_target)->StopMoving();
3443 else
3445 // Real remove called after current aura remove from lists, check if other similar auras active
3446 if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
3447 return;
3449 m_target->clearUnitState(UNIT_STAT_ROOT);
3450 // probably wrong
3451 m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3453 if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
3455 if(m_target->getVictim() && m_target->isAlive())
3456 m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3458 if(m_target->GetTypeId() == TYPEID_PLAYER)
3460 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
3461 data.append(m_target->GetPackGUID());
3462 data << (uint32)2;
3463 m_target->SendMessageToSet(&data,true);
3469 void Aura::HandleAuraModSilence(bool apply, bool Real)
3471 // only at real add/remove aura
3472 if(!Real)
3473 return;
3475 if(apply)
3477 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3478 // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3479 for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
3481 Spell* currentSpell = m_target->m_currentSpells[i];
3482 if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
3484 uint32 state = currentSpell->getState();
3485 // Stop spells on prepare or casting state
3486 if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
3488 currentSpell->cancel();
3489 currentSpell->SetReferencedFromCurrent(false);
3490 m_target->m_currentSpells[i] = NULL;
3495 switch (GetId())
3497 // Arcane Torrent (Energy)
3498 case 25046:
3500 Unit * caster = GetCaster();
3501 if (!caster)
3502 return;
3504 // Search Mana Tap auras on caster
3505 int32 energy = 0;
3506 Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
3507 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3508 if ((*i)->GetId() == 28734)
3509 ++energy;
3510 if (energy)
3512 energy *= 10;
3513 caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true);
3514 caster->RemoveAurasDueToSpell(28734);
3519 else
3521 // Real remove called after current aura remove from lists, check if other similar auras active
3522 if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
3523 return;
3525 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3529 void Aura::HandleModThreat(bool apply, bool Real)
3531 // only at real add/remove aura
3532 if(!Real)
3533 return;
3535 if(!m_target->isAlive())
3536 return;
3538 Unit* caster = GetCaster();
3540 if(!caster || !caster->isAlive())
3541 return;
3543 int level_diff = 0;
3544 int multiplier = 0;
3545 switch (GetId())
3547 // Arcane Shroud
3548 case 26400:
3549 level_diff = m_target->getLevel() - 60;
3550 multiplier = 2;
3551 break;
3552 // The Eye of Diminution
3553 case 28862:
3554 level_diff = m_target->getLevel() - 60;
3555 multiplier = 1;
3556 break;
3558 if (level_diff > 0)
3559 m_modifier.m_amount += multiplier * level_diff;
3561 for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
3563 if(m_modifier.m_miscvalue & int32(1<<x))
3565 if(m_target->GetTypeId() == TYPEID_PLAYER)
3566 ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
3571 void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
3573 // only at real add/remove aura
3574 if(!Real)
3575 return;
3577 if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
3578 return;
3580 Unit* caster = GetCaster();
3582 if(!caster || !caster->isAlive())
3583 return;
3585 float threatMod = 0.0f;
3586 if(apply)
3587 threatMod = float(m_modifier.m_amount);
3588 else
3589 threatMod = float(-m_modifier.m_amount);
3591 m_target->getHostilRefManager().threatAssist(caster, threatMod);
3594 void Aura::HandleModTaunt(bool apply, bool Real)
3596 // only at real add/remove aura
3597 if(!Real)
3598 return;
3600 if(!m_target->isAlive() || !m_target->CanHaveThreatList())
3601 return;
3603 Unit* caster = GetCaster();
3605 if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
3606 return;
3608 if(apply)
3609 m_target->TauntApply(caster);
3610 else
3612 // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
3613 m_target->TauntFadeOut(caster);
3617 /*********************************************************/
3618 /*** MODIFY SPEED ***/
3619 /*********************************************************/
3620 void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real)
3622 // all applied/removed only at real aura add/remove
3623 if(!Real)
3624 return;
3626 m_target->UpdateSpeed(MOVE_RUN, true);
3629 void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real)
3631 // all applied/removed only at real aura add/remove
3632 if(!Real)
3633 return;
3635 m_target->UpdateSpeed(MOVE_RUN, true);
3638 void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
3640 // all applied/removed only at real aura add/remove
3641 if(!Real)
3642 return;
3644 // Enable Fly mode for flying mounts
3645 if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
3647 WorldPacket data;
3648 if(apply)
3649 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
3650 else
3651 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
3652 data.append(m_target->GetPackGUID());
3653 data << uint32(0); // unknown
3654 m_target->SendMessageToSet(&data, true);
3656 //Players on flying mounts must be immune to polymorph
3657 if (m_target->GetTypeId()==TYPEID_PLAYER)
3658 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
3660 // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
3661 if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
3662 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
3665 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3668 void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
3670 // all applied/removed only at real aura add/remove
3671 if(!Real)
3672 return;
3674 m_target->UpdateSpeed(MOVE_SWIM, true);
3677 void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
3679 // all applied/removed only at real aura add/remove
3680 if(!Real)
3681 return;
3683 m_target->UpdateSpeed(MOVE_RUN, true);
3684 m_target->UpdateSpeed(MOVE_SWIM, true);
3685 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3688 void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
3690 // all applied/removed only at real aura add/remove
3691 if(!Real)
3692 return;
3694 m_target->UpdateSpeed(MOVE_RUN, true);
3695 m_target->UpdateSpeed(MOVE_SWIM, true);
3696 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3699 /*********************************************************/
3700 /*** IMMUNITY ***/
3701 /*********************************************************/
3703 void Aura::HandleModMechanicImmunity(bool apply, bool Real)
3705 uint32 mechanic = 1 << m_modifier.m_miscvalue;
3707 //immune movement impairment and loss of control
3708 if(GetId()==42292)
3709 mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
3711 if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3713 Unit::AuraMap& Auras = m_target->GetAuras();
3714 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3716 next = iter;
3717 ++next;
3718 SpellEntry const *spell = iter->second->GetSpellProto();
3719 if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
3720 && !iter->second->IsPositive() // only remove negative spells
3721 && spell->Id != GetId())
3723 //check for mechanic mask
3724 if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
3726 m_target->RemoveAurasDueToSpell(spell->Id);
3727 if(Auras.empty())
3728 break;
3729 else
3730 next = Auras.begin();
3736 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
3738 // special cases
3739 switch(m_modifier.m_miscvalue)
3741 case MECHANIC_INVULNERABILITY:
3742 m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply);
3743 break;
3744 case MECHANIC_SHIELD:
3745 m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply);
3746 break;
3749 // Bestial Wrath
3750 if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
3752 // The Beast Within cast on owner if talent present
3753 if ( Unit* owner = m_target->GetOwner() )
3755 // Search talent
3756 Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
3757 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3759 if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
3761 if (apply)
3762 owner->CastSpell(owner, 34471, true, 0, this);
3763 else
3764 owner->RemoveAurasDueToSpell(34471);
3765 break;
3771 // The Beast Within and Bestial Wrath - immunity
3772 if(GetId() == 19574 || GetId() == 34471)
3774 if(apply)
3776 m_target->CastSpell(m_target,24395,true);
3777 m_target->CastSpell(m_target,24396,true);
3778 m_target->CastSpell(m_target,24397,true);
3779 m_target->CastSpell(m_target,26592,true);
3781 else
3783 m_target->RemoveAurasDueToSpell(24395);
3784 m_target->RemoveAurasDueToSpell(24396);
3785 m_target->RemoveAurasDueToSpell(24397);
3786 m_target->RemoveAurasDueToSpell(26592);
3791 void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
3793 if(!apply)
3795 if(m_target->GetTypeId() == TYPEID_PLAYER)
3797 if(((Player*)m_target)->InBattleGround())
3799 BattleGround *bg = ((Player*)m_target)->GetBattleGround();
3800 if(bg)
3802 switch(bg->GetTypeID())
3804 case BATTLEGROUND_AV:
3806 break;
3808 case BATTLEGROUND_WS:
3810 // Warsong Flag, horde // Silverwing Flag, alliance
3811 if(GetId() == 23333 || GetId() == 23335)
3812 bg->EventPlayerDroppedFlag(((Player*)m_target));
3813 break;
3815 case BATTLEGROUND_AB:
3817 break;
3819 case BATTLEGROUND_EY:
3821 if(GetId() == 34976)
3822 bg->EventPlayerDroppedFlag(((Player*)m_target));
3823 break;
3831 m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
3834 void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
3836 if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3838 Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
3839 for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
3841 if (auraList.front() != this) // skip itself aura (it already added)
3843 m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
3844 itr = auraList.begin();
3846 else
3847 ++itr;
3851 m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
3854 void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
3856 m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
3858 if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3860 if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
3862 uint32 school_mask = m_modifier.m_miscvalue;
3863 Unit::AuraMap& Auras = m_target->GetAuras();
3864 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3866 next = iter;
3867 ++next;
3868 SpellEntry const *spell = iter->second->GetSpellProto();
3869 if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
3870 && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
3871 && !iter->second->IsPositive() //Don't remove positive spells
3872 && spell->Id != GetId() ) //Don't remove self
3874 m_target->RemoveAurasDueToSpell(spell->Id);
3875 if(Auras.empty())
3876 break;
3877 else
3878 next = Auras.begin();
3883 if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
3885 if( apply )
3886 m_target->addUnitState(UNIT_STAT_ISOLATED);
3887 else
3888 m_target->clearUnitState(UNIT_STAT_ISOLATED);
3892 void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
3894 m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
3897 void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
3899 // all applied/removed only at real aura add/remove
3900 if(!Real)
3901 return;
3903 m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
3906 void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
3908 if(!Real)
3909 return;
3911 if(apply)
3913 // some spell have charges by functionality not have its in spell data
3914 switch (GetId())
3916 case 28200: // Ascendance (Talisman of Ascendance trinket)
3917 m_procCharges = 6;
3918 UpdateAuraCharges();
3919 break;
3920 default: break;
3925 void Aura::HandleAuraModStalked(bool apply, bool Real)
3927 // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
3928 if(apply)
3929 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3930 else
3931 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3934 /*********************************************************/
3935 /*** PERIODIC ***/
3936 /*********************************************************/
3938 void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
3940 if (m_periodicTimer <= 0)
3941 m_periodicTimer += m_modifier.periodictime;
3943 m_isPeriodic = apply;
3944 m_isTrigger = apply;
3946 // Curse of the Plaguebringer
3947 if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL)
3949 // Cast Wrath of the Plaguebringer if not dispelled
3950 m_target->CastSpell(m_target, 29214, true, 0, this);
3954 void Aura::HandlePeriodicEnergize(bool apply, bool Real)
3956 if (m_periodicTimer <= 0)
3957 m_periodicTimer += m_modifier.periodictime;
3959 m_isPeriodic = apply;
3962 void Aura::HandlePeriodicHeal(bool apply, bool Real)
3964 if (m_periodicTimer <= 0)
3965 m_periodicTimer += m_modifier.periodictime;
3967 m_isPeriodic = apply;
3969 // only at real apply
3970 if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE)
3972 // provided m_target as original caster to prevent apply aura caster selection for this negative buff
3973 m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID());
3976 // For prevent double apply bonuses
3977 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
3979 if(!loading && apply)
3981 switch (m_spellProto->SpellFamilyName)
3983 case SPELLFAMILY_DRUID:
3985 // Rejuvenation
3986 if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
3988 if(Unit* caster = GetCaster())
3990 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
3991 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
3993 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
3994 switch((*k)->GetModifier()->m_miscvalue)
3996 case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
3997 case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
3999 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4000 break;
4011 void Aura::HandlePeriodicDamage(bool apply, bool Real)
4013 // spells required only Real aura add/remove
4014 if(!Real)
4015 return;
4017 if (m_periodicTimer <= 0)
4018 m_periodicTimer += m_modifier.periodictime;
4020 m_isPeriodic = apply;
4022 // For prevent double apply bonuses
4023 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4025 Unit *caster = GetCaster();
4027 switch (m_spellProto->SpellFamilyName)
4029 case SPELLFAMILY_GENERIC:
4031 // Pounce Bleed
4032 if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 )
4034 // $AP*0.18/6 bonus per tick
4035 if (apply && !loading && caster)
4036 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4037 return;
4039 break;
4041 case SPELLFAMILY_WARRIOR:
4043 // Rend
4044 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4046 // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
4047 if (apply && !loading && caster)
4049 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4050 int32 mws = caster->GetAttackTime(BASE_ATTACK);
4051 float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
4052 float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
4053 // WARNING! in 3.0 multiplier 0.00743f change to 0.6
4054 m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
4056 return;
4058 break;
4060 case SPELLFAMILY_DRUID:
4062 // Rake
4063 if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
4065 // $AP*0.06/3 bonus per tick
4066 if (apply && !loading && caster)
4067 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
4068 return;
4070 // Lacerate
4071 if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
4073 // $AP*0.05/5 bonus per tick
4074 if (apply && !loading && caster)
4075 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
4076 return;
4078 // Rip
4079 if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
4081 // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used]
4082 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4084 uint8 cp = ((Player*)caster)->GetComboPoints();
4086 // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
4087 Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
4088 for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
4090 if((*itr)->GetId()==34241)
4092 m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
4093 break;
4097 if (cp > 4) cp = 4;
4098 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4100 return;
4102 break;
4104 case SPELLFAMILY_ROGUE:
4106 // Deadly poison aura state
4107 if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100)
4109 if(apply)
4110 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
4111 else
4113 // current aura already removed, search present of another
4114 bool found = false;
4115 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
4116 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
4118 SpellEntry const* itr_spell = (*itr)->GetSpellProto();
4119 if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100)
4121 found = true;
4122 break;
4125 // this has been last deadly poison aura
4126 if(!found)
4127 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
4129 return;
4131 // Rupture
4132 if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
4134 // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP]
4135 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4137 uint8 cp = ((Player*)caster)->GetComboPoints();
4138 if (cp > 3) cp = 3;
4139 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4141 return;
4143 // Garrote
4144 if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
4146 // $AP*0.18/6 bonus per tick
4147 if (apply && !loading && caster)
4148 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4149 return;
4151 break;
4153 case SPELLFAMILY_HUNTER:
4155 // Serpent Sting
4156 if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
4158 // $RAP*0.1/5 bonus per tick
4159 if (apply && !loading && caster)
4160 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4161 return;
4163 // Immolation Trap
4164 if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
4166 // $RAP*0.1/5 bonus per tick
4167 if (apply && !loading && caster)
4168 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4169 return;
4171 break;
4173 case SPELLFAMILY_PALADIN:
4175 // Consecration
4176 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4178 if (apply && !loading)
4180 if(Unit* caster = GetCaster())
4182 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4183 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4185 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4186 switch((*k)->GetModifier()->m_miscvalue)
4188 case 5147: // Improved Consecration - Libram of the Eternal Rest
4190 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4191 break;
4197 return;
4199 break;
4201 default:
4202 break;
4206 void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
4208 if (m_periodicTimer <= 0)
4209 m_periodicTimer += m_modifier.periodictime;
4211 m_isPeriodic = apply;
4214 void Aura::HandlePeriodicLeech(bool apply, bool Real)
4216 if (m_periodicTimer <= 0)
4217 m_periodicTimer += m_modifier.periodictime;
4219 m_isPeriodic = apply;
4222 void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
4224 if (m_periodicTimer <= 0)
4225 m_periodicTimer += m_modifier.periodictime;
4227 m_isPeriodic = apply;
4230 /*********************************************************/
4231 /*** MODIFY STATS ***/
4232 /*********************************************************/
4234 /********************************/
4235 /*** RESISTANCE ***/
4236 /********************************/
4238 void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
4240 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4242 if(m_modifier.m_miscvalue & int32(1<<x))
4244 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
4245 if(m_target->GetTypeId() == TYPEID_PLAYER)
4246 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4251 void Aura::HandleAuraModResistance(bool apply, bool Real)
4253 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4255 if(m_modifier.m_miscvalue & int32(1<<x))
4257 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4258 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4259 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4263 // Faerie Fire (druid versions)
4264 if( m_spellProto->SpellIconID == 109 &&
4265 m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
4266 m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
4268 m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
4272 void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
4274 // only players have base stats
4275 if(m_target->GetTypeId() != TYPEID_PLAYER)
4277 //pets only have base armor
4278 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4279 m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
4281 else
4283 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4285 if(m_modifier.m_miscvalue & int32(1<<x))
4286 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
4291 void Aura::HandleModResistancePercent(bool apply, bool Real)
4293 for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4295 if(m_modifier.m_miscvalue & int32(1<<i))
4297 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4298 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4300 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
4301 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
4307 void Aura::HandleModBaseResistance(bool apply, bool Real)
4309 // only players have base stats
4310 if(m_target->GetTypeId() != TYPEID_PLAYER)
4312 //only pets have base stats
4313 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4314 m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4316 else
4318 for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4319 if(m_modifier.m_miscvalue & (1<<i))
4320 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4324 /********************************/
4325 /*** STAT ***/
4326 /********************************/
4328 void Aura::HandleAuraModStat(bool apply, bool Real)
4330 if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
4332 sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
4333 return;
4336 for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4338 // -1 or -2 is all stats ( misc < -2 checked in function beginning )
4339 if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
4341 //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
4342 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4343 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4344 m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
4349 void Aura::HandleModPercentStat(bool apply, bool Real)
4351 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4353 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4354 return;
4357 // only players have base stats
4358 if (m_target->GetTypeId() != TYPEID_PLAYER)
4359 return;
4361 for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
4363 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4364 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
4368 void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real)
4370 if(m_target->GetTypeId() != TYPEID_PLAYER)
4371 return;
4373 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4374 // This information for client side use only
4375 // Recalculate bonus
4376 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4379 void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real)
4381 if(m_target->GetTypeId() != TYPEID_PLAYER)
4382 return;
4384 // Recalculate bonus
4385 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4388 void Aura::HandleAuraModDispelResist(bool apply, bool Real)
4390 if(!Real || !apply)
4391 return;
4393 if(GetId()==33206)
4394 m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
4397 void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real)
4399 if(m_target->GetTypeId() != TYPEID_PLAYER)
4400 return;
4402 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4403 // This information for client side use only
4404 // Recalculate bonus
4405 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4408 void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real)
4410 if(m_target->GetTypeId() != TYPEID_PLAYER)
4411 return;
4413 // Recalculate bonus
4414 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4417 void Aura::HandleModHealingDone(bool /*apply*/, bool Real)
4419 if(m_target->GetTypeId() != TYPEID_PLAYER)
4420 return;
4421 // implemented in Unit::SpellHealingBonus
4422 // this information is for client side only
4423 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4426 void Aura::HandleModTotalPercentStat(bool apply, bool Real)
4428 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4430 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4431 return;
4434 //save current and max HP before applying aura
4435 uint32 curHPValue = m_target->GetHealth();
4436 uint32 maxHPValue = m_target->GetMaxHealth();
4438 for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4440 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4442 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4443 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4444 m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
4448 //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
4449 if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
4451 // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
4452 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
4453 m_target->SetHealth(newHPValue);
4457 void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
4459 if(m_target->GetTypeId() != TYPEID_PLAYER)
4460 return;
4462 if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
4464 // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
4465 // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
4466 sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
4467 return;
4470 // Recalculate Armor
4471 m_target->UpdateArmor();
4474 /********************************/
4475 /*** HEAL & ENERGIZE ***/
4476 /********************************/
4477 void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
4480 Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
4481 so this aura not fully working.
4483 if(apply)
4485 if(!m_target->isAlive())
4486 return;
4488 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4489 m_target->SetStandState(PLAYER_STATE_SIT);
4491 if(m_periodicTimer <= 0)
4493 m_periodicTimer += m_modifier.periodictime;
4495 if(m_target->GetHealth() < m_target->GetMaxHealth())
4497 // PeriodicTick can cast triggered spells with stats changes
4498 PeriodicTick();
4503 m_isPeriodic = apply;
4506 void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
4508 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4509 m_target->SetStandState(PLAYER_STATE_SIT);
4510 if(apply)
4512 if(m_modifier.periodictime == 0)
4513 m_modifier.periodictime = 1000;
4514 if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
4516 m_periodicTimer += m_modifier.periodictime;
4518 if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
4520 // PeriodicTick can cast triggered spells with stats changes
4521 PeriodicTick();
4526 m_isPeriodic = apply;
4529 void Aura::HandleModRegen(bool apply, bool Real) // eating
4531 if(apply)
4533 if(!m_target->isAlive())
4534 return;
4536 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4537 m_target->SetStandState(PLAYER_STATE_SIT);
4539 if(m_periodicTimer <= 0)
4541 m_periodicTimer += 5000;
4542 int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
4543 Unit *caster = GetCaster();
4544 if (caster)
4546 SpellEntry const *spellProto = GetSpellProto();
4547 if (spellProto)
4548 m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
4553 m_isPeriodic = apply;
4556 void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
4558 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4559 m_target->SetStandState(PLAYER_STATE_SIT);
4561 if(apply && m_periodicTimer <= 0)
4563 m_periodicTimer += 2000;
4565 Powers pt = m_target->getPowerType();
4566 if(int32(pt) != m_modifier.m_miscvalue)
4567 return;
4569 if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
4571 // eating anim
4572 m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
4574 else if( GetId() == 20577 )
4576 // cannibalize anim
4577 m_target->HandleEmoteCommand(398);
4580 // Warrior talent, gain 1 rage every 3 seconds while in combat
4581 if(pt == POWER_RAGE && m_target->isInCombat())
4583 m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
4584 m_periodicTimer += 1000;
4587 m_isPeriodic = apply;
4588 if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
4589 ((Player*)m_target)->UpdateManaRegen();
4592 void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
4594 // spells required only Real aura add/remove
4595 if(!Real)
4596 return;
4598 if (m_target->GetTypeId() != TYPEID_PLAYER)
4599 return;
4601 // Update manaregen value
4602 if (m_modifier.m_miscvalue == POWER_MANA)
4603 ((Player*)m_target)->UpdateManaRegen();
4606 void Aura::HandleModManaRegen(bool /*apply*/, bool Real)
4608 // spells required only Real aura add/remove
4609 if(!Real)
4610 return;
4612 if (m_target->GetTypeId() != TYPEID_PLAYER)
4613 return;
4615 //Note: an increase in regen does NOT cause threat.
4616 ((Player*)m_target)->UpdateManaRegen();
4619 void Aura::HandleComprehendLanguage(bool apply, bool Real)
4621 if(apply)
4622 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4623 else
4624 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4627 void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
4629 // Special case with temporary increase max/current health
4630 switch(GetId())
4632 case 12976: // Warrior Last Stand triggered spell
4633 case 28726: // Nightmare Seed ( Nightmare Seed )
4634 case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
4635 case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
4637 if(Real)
4639 if(apply)
4641 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4642 m_target->ModifyHealth(m_modifier.m_amount);
4644 else
4646 if (int32(m_target->GetHealth()) > m_modifier.m_amount)
4647 m_target->ModifyHealth(-m_modifier.m_amount);
4648 else
4649 m_target->SetHealth(1);
4650 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4653 return;
4657 // generic case
4658 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4661 void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
4663 uint32 oldhealth = m_target->GetHealth();
4664 double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
4666 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4668 // refresh percentage
4669 if(oldhealth > 0)
4671 uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
4672 if(newhealth==0)
4673 newhealth = 1;
4675 m_target->SetHealth(newhealth);
4679 void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
4681 Powers powerType = m_target->getPowerType();
4682 if(int32(powerType) != m_modifier.m_miscvalue)
4683 return;
4685 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4687 m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4690 void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/)
4692 Powers powerType = m_target->getPowerType();
4693 if(int32(powerType) != m_modifier.m_miscvalue)
4694 return;
4696 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4698 m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply);
4701 void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/)
4703 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
4706 /********************************/
4707 /*** FIGHT ***/
4708 /********************************/
4710 void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real)
4712 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4713 return;
4715 ((Player*)m_target)->UpdateParryPercentage();
4718 void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real)
4720 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4721 return;
4723 ((Player*)m_target)->UpdateDodgePercentage();
4724 //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
4727 void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real)
4729 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4730 return;
4732 ((Player*)m_target)->UpdateBlockPercentage();
4733 //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
4736 void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real)
4738 // spells required only Real aura add/remove
4739 if(!Real)
4740 return;
4742 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4743 return;
4745 ((Player*)m_target)->UpdateManaRegen();
4748 void Aura::HandleAuraModCritPercent(bool apply, bool Real)
4750 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4751 return;
4753 // apply item specific bonuses for already equipped weapon
4754 if(Real)
4756 for(int i = 0; i < MAX_ATTACK; ++i)
4757 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4758 ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
4761 // mods must be applied base at equipped weapon class and subclass comparison
4762 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4763 // m_modifier.m_miscvalue comparison with item generated damage types
4765 if (GetSpellProto()->EquippedItemClass == -1)
4767 ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4768 ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4769 ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4771 else
4773 // done in Player::_ApplyWeaponDependentAuraMods
4777 void Aura::HandleModHitChance(bool apply, bool Real)
4779 m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4780 m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4783 void Aura::HandleModSpellHitChance(bool apply, bool Real)
4785 m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
4788 void Aura::HandleModSpellCritChance(bool apply, bool Real)
4790 // spells required only Real aura add/remove
4791 if(!Real)
4792 return;
4794 if(m_target->GetTypeId() == TYPEID_PLAYER)
4796 ((Player*)m_target)->UpdateAllSpellCritChances();
4798 else
4800 m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
4804 void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
4806 // spells required only Real aura add/remove
4807 if(!Real)
4808 return;
4810 if(m_target->GetTypeId() != TYPEID_PLAYER)
4811 return;
4813 for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
4814 if (m_modifier.m_miscvalue & (1<<school))
4815 ((Player*)m_target)->UpdateSpellCritChance(school);
4818 /********************************/
4819 /*** ATTACK SPEED ***/
4820 /********************************/
4822 void Aura::HandleModCastingSpeed(bool apply, bool Real)
4824 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4827 void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
4829 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4830 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4831 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4834 void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
4836 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4837 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4838 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4839 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4842 void Aura::HandleModAttackSpeed(bool apply, bool Real)
4844 if(!m_target->isAlive() )
4845 return;
4847 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4850 void Aura::HandleHaste(bool apply, bool Real)
4852 m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
4853 m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
4854 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
4857 void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
4859 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4862 void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
4864 if(m_target->GetTypeId() != TYPEID_PLAYER)
4865 return;
4866 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
4869 /********************************/
4870 /*** ATTACK POWER ***/
4871 /********************************/
4873 void Aura::HandleAuraModAttackPower(bool apply, bool Real)
4875 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4878 void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
4880 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4881 return;
4883 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4886 void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
4888 //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
4889 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
4892 void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
4894 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4895 return;
4897 //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
4898 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
4901 void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
4903 // spells required only Real aura add/remove
4904 if(!Real)
4905 return;
4907 if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4908 return;
4910 if(m_modifier.m_miscvalue != STAT_INTELLECT)
4912 // support required adding UpdateAttackPowerAndDamage calls at stat update
4913 sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intelect stats!");
4914 return;
4917 // Recalculate bonus
4918 ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
4921 /********************************/
4922 /*** DAMAGE BONUS ***/
4923 /********************************/
4924 void Aura::HandleModDamageDone(bool apply, bool Real)
4926 // apply item specific bonuses for already equipped weapon
4927 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
4929 for(int i = 0; i < MAX_ATTACK; ++i)
4930 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4931 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
4934 // m_modifier.m_miscvalue is bitmask of spell schools
4935 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
4936 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
4937 // 127 - full bitmask any damages
4939 // mods must be applied base at equipped weapon class and subclass comparison
4940 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4941 // m_modifier.m_miscvalue comparison with item generated damage types
4943 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
4945 // apply generic physical damage bonuses including wand case
4946 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
4948 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4949 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4950 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4952 else
4954 // done in Player::_ApplyWeaponDependentAuraMods
4957 if(m_target->GetTypeId() == TYPEID_PLAYER)
4959 if(m_positive)
4960 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
4961 else
4962 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
4966 // Skip non magic case for speedup
4967 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
4968 return;
4970 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
4972 // wand magic case (skip generic to all item spell bonuses)
4973 // done in Player::_ApplyWeaponDependentAuraMods
4975 // Skip item specific requirements for not wand magic damage
4976 return;
4979 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4980 // This information for client side use only
4981 if(m_target->GetTypeId() == TYPEID_PLAYER)
4983 if(m_positive)
4985 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
4987 if((m_modifier.m_miscvalue & (1<<i)) != 0)
4988 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
4991 else
4993 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
4995 if((m_modifier.m_miscvalue & (1<<i)) != 0)
4996 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
4999 Pet* pet = m_target->GetPet();
5000 if(pet)
5001 pet->UpdateAttackPowerAndDamage();
5005 void Aura::HandleModDamagePercentDone(bool apply, bool Real)
5007 sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
5009 // apply item specific bonuses for already equipped weapon
5010 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5012 for(int i = 0; i < MAX_ATTACK; ++i)
5013 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5014 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5017 // m_modifier.m_miscvalue is bitmask of spell schools
5018 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5019 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
5020 // 127 - full bitmask any damages
5022 // mods must be applied base at equipped weapon class and subclass comparison
5023 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5024 // m_modifier.m_miscvalue comparison with item generated damage types
5026 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5028 // apply generic physical damage bonuses including wand case
5029 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5031 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5032 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5033 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5035 else
5037 // done in Player::_ApplyWeaponDependentAuraMods
5039 // For show in client
5040 if(m_target->GetTypeId() == TYPEID_PLAYER)
5041 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
5044 // Skip non magic case for speedup
5045 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5046 return;
5048 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5050 // wand magic case (skip generic to all item spell bonuses)
5051 // done in Player::_ApplyWeaponDependentAuraMods
5053 // Skip item specific requirements for not wand magic damage
5054 return;
5057 // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
5058 // Send info to client
5059 if(m_target->GetTypeId() == TYPEID_PLAYER)
5060 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
5061 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
5064 void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
5066 // spells required only Real aura add/remove
5067 if(!Real)
5068 return;
5070 sLog.outDebug("AURA MOD OFFHAND DAMAGE");
5072 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5075 /********************************/
5076 /*** POWER COST ***/
5077 /********************************/
5079 void Aura::HandleModPowerCostPCT(bool apply, bool Real)
5081 // spells required only Real aura add/remove
5082 if(!Real)
5083 return;
5085 float amount = m_modifier.m_amount/100.0f;
5086 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5087 if(m_modifier.m_miscvalue & (1<<i))
5088 m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
5091 void Aura::HandleModPowerCost(bool apply, bool Real)
5093 // spells required only Real aura add/remove
5094 if(!Real)
5095 return;
5097 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5098 if(m_modifier.m_miscvalue & (1<<i))
5099 m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
5102 /*********************************************************/
5103 /*** OTHERS ***/
5104 /*********************************************************/
5106 void Aura::HandleShapeshiftBoosts(bool apply)
5108 uint32 spellId = 0;
5109 uint32 spellId2 = 0;
5110 uint32 HotWSpellId = 0;
5112 switch(GetModifier()->m_miscvalue)
5114 case FORM_CAT:
5115 spellId = 3025;
5116 HotWSpellId = 24900;
5117 break;
5118 case FORM_TREE:
5119 spellId = 5420;
5120 break;
5121 case FORM_TRAVEL:
5122 spellId = 5419;
5123 break;
5124 case FORM_AQUA:
5125 spellId = 5421;
5126 break;
5127 case FORM_BEAR:
5128 spellId = 1178;
5129 spellId2 = 21178;
5130 HotWSpellId = 24899;
5131 break;
5132 case FORM_DIREBEAR:
5133 spellId = 9635;
5134 spellId2 = 21178;
5135 HotWSpellId = 24899;
5136 break;
5137 case FORM_BATTLESTANCE:
5138 spellId = 21156;
5139 break;
5140 case FORM_DEFENSIVESTANCE:
5141 spellId = 7376;
5142 break;
5143 case FORM_BERSERKERSTANCE:
5144 spellId = 7381;
5145 break;
5146 case FORM_MOONKIN:
5147 spellId = 24905;
5148 // aura from effect trigger spell
5149 spellId2 = 24907;
5150 break;
5151 case FORM_FLIGHT:
5152 spellId = 33948;
5153 break;
5154 case FORM_FLIGHT_EPIC:
5155 spellId = 40122;
5156 spellId2 = 40121;
5157 break;
5158 case FORM_SPIRITOFREDEMPTION:
5159 spellId = 27792;
5160 spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
5161 break;
5162 case FORM_GHOSTWOLF:
5163 case FORM_AMBIENT:
5164 case FORM_GHOUL:
5165 case FORM_SHADOW:
5166 case FORM_STEALTH:
5167 case FORM_CREATURECAT:
5168 case FORM_CREATUREBEAR:
5169 spellId = 0;
5170 break;
5173 uint32 form = GetModifier()->m_miscvalue-1;
5175 if(apply)
5177 if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
5178 if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
5180 if(m_target->GetTypeId() == TYPEID_PLAYER)
5182 const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
5183 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
5185 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
5186 if(itr->first==spellId || itr->first==spellId2) continue;
5187 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
5188 if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
5189 if (spellInfo->Stances & (1<<form))
5190 m_target->CastSpell(m_target, itr->first, true, NULL, this);
5192 //LotP
5193 if (((Player*)m_target)->HasSpell(17007))
5195 SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
5196 if (spellInfo && spellInfo->Stances & (1<<form))
5197 m_target->CastSpell(m_target, 24932, true, NULL, this);
5199 // HotW
5200 if (HotWSpellId)
5202 Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
5203 for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
5205 if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
5207 int32 HotWMod = (*i)->GetModifier()->m_amount;
5208 if(GetModifier()->m_miscvalue == FORM_CAT)
5209 HotWMod /= 2;
5211 m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
5212 break;
5218 else
5220 m_target->RemoveAurasDueToSpell(spellId);
5221 m_target->RemoveAurasDueToSpell(spellId2);
5223 Unit::AuraMap& tAuras = m_target->GetAuras();
5224 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
5226 if (itr->second->IsRemovedOnShapeLost())
5228 m_target->RemoveAurasDueToSpell(itr->second->GetId());
5229 itr = tAuras.begin();
5231 else
5233 ++itr;
5238 /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
5239 m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
5242 void Aura::HandleAuraEmpathy(bool apply, bool Real)
5244 if(m_target->GetTypeId() != TYPEID_UNIT)
5245 return;
5247 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
5248 if(ci && ci->type == CREATURE_TYPE_BEAST)
5249 m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
5252 void Aura::HandleAuraUntrackable(bool apply, bool Real)
5254 if(apply)
5255 m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5256 else
5257 m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5260 void Aura::HandleAuraModPacify(bool apply, bool Real)
5262 if(m_target->GetTypeId() != TYPEID_PLAYER)
5263 return;
5265 if(apply)
5266 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5267 else
5268 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5271 void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
5273 HandleAuraModPacify(apply,Real);
5274 HandleAuraModSilence(apply,Real);
5277 void Aura::HandleAuraGhost(bool apply, bool Real)
5279 if(m_target->GetTypeId() != TYPEID_PLAYER)
5280 return;
5282 if(apply)
5284 m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5286 else
5288 m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5292 void Aura::HandleAuraAllowFlight(bool apply, bool Real)
5294 // all applied/removed only at real aura add/remove
5295 if(!Real)
5296 return;
5298 // allow fly
5299 WorldPacket data;
5300 if(apply)
5301 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
5302 else
5303 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
5304 data.append(m_target->GetPackGUID());
5305 data << uint32(0); // unk
5306 m_target->SendMessageToSet(&data, true);
5309 void Aura::HandleModRating(bool apply, bool Real)
5311 // spells required only Real aura add/remove
5312 if(!Real)
5313 return;
5315 if(m_target->GetTypeId() != TYPEID_PLAYER)
5316 return;
5318 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5319 if (m_modifier.m_miscvalue & (1 << rating))
5320 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
5323 void Aura::HandleForceMoveForward(bool apply, bool Real)
5325 if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
5326 return;
5327 if(apply)
5328 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5329 else
5330 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5333 void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real)
5335 if(m_target->GetTypeId() != TYPEID_PLAYER)
5336 return;
5338 ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
5339 ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
5342 void Aura::HandleModTargetResistance(bool apply, bool Real)
5344 // spells required only Real aura add/remove
5345 if(!Real)
5346 return;
5347 // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
5349 // show armor penetration
5350 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
5351 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
5353 // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
5354 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
5355 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
5358 void Aura::HandleShieldBlockValue(bool apply, bool Real)
5360 BaseModType modType = FLAT_MOD;
5361 if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
5362 modType = PCT_MOD;
5364 if(m_target->GetTypeId() == TYPEID_PLAYER)
5365 ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
5368 void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
5370 // spells required only Real aura add/remove
5371 if(!Real)
5372 return;
5374 if(m_target->GetTypeId() != TYPEID_PLAYER)
5375 return;
5377 Player *target = (Player*)m_target;
5379 // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
5380 // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
5381 if( !apply && m_duration==0 && target->GetComboTarget())
5382 if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
5383 target->AddComboPoints(unit, -m_modifier.m_amount);
5386 void Aura::HandleModUnattackable( bool Apply, bool Real )
5388 if(Real && Apply)
5389 m_target->CombatStop();
5391 m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
5394 void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
5396 // spells required only Real aura add/remove
5397 if(!Real)
5398 return;
5400 // prepare spirit state
5401 if(apply)
5403 if(m_target->GetTypeId()==TYPEID_PLAYER)
5405 // disable breath/etc timers
5406 ((Player*)m_target)->StopMirrorTimers();
5408 // set stand state (expected in this form)
5409 if(!m_target->IsStandState())
5410 m_target->SetStandState(PLAYER_STATE_NONE);
5413 m_target->SetHealth(1);
5415 // die at aura end
5416 else
5417 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
5420 void Aura::CleanupTriggeredSpells()
5422 uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
5423 if(!tSpellId)
5424 return;
5426 SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
5427 if(!tProto)
5428 return;
5430 if(GetSpellDuration(tProto) != -1)
5431 return;
5433 // needed for spell 43680, maybe others
5434 // TODO: is there a spell flag, which can solve this in a more sophisticated way?
5435 if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
5436 GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
5437 return;
5438 m_target->RemoveAurasDueToSpell(tSpellId);
5441 void Aura::HandleAuraPowerBurn(bool apply, bool Real)
5443 if (m_periodicTimer <= 0)
5444 m_periodicTimer += m_modifier.periodictime;
5446 m_isPeriodic = apply;
5449 void Aura::HandleSchoolAbsorb(bool apply, bool Real)
5451 if(!Real)
5452 return;
5454 // prevent double apply bonuses
5455 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
5457 if(Unit* caster = GetCaster())
5459 float DoneActualBenefit = 0.0f;
5460 switch(m_spellProto->SpellFamilyName)
5462 case SPELLFAMILY_PRIEST:
5463 if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
5465 //+30% from +healing bonus
5466 DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
5467 break;
5469 break;
5470 case SPELLFAMILY_MAGE:
5471 if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
5473 //frost ward, fire ward, ice barrier
5474 //+10% from +spd bonus
5475 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5476 break;
5478 break;
5479 case SPELLFAMILY_WARLOCK:
5480 if(m_spellProto->SpellFamilyFlags == 0x00)
5482 //shadow ward
5483 //+10% from +spd bonus
5484 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5485 break;
5487 break;
5488 default:
5489 break;
5492 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
5494 m_modifier.m_amount += (int32)DoneActualBenefit;
5499 void Aura::PeriodicTick()
5501 if(!m_target->isAlive())
5502 return;
5504 switch(m_modifier.m_auraname)
5506 case SPELL_AURA_PERIODIC_DAMAGE:
5507 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
5509 Unit *pCaster = GetCaster();
5510 if(!pCaster)
5511 return;
5513 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5514 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5515 return;
5517 // Check for immune (not use charges)
5518 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5519 return;
5521 // some auras remove at specific health level or more
5522 if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
5524 switch(GetId())
5526 case 43093: case 31956: case 38801:
5527 case 35321: case 38363: case 39215:
5528 if(m_target->GetHealth() == m_target->GetMaxHealth() )
5530 m_target->RemoveAurasDueToSpell(GetId());
5531 return;
5533 break;
5534 case 38772:
5536 uint32 percent =
5537 GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
5538 pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
5539 100;
5540 if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
5542 m_target->RemoveAurasDueToSpell(GetId());
5543 return;
5545 break;
5547 default:
5548 break;
5552 uint32 absorb=0;
5553 uint32 resist=0;
5554 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5556 // ignore non positive values (can be result apply spellmods to aura damage
5557 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5559 uint32 pdamage;
5561 if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
5563 pdamage = amount;
5565 // Calculate armor mitigation if it is a physical spell
5566 // But not for bleed mechanic spells
5567 if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
5568 GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
5570 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5571 cleanDamage.damage += pdamage - pdamageReductedArmor;
5572 pdamage = pdamageReductedArmor;
5575 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5577 // Curse of Agony damage-per-tick calculation
5578 if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
5580 // 1..4 ticks, 1/2 from normal tick damage
5581 if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
5582 pdamage = pdamage/2;
5583 // 9..12 ticks, 3/2 from normal tick damage
5584 else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
5585 pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
5586 // 5..8 ticks have normal tick damage
5589 else
5590 pdamage = uint32(m_target->GetMaxHealth()*amount/100);
5592 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5593 // Reduce dot damage from resilience for players
5594 if (m_target->GetTypeId()==TYPEID_PLAYER)
5595 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5597 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5599 sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5600 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5602 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5603 data.append(m_target->GetPackGUID());
5604 data.appendPackGUID(GetCasterGUID());
5605 data << uint32(GetId());
5606 data << uint32(1);
5607 data << uint32(m_modifier.m_auraname);
5608 data << (uint32)pdamage;
5609 data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
5610 data << (uint32)absorb;
5611 data << (uint32)resist;
5612 m_target->SendMessageToSet(&data,true);
5614 Unit* target = m_target; // aura can be deleted in DealDamage
5615 SpellEntry const* spellProto = GetSpellProto();
5617 pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5619 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5621 pCaster->ProcDamageAndSpell(target, PROC_FLAG_NONE, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), GetSpellSchoolMask(spellProto), spellProto);
5622 break;
5624 case SPELL_AURA_PERIODIC_LEECH:
5626 Unit *pCaster = GetCaster();
5627 if(!pCaster)
5628 return;
5630 if(!pCaster->isAlive())
5631 return;
5633 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5634 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5635 return;
5637 // Check for immune (not use charges)
5638 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5639 return;
5641 uint32 absorb=0;
5642 uint32 resist=0;
5643 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5645 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5647 //Calculate armor mitigation if it is a physical spell
5648 if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
5650 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5651 cleanDamage.damage += pdamage - pdamageReductedArmor;
5652 pdamage = pdamageReductedArmor;
5655 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5657 // talent Soul Siphon add bonus to Drain Life spells
5658 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
5660 // find talent max bonus percentage
5661 Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5662 for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
5664 if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
5666 if((*i)->GetEffIndex()!=1)
5668 sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
5669 break;
5672 // effect 1 m_amount
5673 int32 maxPercent = (*i)->GetModifier()->m_amount;
5674 // effect 0 m_amount
5675 int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
5677 // count affliction effects and calc additional damage in percentage
5678 int32 modPercent = 0;
5679 Unit::AuraMap const& victimAuras = m_target->GetAuras();
5680 for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
5682 Aura* aura = itr->second;
5683 if (aura->IsPositive())continue;
5684 SpellEntry const* m_spell = aura->GetSpellProto();
5685 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
5686 continue;
5688 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
5689 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
5691 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
5693 if(_spell_idx->second->skillId == SKILL_AFFLICTION)
5695 modPercent += stepPercent;
5696 if (modPercent >= maxPercent)
5698 modPercent = maxPercent;
5699 break;
5704 pdamage += (pdamage*modPercent/100);
5705 break;
5710 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5711 // Reduce dot damage from resilience for players
5712 if (m_target->GetTypeId()==TYPEID_PLAYER)
5713 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5715 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5717 if(m_target->GetHealth() < pdamage)
5718 pdamage = uint32(m_target->GetHealth());
5720 sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5721 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5723 pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
5726 Unit* target = m_target; // aura can be deleted in DealDamage
5727 SpellEntry const* spellProto = GetSpellProto();
5728 float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
5730 uint32 new_damage = pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
5732 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5734 pCaster->ProcDamageAndSpell(target, PROC_FLAG_HEALED, PROC_FLAG_TAKE_DAMAGE, new_damage, GetSpellSchoolMask(spellProto), spellProto);
5735 if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
5737 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
5739 if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
5740 pCaster->m_currentSpells[i]->cancel();
5745 if(Player *modOwner = pCaster->GetSpellModOwner())
5746 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
5748 uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
5750 int32 gain = pCaster->ModifyHealth(heal);
5751 pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
5753 pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
5754 break;
5756 case SPELL_AURA_PERIODIC_HEAL:
5757 case SPELL_AURA_OBS_MOD_HEALTH:
5759 Unit *pCaster = GetCaster();
5760 if(!pCaster)
5761 return;
5763 // heal for caster damage (must be alive)
5764 if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive())
5765 return;
5767 // ignore non positive values (can be result apply spellmods to aura damage
5768 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5770 uint32 pdamage;
5772 if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
5773 pdamage = uint32(m_target->GetMaxHealth() * amount/100);
5774 else
5775 pdamage = amount;
5777 pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
5779 sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
5780 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5782 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5783 data.append(m_target->GetPackGUID());
5784 data.appendPackGUID(GetCasterGUID());
5785 data << uint32(GetId());
5786 data << uint32(1);
5787 data << uint32(m_modifier.m_auraname);
5788 data << (uint32)pdamage;
5789 m_target->SendMessageToSet(&data,true);
5791 int32 gain = m_target->ModifyHealth(pdamage);
5793 // add HoTs to amount healed in bgs
5794 if( pCaster->GetTypeId() == TYPEID_PLAYER )
5795 if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
5796 bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
5798 //Do check before because m_modifier.auraName can be invalidate by DealDamage.
5799 bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
5801 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5803 Unit* target = m_target; // aura can be deleted in DealDamage
5804 SpellEntry const* spellProto = GetSpellProto();
5805 bool haveCastItem = GetCastItemGUID()!=0;
5807 // heal for caster damage
5808 if(m_target!=pCaster && spellProto->SpellVisual==163)
5810 uint32 dmg = spellProto->manaPerSecond;
5811 if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
5813 pCaster->RemoveAurasDueToSpell(GetId());
5815 // finish current generic/channeling spells, don't affect autorepeat
5816 if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
5818 pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
5820 if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
5822 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
5823 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
5826 else
5828 pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
5830 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5831 pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5835 // ignore item heals
5836 if(procSpell && !haveCastItem)
5837 pCaster->ProcDamageAndSpell(target,PROC_FLAG_NONE, PROC_FLAG_HEALED, pdamage, SPELL_SCHOOL_MASK_NONE, spellProto);
5838 break;
5840 case SPELL_AURA_PERIODIC_MANA_LEECH:
5842 Unit *pCaster = GetCaster();
5843 if(!pCaster)
5844 return;
5846 if(!pCaster->isAlive())
5847 return;
5849 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5850 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5851 return;
5853 // Check for immune (not use charges)
5854 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5855 return;
5857 // ignore non positive values (can be result apply spellmods to aura damage
5858 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5860 sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
5861 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5863 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5864 break;
5866 Powers power = Powers(m_modifier.m_miscvalue);
5868 // power type might have changed between aura applying and tick (druid's shapeshift)
5869 if(m_target->getPowerType() != power)
5870 break;
5872 int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
5874 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
5875 if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
5876 drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
5878 m_target->ModifyPower(power, -drain_amount);
5880 float gain_multiplier = 0;
5882 if(pCaster->GetMaxPower(power) > 0)
5884 gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
5886 if(Player *modOwner = pCaster->GetSpellModOwner())
5887 modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
5890 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5891 data.append(m_target->GetPackGUID());
5892 data.appendPackGUID(GetCasterGUID());
5893 data << uint32(GetId());
5894 data << uint32(1);
5895 data << uint32(m_modifier.m_auraname);
5896 data << (uint32)power; // power type
5897 data << (uint32)drain_amount;
5898 data << (float)gain_multiplier;
5899 m_target->SendMessageToSet(&data,true);
5901 int32 gain_amount = int32(drain_amount*gain_multiplier);
5903 if(gain_amount)
5905 int32 gain = pCaster->ModifyPower(power,gain_amount);
5906 m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
5908 break;
5910 case SPELL_AURA_PERIODIC_ENERGIZE:
5912 // ignore non positive values (can be result apply spellmods to aura damage
5913 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5915 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
5916 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5918 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5919 break;
5921 Powers power = Powers(m_modifier.m_miscvalue);
5923 if(m_target->GetMaxPower(power) == 0)
5924 break;
5926 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5927 data.append(m_target->GetPackGUID());
5928 data.appendPackGUID(GetCasterGUID());
5929 data << uint32(GetId());
5930 data << uint32(1);
5931 data << uint32(m_modifier.m_auraname);
5932 data << (uint32)power; // power type
5933 data << (uint32)pdamage;
5934 m_target->SendMessageToSet(&data,true);
5936 int32 gain = m_target->ModifyPower(power,pdamage);
5938 if(Unit* pCaster = GetCaster())
5939 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5940 break;
5942 case SPELL_AURA_OBS_MOD_MANA:
5944 // ignore non positive values (can be result apply spellmods to aura damage
5945 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5947 uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
5949 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
5950 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5952 if(m_target->GetMaxPower(POWER_MANA) == 0)
5953 break;
5955 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5956 data.append(m_target->GetPackGUID());
5957 data.appendPackGUID(GetCasterGUID());
5958 data << uint32(GetId());
5959 data << uint32(1);
5960 data << uint32(m_modifier.m_auraname);
5961 data << (uint32)0; // ?
5962 data << (uint32)pdamage;
5963 m_target->SendMessageToSet(&data,true);
5965 int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
5967 if(Unit* pCaster = GetCaster())
5968 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5969 break;
5971 case SPELL_AURA_POWER_BURN_MANA:
5973 Unit *pCaster = GetCaster();
5974 if(!pCaster)
5975 return;
5977 // Check for immune (not use charges)
5978 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5979 return;
5981 int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5983 Powers powerType = Powers(m_modifier.m_miscvalue);
5985 if(!m_target->isAlive() || m_target->getPowerType() != powerType)
5986 return;
5988 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
5989 if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
5990 pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
5992 uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
5994 gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
5996 //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
5997 pCaster->SpellNonMeleeDamageLog(m_target, GetId(), gain);
5998 break;
6000 // Here tick dummy auras
6001 case SPELL_AURA_PERIODIC_DUMMY:
6003 PeriodicDummyTick();
6004 break;
6006 default:
6007 break;
6011 void Aura::PeriodicDummyTick()
6013 SpellEntry const* spell = GetSpellProto();
6014 switch (spell->Id)
6016 // Drink
6017 case 430:
6018 case 431:
6019 case 432:
6020 case 1133:
6021 case 1135:
6022 case 1137:
6023 case 10250:
6024 case 22734:
6025 case 27089:
6026 case 34291:
6027 case 43706:
6028 case 46755:
6030 if (m_target->GetTypeId() != TYPEID_PLAYER)
6031 return;
6032 // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
6033 Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
6034 for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
6036 if ((*i)->GetId() == GetId())
6038 // Get tick number
6039 int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
6040 // Default case (not on arenas)
6041 if (tick == 0)
6043 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6044 ((Player*)m_target)->UpdateManaRegen();
6045 // Disable continue
6046 m_isPeriodic = false;
6048 return;
6049 //**********************************************
6050 // Code commended since arena patch not added
6051 // This feature uses only in arenas
6052 //**********************************************
6053 // Here need increase mana regen per tick (6 second rule)
6054 // on 0 tick - 0 (handled in 2 second)
6055 // on 1 tick - 166% (handled in 4 second)
6056 // on 2 tick - 133% (handled in 6 second)
6057 // Not need update after 3 tick
6059 if (tick > 3)
6060 return;
6061 // Apply bonus for 0 - 3 tick
6062 switch (tick)
6064 case 0: // 0%
6065 (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
6066 break;
6067 case 1: // 166%
6068 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
6069 break;
6070 case 2: // 133%
6071 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
6072 break;
6073 default: // 100% - normal regen
6074 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6075 break;
6077 ((Player*)m_target)->UpdateManaRegen();
6078 return;*/
6081 return;
6083 // // Panda
6084 // case 19230: break;
6085 // // Master of Subtlety
6086 // case 31666: break;
6087 // // Gossip NPC Periodic - Talk
6088 // case 33208: break;
6089 // // Gossip NPC Periodic - Despawn
6090 // case 33209: break;
6091 // // Force of Nature
6092 // case 33831: break;
6093 // Aspect of the Viper
6094 case 34074:
6096 if (m_target->GetTypeId() != TYPEID_PLAYER)
6097 return;
6098 // Should be manauser
6099 if (m_target->getPowerType()!=POWER_MANA)
6100 return;
6101 Unit *caster = GetCaster();
6102 if (!caster)
6103 return;
6104 // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
6105 int mana = m_target->GetPower(POWER_MANA);
6106 int max_mana = m_target->GetMaxPower(POWER_MANA);
6107 int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
6108 float regen_pct = 1.20f - 1.1f * mana / max_mana;
6109 if (regen_pct > 1.0f) regen_pct = 1.0f;
6110 else if (regen_pct < 0.2f) regen_pct = 0.2f;
6111 m_modifier.m_amount = int32 (base_regen * regen_pct);
6112 ((Player*)m_target)->UpdateManaRegen();
6113 return;
6115 // // Steal Weapon
6116 // case 36207: break;
6117 // // Simon Game START timer, (DND)
6118 // case 39993: break;
6119 // // Harpooner's Mark
6120 // case 40084: break;
6121 // // Knockdown Fel Cannon: break; The Aggro Burst
6122 // case 40119: break;
6123 // // Old Mount Spell
6124 // case 40154: break;
6125 // // Magnetic Pull
6126 // case 40581: break;
6127 // // Ethereal Ring: break; The Bolt Burst
6128 // case 40801: break;
6129 // // Crystal Prison
6130 // case 40846: break;
6131 // // Copy Weapon
6132 // case 41054: break;
6133 // // Ethereal Ring Visual, Lightning Aura
6134 // case 41477: break;
6135 // // Ethereal Ring Visual, Lightning Aura (Fork)
6136 // case 41525: break;
6137 // // Ethereal Ring Visual, Lightning Jumper Aura
6138 // case 41567: break;
6139 // // No Man's Land
6140 // case 41955: break;
6141 // // Headless Horseman - Fire
6142 // case 42074: break;
6143 // // Headless Horseman - Visual - Large Fire
6144 // case 42075: break;
6145 // // Headless Horseman - Start Fire, Periodic Aura
6146 // case 42140: break;
6147 // // Ram Speed Boost
6148 // case 42152: break;
6149 // // Headless Horseman - Fires Out Victory Aura
6150 // case 42235: break;
6151 // // Pumpkin Life Cycle
6152 // case 42280: break;
6153 // // Brewfest Request Chick Chuck Mug Aura
6154 // case 42537: break;
6155 // // Squashling
6156 // case 42596: break;
6157 // // Headless Horseman Climax, Head: Periodic
6158 // case 42603: break;
6159 // // Fire Bomb
6160 // case 42621: break;
6161 // // Headless Horseman - Conflagrate, Periodic Aura
6162 // case 42637: break;
6163 // // Headless Horseman - Create Pumpkin Treats Aura
6164 // case 42774: break;
6165 // // Headless Horseman Climax - Summoning Rhyme Aura
6166 // case 42879: break;
6167 // // Tricky Treat
6168 // case 42919: break;
6169 // // Giddyup!
6170 // case 42924: break;
6171 // // Ram - Trot
6172 // case 42992: break;
6173 // // Ram - Canter
6174 // case 42993: break;
6175 // // Ram - Gallop
6176 // case 42994: break;
6177 // // Ram Level - Neutral
6178 // case 43310: break;
6179 // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
6180 // case 43884: break;
6181 // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
6182 // case 44000: break;
6183 // // Energy Feedback
6184 // case 44328: break;
6185 // // Romantic Picnic
6186 // case 45102: break;
6187 // // Romantic Picnic
6188 // case 45123: break;
6189 // // Looking for Love
6190 // case 45124: break;
6191 // // Kite - Lightning Strike Kite Aura
6192 // case 45197: break;
6193 // // Rocket Chicken
6194 // case 45202: break;
6195 // // Copy Offhand Weapon
6196 // case 45205: break;
6197 // // Upper Deck - Kite - Lightning Periodic Aura
6198 // case 45207: break;
6199 // // Kite -Sky Lightning Strike Kite Aura
6200 // case 45251: break;
6201 // // Ribbon Pole Dancer Check Aura
6202 // case 45390: break;
6203 // // Holiday - Midsummer, Ribbon Pole Periodic Visual
6204 // case 45406: break;
6205 // // Parachute
6206 // case 45472: break;
6207 // // Alliance Flag, Extra Damage Debuff
6208 // case 45898: break;
6209 // // Horde Flag, Extra Damage Debuff
6210 // case 45899: break;
6211 // // Ahune - Summoning Rhyme Aura
6212 // case 45926: break;
6213 // // Ahune - Slippery Floor
6214 // case 45945: break;
6215 // // Ahune's Shield
6216 // case 45954: break;
6217 // // Nether Vapor Lightning
6218 // case 45960: break;
6219 // // Darkness
6220 // case 45996: break;
6221 // // Summon Blood Elves Periodic
6222 // case 46041: break;
6223 // // Transform Visual Missile Periodic
6224 // case 46205: break;
6225 // // Find Opening Beam End
6226 // case 46333: break;
6227 // // Ice Spear Control Aura
6228 // case 46371: break;
6229 // // Hailstone Chill
6230 // case 46458: break;
6231 // // Hailstone Chill, Internal
6232 // case 46465: break;
6233 // // Chill, Internal Shifter
6234 // case 46549: break;
6235 // // Summon Ice Spear Knockback Delayer
6236 // case 46878: break;
6237 // // Burninate Effect
6238 // case 47214: break;
6239 // // Fizzcrank Practice Parachute
6240 // case 47228: break;
6241 // // Send Mug Control Aura
6242 // case 47369: break;
6243 // // Direbrew's Disarm (precast)
6244 // case 47407: break;
6245 // // Mole Machine Port Schedule
6246 // case 47489: break;
6247 // // Mole Machine Portal Schedule
6248 // case 49466: break;
6249 // // Drink Coffee
6250 // case 49472: break;
6251 // // Listening to Music
6252 // case 50493: break;
6253 // // Love Rocket Barrage
6254 // case 50530: break;
6255 default:
6256 break;
6260 void Aura::HandlePreventFleeing(bool apply, bool Real)
6262 if(!Real)
6263 return;
6265 Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
6266 if( !fearAuras.empty() )
6268 if (apply)
6269 m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
6270 else
6271 m_target->SetFeared(true);
6275 void Aura::HandleManaShield(bool apply, bool Real)
6277 if(!Real)
6278 return;
6280 // prevent double apply bonuses
6281 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
6283 if(Unit* caster = GetCaster())
6285 float DoneActualBenefit = 0.0f;
6286 switch(m_spellProto->SpellFamilyName)
6288 case SPELLFAMILY_MAGE:
6289 if(m_spellProto->SpellFamilyFlags & 0x8000)
6291 // Mana Shield
6292 // +50% from +spd bonus
6293 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
6294 break;
6296 break;
6297 default:
6298 break;
6301 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
6303 m_modifier.m_amount += (int32)DoneActualBenefit;
6308 void Aura::HandleArenaPreparation(bool apply, bool Real)
6310 if(!Real)
6311 return;
6313 if(apply)
6314 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6315 else
6316 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);