Merge branch 'master' of git@github.com:mangos/mangos.git into procflag
[getmangos.git] / src / game / SpellAuras.cpp
blobd1cf865681f06402164e4ca4a84841d4dac15922
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::CalculateMeleeDamage and Unit::CalculateSpellDamage
257 &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
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 m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
2152 return;
2155 // Predatory Strikes
2156 if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
2158 ((Player*)m_target)->UpdateAttackPowerAndDamage();
2159 return;
2161 // Idol of the Emerald Queen
2162 if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
2164 if(apply)
2166 SpellModifier *mod = new SpellModifier;
2167 mod->op = SPELLMOD_DOT;
2168 mod->value = m_modifier.m_amount/7;
2169 mod->type = SPELLMOD_FLAT;
2170 mod->spellId = GetId();
2171 mod->effectId = m_effIndex;
2172 mod->lastAffected = NULL;
2173 mod->mask = 0x001000000000LL;
2174 mod->charges = 0;
2176 m_spellmod = mod;
2179 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2180 return;
2182 break;
2184 case SPELLFAMILY_HUNTER:
2186 // Improved Aspect of the Viper
2187 if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
2189 if(apply)
2191 // + effect value for Aspect of the Viper
2192 SpellModifier *mod = new SpellModifier;
2193 mod->op = SPELLMOD_EFFECT1;
2194 mod->value = m_modifier.m_amount;
2195 mod->type = SPELLMOD_FLAT;
2196 mod->spellId = GetId();
2197 mod->effectId = m_effIndex;
2198 mod->lastAffected = NULL;
2199 mod->mask = 0x4000000000000LL;
2200 mod->charges = 0;
2202 m_spellmod = mod;
2205 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2206 return;
2208 break;
2210 case SPELLFAMILY_SHAMAN:
2212 // Improved Weapon Totems
2213 if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
2215 if(apply)
2217 SpellModifier *mod = new SpellModifier;
2218 mod->op = SPELLMOD_EFFECT1;
2219 mod->value = m_modifier.m_amount;
2220 mod->type = SPELLMOD_PCT;
2221 mod->spellId = GetId();
2222 mod->effectId = m_effIndex;
2223 mod->lastAffected = NULL;
2224 switch (m_effIndex)
2226 case 0:
2227 mod->mask = 0x00200000000LL; // Windfury Totem
2228 break;
2229 case 1:
2230 mod->mask = 0x00400000000LL; // Flametongue Totem
2231 break;
2233 mod->charges = 0;
2235 m_spellmod = mod;
2238 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2239 return;
2241 break;
2245 // pet auras
2246 if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
2248 if(apply)
2249 m_target->AddPetAura(petSpell);
2250 else
2251 m_target->RemovePetAura(petSpell);
2252 return;
2256 void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
2258 // spells required only Real aura add/remove
2259 if(!Real)
2260 return;
2262 SpellEntry const*spell = GetSpellProto();
2263 switch( spell->SpellFamilyName)
2265 case SPELLFAMILY_ROGUE:
2267 // Master of Subtlety
2268 if (spell->Id==31666 && !apply && Real)
2270 m_target->RemoveAurasDueToSpell(31665);
2271 break;
2273 break;
2275 case SPELLFAMILY_HUNTER:
2277 // Aspect of the Viper
2278 if (spell->SpellFamilyFlags&0x0004000000000000LL)
2280 // Update regen on remove
2281 if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
2282 ((Player*)m_target)->UpdateManaRegen();
2283 break;
2285 break;
2289 m_isPeriodic = apply;
2292 void Aura::HandleAuraMounted(bool apply, bool Real)
2294 // only at real add/remove aura
2295 if(!Real)
2296 return;
2298 if(apply)
2300 CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2301 if(!ci)
2303 sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
2304 return;
2307 uint32 team = 0;
2308 if (m_target->GetTypeId()==TYPEID_PLAYER)
2309 team = ((Player*)m_target)->GetTeam();
2311 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2312 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2313 if (minfo)
2314 display_id = minfo->modelid;
2316 m_target->Mount(display_id);
2318 else
2320 m_target->Unmount();
2324 void Aura::HandleAuraWaterWalk(bool apply, bool Real)
2326 // only at real add/remove aura
2327 if(!Real)
2328 return;
2330 WorldPacket data;
2331 if(apply)
2332 data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
2333 else
2334 data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
2335 data.append(m_target->GetPackGUID());
2336 data << uint32(0);
2337 m_target->SendMessageToSet(&data,true);
2340 void Aura::HandleAuraFeatherFall(bool apply, bool Real)
2342 // only at real add/remove aura
2343 if(!Real)
2344 return;
2346 WorldPacket data;
2347 if(apply)
2348 data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
2349 else
2350 data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
2351 data.append(m_target->GetPackGUID());
2352 data << (uint32)0;
2353 m_target->SendMessageToSet(&data,true);
2356 void Aura::HandleAuraHover(bool apply, bool Real)
2358 // only at real add/remove aura
2359 if(!Real)
2360 return;
2362 WorldPacket data;
2363 if(apply)
2364 data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
2365 else
2366 data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
2367 data.append(m_target->GetPackGUID());
2368 data << uint32(0);
2369 m_target->SendMessageToSet(&data,true);
2372 void Aura::HandleWaterBreathing(bool apply, bool Real)
2374 if(apply)
2375 m_target->waterbreath = true;
2376 else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
2378 m_target->waterbreath = false;
2380 // update for enable timer in case not moving target
2381 if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
2383 ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
2384 ((Player*)m_target)->HandleDrowning();
2389 void Aura::HandleAuraModShapeshift(bool apply, bool Real)
2391 if(!Real)
2392 return;
2394 uint32 modelid = 0;
2395 Powers PowerType = POWER_MANA;
2396 ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
2397 switch(form)
2399 case FORM_CAT:
2400 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2401 modelid = 892;
2402 else
2403 modelid = 8571;
2404 PowerType = POWER_ENERGY;
2405 break;
2406 case FORM_TRAVEL:
2407 modelid = 632;
2408 break;
2409 case FORM_AQUA:
2410 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2411 modelid = 2428;
2412 else
2413 modelid = 2428;
2414 break;
2415 case FORM_BEAR:
2416 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2417 modelid = 2281;
2418 else
2419 modelid = 2289;
2420 PowerType = POWER_RAGE;
2421 break;
2422 case FORM_GHOUL:
2423 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2424 modelid = 10045;
2425 break;
2426 case FORM_DIREBEAR:
2427 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2428 modelid = 2281;
2429 else
2430 modelid = 2289;
2431 PowerType = POWER_RAGE;
2432 break;
2433 case FORM_CREATUREBEAR:
2434 modelid = 902;
2435 break;
2436 case FORM_GHOSTWOLF:
2437 modelid = 4613;
2438 break;
2439 case FORM_FLIGHT:
2440 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2441 modelid = 20857;
2442 else
2443 modelid = 20872;
2444 break;
2445 case FORM_MOONKIN:
2446 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2447 modelid = 15374;
2448 else
2449 modelid = 15375;
2450 break;
2451 case FORM_FLIGHT_EPIC:
2452 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2453 modelid = 21243;
2454 else
2455 modelid = 21244;
2456 break;
2457 case FORM_AMBIENT:
2458 case FORM_SHADOW:
2459 case FORM_STEALTH:
2460 break;
2461 case FORM_TREE:
2462 modelid = 864;
2463 break;
2464 case FORM_BATTLESTANCE:
2465 case FORM_BERSERKERSTANCE:
2466 case FORM_DEFENSIVESTANCE:
2467 PowerType = POWER_RAGE;
2468 break;
2469 case FORM_SPIRITOFREDEMPTION:
2470 modelid = 16031;
2471 break;
2472 default:
2473 sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
2476 // remove polymorph before changing display id to keep new display id
2477 switch ( form )
2479 case FORM_CAT:
2480 case FORM_TREE:
2481 case FORM_TRAVEL:
2482 case FORM_AQUA:
2483 case FORM_BEAR:
2484 case FORM_DIREBEAR:
2485 case FORM_FLIGHT_EPIC:
2486 case FORM_FLIGHT:
2487 case FORM_MOONKIN:
2488 // remove movement affects
2489 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2490 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2492 // and polymorphic affects
2493 if(m_target->IsPolymorphed())
2494 m_target->RemoveAurasDueToSpell(m_target->getTransForm());
2495 break;
2496 default:
2497 break;
2500 if(apply)
2502 // remove other shapeshift before applying a new one
2503 if(m_target->m_ShapeShiftFormSpellId)
2504 m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
2506 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
2508 if(modelid > 0)
2509 m_target->SetDisplayId(modelid);
2511 if(PowerType != POWER_MANA)
2513 // reset power to default values only at power change
2514 if(m_target->getPowerType()!=PowerType)
2515 m_target->setPowerType(PowerType);
2517 switch(form)
2519 case FORM_CAT:
2520 case FORM_BEAR:
2521 case FORM_DIREBEAR:
2523 // get furor proc chance
2524 uint32 FurorChance = 0;
2525 Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2526 for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
2528 if ((*i)->GetSpellProto()->SpellIconID == 238)
2530 FurorChance = (*i)->GetModifier()->m_amount;
2531 break;
2535 if (m_modifier.m_miscvalue == FORM_CAT)
2537 m_target->SetPower(POWER_ENERGY,0);
2538 if(urand(1,100) <= FurorChance)
2539 m_target->CastSpell(m_target,17099,true,NULL,this);
2541 else
2543 m_target->SetPower(POWER_RAGE,0);
2544 if(urand(1,100) <= FurorChance)
2545 m_target->CastSpell(m_target,17057,true,NULL,this);
2547 break;
2549 case FORM_BATTLESTANCE:
2550 case FORM_DEFENSIVESTANCE:
2551 case FORM_BERSERKERSTANCE:
2553 uint32 Rage_val = 0;
2554 // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
2555 if(m_target->GetTypeId() == TYPEID_PLAYER)
2557 PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
2558 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2560 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
2561 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2562 if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
2563 Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
2567 if (m_target->GetPower(POWER_RAGE) > Rage_val)
2568 m_target->SetPower(POWER_RAGE,Rage_val);
2569 break;
2571 default:
2572 break;
2576 m_target->m_ShapeShiftFormSpellId = GetId();
2577 m_target->m_form = form;
2579 else
2581 if(modelid > 0)
2582 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2583 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
2584 if(m_target->getClass() == CLASS_DRUID)
2585 m_target->setPowerType(POWER_MANA);
2586 m_target->m_ShapeShiftFormSpellId = 0;
2587 m_target->m_form = FORM_NONE;
2589 switch(form)
2591 // Nordrassil Harness - bonus
2592 case FORM_BEAR:
2593 case FORM_DIREBEAR:
2594 case FORM_CAT:
2596 if(Aura* dummy = m_target->GetDummyAura(37315) )
2597 m_target->CastSpell(m_target,37316,true,NULL,dummy);
2598 break;
2600 // Nordrassil Regalia - bonus
2601 case FORM_MOONKIN:
2603 if(Aura* dummy = m_target->GetDummyAura(37324) )
2604 m_target->CastSpell(m_target,37325,true,NULL,dummy);
2605 break;
2610 // adding/removing linked auras
2611 // add/remove the shapeshift aura's boosts
2612 HandleShapeshiftBoosts(apply);
2614 if(m_target->GetTypeId()==TYPEID_PLAYER)
2615 ((Player*)m_target)->InitDataForForm();
2618 void Aura::HandleAuraTransform(bool apply, bool Real)
2620 if (apply)
2622 // special case (spell specific functionality)
2623 if(m_modifier.m_miscvalue==0)
2625 // player applied only
2626 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2627 return;
2629 switch(GetId())
2631 // Orb of Deception
2632 case 16739:
2634 uint32 orb_model = m_target->GetNativeDisplayId();
2635 switch(orb_model)
2637 // Troll Female
2638 case 1479: m_target->SetDisplayId(10134); break;
2639 // Troll Male
2640 case 1478: m_target->SetDisplayId(10135); break;
2641 // Tauren Male
2642 case 59: m_target->SetDisplayId(10136); break;
2643 // Human Male
2644 case 49: m_target->SetDisplayId(10137); break;
2645 // Human Female
2646 case 50: m_target->SetDisplayId(10138); break;
2647 // Orc Male
2648 case 51: m_target->SetDisplayId(10139); break;
2649 // Orc Female
2650 case 52: m_target->SetDisplayId(10140); break;
2651 // Dwarf Male
2652 case 53: m_target->SetDisplayId(10141); break;
2653 // Dwarf Female
2654 case 54: m_target->SetDisplayId(10142); break;
2655 // NightElf Male
2656 case 55: m_target->SetDisplayId(10143); break;
2657 // NightElf Female
2658 case 56: m_target->SetDisplayId(10144); break;
2659 // Undead Female
2660 case 58: m_target->SetDisplayId(10145); break;
2661 // Undead Male
2662 case 57: m_target->SetDisplayId(10146); break;
2663 // Tauren Female
2664 case 60: m_target->SetDisplayId(10147); break;
2665 // Gnome Male
2666 case 1563: m_target->SetDisplayId(10148); break;
2667 // Gnome Female
2668 case 1564: m_target->SetDisplayId(10149); break;
2669 // BloodElf Female
2670 case 15475: m_target->SetDisplayId(17830); break;
2671 // BloodElf Male
2672 case 15476: m_target->SetDisplayId(17829); break;
2673 // Dranei Female
2674 case 16126: m_target->SetDisplayId(17828); break;
2675 // Dranei Male
2676 case 16125: m_target->SetDisplayId(17827); break;
2677 default: break;
2679 break;
2681 // Murloc costume
2682 case 42365: m_target->SetDisplayId(21723); break;
2683 default: break;
2686 else
2688 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2689 if(!ci)
2691 //pig pink ^_^
2692 m_target->SetDisplayId(16358);
2693 sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
2695 else
2697 // Will use the default model here
2698 m_target->SetDisplayId(ci->DisplayID_A);
2700 // Dragonmaw Illusion (set mount model also)
2701 if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
2702 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
2704 m_target->setTransForm(GetId());
2707 // polymorph case
2708 if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
2710 // for players, start regeneration after 1s (in polymorph fast regeneration case)
2711 // only if caster is Player (after patch 2.4.2)
2712 if(IS_PLAYER_GUID(GetCasterGUID()) )
2713 ((Player*)m_target)->setRegenTimer(1000);
2715 //dismount polymorphed target (after patch 2.4.2)
2716 if (m_target->IsMounted())
2717 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2720 else
2722 Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
2723 if(otherTransforms.empty())
2725 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2726 m_target->setTransForm(0);
2728 else
2730 // look for other transform auras
2731 Aura* handledAura = *otherTransforms.begin();
2732 for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
2734 // negative auras are preferred
2735 if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
2737 handledAura = *i;
2738 break;
2741 handledAura->ApplyModifier(true);
2744 // Dragonmaw Illusion (restore mount model)
2745 if(GetId()==42016 && m_target->GetMountID()==16314)
2747 if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
2749 uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
2750 if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
2752 uint32 team = 0;
2753 if (m_target->GetTypeId()==TYPEID_PLAYER)
2754 team = ((Player*)m_target)->GetTeam();
2756 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2757 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2758 if (minfo)
2759 display_id = minfo->modelid;
2761 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
2768 void Aura::HandleForceReaction(bool apply, bool Real)
2770 if(m_target->GetTypeId() != TYPEID_PLAYER)
2771 return;
2773 if(!Real)
2774 return;
2776 Player* player = (Player*)m_target;
2778 uint32 faction_id = m_modifier.m_miscvalue;
2779 uint32 faction_rank = m_modifier.m_amount;
2781 if(apply)
2782 player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
2783 else
2784 player->m_forcedReactions.erase(faction_id);
2786 WorldPacket data;
2787 data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
2788 data << uint32(player->m_forcedReactions.size());
2789 for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
2791 data << uint32(itr->first); // faction_id (Faction.dbc)
2792 data << uint32(itr->second); // reputation rank
2794 player->SendDirectMessage(&data);
2797 void Aura::HandleAuraModSkill(bool apply, bool Real)
2799 if(m_target->GetTypeId() != TYPEID_PLAYER)
2800 return;
2802 uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
2803 int32 points = GetModifier()->m_amount;
2805 ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
2806 if(prot == SKILL_DEFENSE)
2807 ((Player*)m_target)->UpdateDefenseBonusesMod();
2810 void Aura::HandleChannelDeathItem(bool apply, bool Real)
2812 if(Real && !apply)
2814 Unit* caster = GetCaster();
2815 Unit* victim = GetTarget();
2816 if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
2817 return;
2819 SpellEntry const *spellInfo = GetSpellProto();
2820 if(spellInfo->EffectItemType[m_effIndex] == 0)
2821 return;
2823 // Soul Shard only from non-grey units
2824 if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
2825 (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
2826 victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
2827 return;
2828 ItemPosCountVec dest;
2829 uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
2830 if( msg != EQUIP_ERR_OK )
2832 ((Player*)caster)->SendEquipError( msg, NULL, NULL );
2833 return;
2836 Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
2837 ((Player*)caster)->SendNewItem(newitem, 1, true, false);
2841 void Aura::HandleBindSight(bool apply, bool Real)
2843 Unit* caster = GetCaster();
2844 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2845 return;
2847 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2850 void Aura::HandleFarSight(bool apply, bool Real)
2852 Unit* caster = GetCaster();
2853 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2854 return;
2856 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2859 void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
2861 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2862 return;
2864 if(apply)
2865 m_target->RemoveNoStackAurasDueToAura(this);
2866 m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
2869 void Aura::HandleAuraTrackResources(bool apply, bool Real)
2871 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2872 return;
2874 if(apply)
2875 m_target->RemoveNoStackAurasDueToAura(this);
2876 m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
2879 void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
2881 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2882 return;
2884 if(apply)
2885 m_target->RemoveNoStackAurasDueToAura(this);
2887 m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
2890 void Aura::HandleAuraModScale(bool apply, bool Real)
2892 m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
2895 void Aura::HandleModPossess(bool apply, bool Real)
2897 if(!Real)
2898 return;
2900 if(m_target->getLevel() > m_modifier.m_amount)
2901 return;
2903 // not possess yourself
2904 if(GetCasterGUID() == m_target->GetGUID())
2905 return;
2907 Unit* caster = GetCaster();
2908 if(!caster)
2909 return;
2911 if( apply )
2913 m_target->SetCharmerGUID(GetCasterGUID());
2914 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
2915 caster->SetCharm(m_target);
2917 m_target->CombatStop();
2918 m_target->DeleteThreatList();
2919 if(m_target->GetTypeId() == TYPEID_UNIT)
2921 m_target->StopMoving();
2922 m_target->GetMotionMaster()->Clear();
2923 m_target->GetMotionMaster()->MoveIdle();
2924 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
2925 charmInfo->InitPossessCreateSpells();
2928 if(caster->GetTypeId() == TYPEID_PLAYER)
2930 ((Player*)caster)->PossessSpellInitialize();
2933 else
2935 m_target->SetCharmerGUID(0);
2937 if(m_target->GetTypeId() == TYPEID_PLAYER)
2938 ((Player*)m_target)->setFactionForRace(m_target->getRace());
2939 else if(m_target->GetTypeId() == TYPEID_UNIT)
2941 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
2942 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
2945 caster->SetCharm(0);
2947 if(caster->GetTypeId() == TYPEID_PLAYER)
2949 WorldPacket data(SMSG_PET_SPELLS, 8);
2950 data << uint64(0);
2951 ((Player*)caster)->GetSession()->SendPacket(&data);
2953 if(m_target->GetTypeId() == TYPEID_UNIT)
2955 ((Creature*)m_target)->AIM_Initialize();
2957 if (((Creature*)m_target)->AI())
2958 ((Creature*)m_target)->AI()->AttackStart(caster);
2961 if(caster->GetTypeId() == TYPEID_PLAYER)
2962 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2965 void Aura::HandleModPossessPet(bool apply, bool Real)
2967 if(!Real)
2968 return;
2970 Unit* caster = GetCaster();
2971 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2972 return;
2973 if(caster->GetPet() != m_target)
2974 return;
2976 if(apply)
2978 caster->SetUInt64Value(PLAYER_FARSIGHT, m_target->GetGUID());
2979 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2981 else
2983 caster->SetUInt64Value(PLAYER_FARSIGHT, 0);
2984 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2988 void Aura::HandleModCharm(bool apply, bool Real)
2990 if(!Real)
2991 return;
2993 // not charm yourself
2994 if(GetCasterGUID() == m_target->GetGUID())
2995 return;
2997 Unit* caster = GetCaster();
2998 if(!caster)
2999 return;
3001 if(int32(m_target->getLevel()) <= m_modifier.m_amount)
3003 if( apply )
3005 m_target->SetCharmerGUID(GetCasterGUID());
3006 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
3007 m_target->CastStop(m_target==caster ? GetId() : 0);
3008 caster->SetCharm(m_target);
3010 m_target->CombatStop();
3011 m_target->DeleteThreatList();
3013 if(m_target->GetTypeId() == TYPEID_UNIT)
3015 ((Creature*)m_target)->AIM_Initialize();
3016 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3017 charmInfo->InitCharmCreateSpells();
3018 charmInfo->SetReactState( REACT_DEFENSIVE );
3020 if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
3022 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3023 if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
3025 //to prevent client crash
3026 m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
3027 //just to enable stat window
3028 charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
3029 //if charmed two demons the same session, the 2nd gets the 1st one's name
3030 m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
3035 if(caster->GetTypeId() == TYPEID_PLAYER)
3037 ((Player*)caster)->CharmSpellInitialize();
3040 else
3042 m_target->SetCharmerGUID(0);
3044 if(m_target->GetTypeId() == TYPEID_PLAYER)
3045 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3046 else
3048 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3050 // restore faction
3051 if(((Creature*)m_target)->isPet())
3053 if(Unit* owner = m_target->GetOwner())
3054 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
3055 else if(cinfo)
3056 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3058 else if(cinfo) // normal creature
3059 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3061 // restore UNIT_FIELD_BYTES_0
3062 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
3064 CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
3065 if(cainfo && cainfo->bytes0 != 0)
3066 m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
3067 else
3068 m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
3070 if(m_target->GetCharmInfo())
3071 m_target->GetCharmInfo()->SetPetNumber(0, true);
3072 else
3073 sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
3077 caster->SetCharm(0);
3079 if(caster->GetTypeId() == TYPEID_PLAYER)
3081 WorldPacket data(SMSG_PET_SPELLS, 8);
3082 data << uint64(0);
3083 ((Player*)caster)->GetSession()->SendPacket(&data);
3085 if(m_target->GetTypeId() == TYPEID_UNIT)
3087 ((Creature*)m_target)->AIM_Initialize();
3088 if (((Creature*)m_target)->AI())
3089 ((Creature*)m_target)->AI()->AttackStart(caster);
3095 void Aura::HandleModConfuse(bool apply, bool Real)
3097 if(!Real)
3098 return;
3100 m_target->SetConfused(apply, GetCasterGUID(), GetId());
3103 void Aura::HandleModFear(bool apply, bool Real)
3105 if (!Real)
3106 return;
3108 m_target->SetFeared(apply, GetCasterGUID(), GetId());
3111 void Aura::HandleFeignDeath(bool apply, bool Real)
3113 if(!Real)
3114 return;
3116 if(m_target->GetTypeId() != TYPEID_PLAYER)
3117 return;
3119 if( apply )
3122 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3123 data<<m_target->GetGUID();
3124 data<<uint8(0);
3125 m_target->SendMessageToSet(&data,true);
3127 // blizz like 2.0.x
3128 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3129 // blizz like 2.0.x
3130 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3131 // blizz like 2.0.x
3132 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3134 m_target->addUnitState(UNIT_STAT_DIED);
3135 m_target->CombatStop();
3137 // prevent interrupt message
3138 if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
3139 m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
3140 m_target->InterruptNonMeleeSpells(true);
3141 m_target->getHostilRefManager().deleteReferences();
3143 else
3146 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3147 data<<m_target->GetGUID();
3148 data<<uint8(1);
3149 m_target->SendMessageToSet(&data,true);
3151 // blizz like 2.0.x
3152 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3153 // blizz like 2.0.x
3154 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3155 // blizz like 2.0.x
3156 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3158 m_target->clearUnitState(UNIT_STAT_DIED);
3162 void Aura::HandleAuraModDisarm(bool apply, bool Real)
3164 if(!Real)
3165 return;
3167 if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
3168 return;
3170 // not sure for it's correctness
3171 if(apply)
3172 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3173 else
3174 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3176 // only at real add/remove aura
3177 if (m_target->GetTypeId() != TYPEID_PLAYER)
3178 return;
3180 // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
3181 if (((Player *)m_target)->IsInFeralForm())
3182 return;
3184 if (apply)
3185 m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
3186 else
3187 ((Player *)m_target)->SetRegularAttackTime();
3189 m_target->UpdateDamagePhysical(BASE_ATTACK);
3192 void Aura::HandleAuraModStun(bool apply, bool Real)
3194 if(!Real)
3195 return;
3197 if (apply)
3199 m_target->addUnitState(UNIT_STAT_STUNNED);
3200 m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
3202 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
3203 m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
3205 // Creature specific
3206 if(m_target->GetTypeId() != TYPEID_PLAYER)
3207 ((Creature*)m_target)->StopMoving();
3208 else
3209 m_target->SetUnitMovementFlags(0); //Clear movement flags
3211 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
3213 data.append(m_target->GetPackGUID());
3214 data << uint32(0);
3215 m_target->SendMessageToSet(&data,true);
3217 else
3219 // Real remove called after current aura remove from lists, check if other similar auras active
3220 if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
3221 return;
3223 m_target->clearUnitState(UNIT_STAT_STUNNED);
3224 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
3226 if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
3228 if(m_target->getVictim() && m_target->isAlive())
3229 m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3231 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
3232 data.append(m_target->GetPackGUID());
3233 data << uint32(0);
3234 m_target->SendMessageToSet(&data,true);
3237 // Wyvern Sting
3238 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
3240 Unit* caster = GetCaster();
3241 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
3242 return;
3244 uint32 spell_id = 0;
3246 switch(GetId())
3248 case 19386: spell_id = 24131; break;
3249 case 24132: spell_id = 24134; break;
3250 case 24133: spell_id = 24135; break;
3251 case 27068: spell_id = 27069; break;
3252 default:
3253 sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
3254 return;
3257 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
3259 if(!spellInfo)
3260 return;
3262 caster->CastSpell(m_target,spellInfo,true,NULL,this);
3263 return;
3268 void Aura::HandleModStealth(bool apply, bool Real)
3270 if(apply)
3272 // drop flag at stealth in bg
3273 if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
3274 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3275 bg->EventPlayerDroppedFlag((Player*)m_target);
3277 // only at real aura add
3278 if(Real)
3280 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
3281 if(m_target->GetTypeId()==TYPEID_PLAYER)
3282 m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
3284 // apply only if not in GM invisibility (and overwrite invisibility state)
3285 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3287 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3288 m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
3291 // for RACE_NIGHTELF stealth
3292 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3293 m_target->CastSpell(m_target, 21009, true, NULL, this);
3296 else
3298 // only at real aura remove
3299 if(Real)
3301 // for RACE_NIGHTELF stealth
3302 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3303 m_target->RemoveAurasDueToSpell(21009);
3305 // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
3306 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
3308 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
3309 if(m_target->GetTypeId()==TYPEID_PLAYER)
3310 m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
3312 // restore invisibility if any
3313 if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
3315 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3316 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3318 else
3319 m_target->SetVisibility(VISIBILITY_ON);
3324 // Master of Subtlety
3325 Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
3326 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
3328 if ((*i)->GetSpellProto()->SpellIconID == 2114)
3330 if (apply)
3332 int32 bp = (*i)->GetModifier()->m_amount;
3333 m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
3335 else
3336 m_target->CastSpell(m_target,31666,true);
3337 break;
3342 void Aura::HandleInvisibility(bool apply, bool Real)
3344 if(apply)
3346 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3348 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3350 // apply glow vision
3351 m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3353 // drop flag at invisible in bg
3354 if(((Player*)m_target)->InBattleGround())
3355 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3356 bg->EventPlayerDroppedFlag((Player*)m_target);
3359 // apply only if not in GM invisibility and not stealth
3360 if(m_target->GetVisibility()==VISIBILITY_ON)
3362 // Aura not added yet but visibility code expect temporary add aura
3363 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3364 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3367 else
3369 // recalculate value at modifier remove (current aura already removed)
3370 m_target->m_invisibilityMask = 0;
3371 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
3372 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3373 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3375 // only at real aura remove and if not have different invisibility auras.
3376 if(Real && m_target->m_invisibilityMask==0)
3378 // remove glow vision
3379 if(m_target->GetTypeId() == TYPEID_PLAYER)
3380 m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3382 // apply only if not in GM invisibility & not stealthed while invisible
3383 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3385 // if have stealth aura then already have stealth visibility
3386 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
3387 m_target->SetVisibility(VISIBILITY_ON);
3393 void Aura::HandleInvisibilityDetect(bool apply, bool Real)
3395 if(apply)
3397 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3399 else
3401 // recalculate value at modifier remove (current aura already removed)
3402 m_target->m_detectInvisibilityMask = 0;
3403 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
3404 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3405 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3407 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3408 ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
3411 void Aura::HandleAuraModRoot(bool apply, bool Real)
3413 // only at real add/remove aura
3414 if(!Real)
3415 return;
3417 uint32 apply_stat = UNIT_STAT_ROOT;
3418 if (apply)
3420 m_target->addUnitState(UNIT_STAT_ROOT);
3421 m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
3422 // probably wrong
3423 m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3425 //Save last orientation
3426 if( m_target->getVictim() )
3427 m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
3429 if(m_target->GetTypeId() == TYPEID_PLAYER)
3431 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
3432 data.append(m_target->GetPackGUID());
3433 data << (uint32)2;
3434 m_target->SendMessageToSet(&data,true);
3436 //Clear unit movement flags
3437 m_target->SetUnitMovementFlags(0);
3439 else
3440 ((Creature *)m_target)->StopMoving();
3442 else
3444 // Real remove called after current aura remove from lists, check if other similar auras active
3445 if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
3446 return;
3448 m_target->clearUnitState(UNIT_STAT_ROOT);
3449 // probably wrong
3450 m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3452 if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
3454 if(m_target->getVictim() && m_target->isAlive())
3455 m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3457 if(m_target->GetTypeId() == TYPEID_PLAYER)
3459 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
3460 data.append(m_target->GetPackGUID());
3461 data << (uint32)2;
3462 m_target->SendMessageToSet(&data,true);
3468 void Aura::HandleAuraModSilence(bool apply, bool Real)
3470 // only at real add/remove aura
3471 if(!Real)
3472 return;
3474 if(apply)
3476 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3477 // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3478 for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
3480 Spell* currentSpell = m_target->m_currentSpells[i];
3481 if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
3483 uint32 state = currentSpell->getState();
3484 // Stop spells on prepare or casting state
3485 if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
3487 currentSpell->cancel();
3488 currentSpell->SetReferencedFromCurrent(false);
3489 m_target->m_currentSpells[i] = NULL;
3494 switch (GetId())
3496 // Arcane Torrent (Energy)
3497 case 25046:
3499 Unit * caster = GetCaster();
3500 if (!caster)
3501 return;
3503 // Search Mana Tap auras on caster
3504 int32 energy = 0;
3505 Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
3506 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3507 if ((*i)->GetId() == 28734)
3508 ++energy;
3509 if (energy)
3511 energy *= 10;
3512 caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true);
3513 caster->RemoveAurasDueToSpell(28734);
3518 else
3520 // Real remove called after current aura remove from lists, check if other similar auras active
3521 if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
3522 return;
3524 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3528 void Aura::HandleModThreat(bool apply, bool Real)
3530 // only at real add/remove aura
3531 if(!Real)
3532 return;
3534 if(!m_target->isAlive())
3535 return;
3537 Unit* caster = GetCaster();
3539 if(!caster || !caster->isAlive())
3540 return;
3542 int level_diff = 0;
3543 int multiplier = 0;
3544 switch (GetId())
3546 // Arcane Shroud
3547 case 26400:
3548 level_diff = m_target->getLevel() - 60;
3549 multiplier = 2;
3550 break;
3551 // The Eye of Diminution
3552 case 28862:
3553 level_diff = m_target->getLevel() - 60;
3554 multiplier = 1;
3555 break;
3557 if (level_diff > 0)
3558 m_modifier.m_amount += multiplier * level_diff;
3560 for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
3562 if(m_modifier.m_miscvalue & int32(1<<x))
3564 if(m_target->GetTypeId() == TYPEID_PLAYER)
3565 ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
3570 void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
3572 // only at real add/remove aura
3573 if(!Real)
3574 return;
3576 if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
3577 return;
3579 Unit* caster = GetCaster();
3581 if(!caster || !caster->isAlive())
3582 return;
3584 float threatMod = 0.0f;
3585 if(apply)
3586 threatMod = float(m_modifier.m_amount);
3587 else
3588 threatMod = float(-m_modifier.m_amount);
3590 m_target->getHostilRefManager().threatAssist(caster, threatMod);
3593 void Aura::HandleModTaunt(bool apply, bool Real)
3595 // only at real add/remove aura
3596 if(!Real)
3597 return;
3599 if(!m_target->isAlive() || !m_target->CanHaveThreatList())
3600 return;
3602 Unit* caster = GetCaster();
3604 if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
3605 return;
3607 if(apply)
3608 m_target->TauntApply(caster);
3609 else
3611 // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
3612 m_target->TauntFadeOut(caster);
3616 /*********************************************************/
3617 /*** MODIFY SPEED ***/
3618 /*********************************************************/
3619 void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real)
3621 // all applied/removed only at real aura add/remove
3622 if(!Real)
3623 return;
3625 m_target->UpdateSpeed(MOVE_RUN, true);
3628 void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real)
3630 // all applied/removed only at real aura add/remove
3631 if(!Real)
3632 return;
3634 m_target->UpdateSpeed(MOVE_RUN, true);
3637 void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
3639 // all applied/removed only at real aura add/remove
3640 if(!Real)
3641 return;
3643 // Enable Fly mode for flying mounts
3644 if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
3646 WorldPacket data;
3647 if(apply)
3648 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
3649 else
3650 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
3651 data.append(m_target->GetPackGUID());
3652 data << uint32(0); // unknown
3653 m_target->SendMessageToSet(&data, true);
3655 //Players on flying mounts must be immune to polymorph
3656 if (m_target->GetTypeId()==TYPEID_PLAYER)
3657 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
3659 // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
3660 if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
3661 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
3664 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3667 void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
3669 // all applied/removed only at real aura add/remove
3670 if(!Real)
3671 return;
3673 m_target->UpdateSpeed(MOVE_SWIM, true);
3676 void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
3678 // all applied/removed only at real aura add/remove
3679 if(!Real)
3680 return;
3682 m_target->UpdateSpeed(MOVE_RUN, true);
3683 m_target->UpdateSpeed(MOVE_SWIM, true);
3684 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3687 void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
3689 // all applied/removed only at real aura add/remove
3690 if(!Real)
3691 return;
3693 m_target->UpdateSpeed(MOVE_RUN, true);
3694 m_target->UpdateSpeed(MOVE_SWIM, true);
3695 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3698 /*********************************************************/
3699 /*** IMMUNITY ***/
3700 /*********************************************************/
3702 void Aura::HandleModMechanicImmunity(bool apply, bool Real)
3704 uint32 mechanic = 1 << m_modifier.m_miscvalue;
3706 //immune movement impairment and loss of control
3707 if(GetId()==42292)
3708 mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
3710 if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3712 Unit::AuraMap& Auras = m_target->GetAuras();
3713 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3715 next = iter;
3716 ++next;
3717 SpellEntry const *spell = iter->second->GetSpellProto();
3718 if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
3719 && !iter->second->IsPositive() // only remove negative spells
3720 && spell->Id != GetId())
3722 //check for mechanic mask
3723 if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
3725 m_target->RemoveAurasDueToSpell(spell->Id);
3726 if(Auras.empty())
3727 break;
3728 else
3729 next = Auras.begin();
3735 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
3737 // special cases
3738 switch(m_modifier.m_miscvalue)
3740 case MECHANIC_INVULNERABILITY:
3741 m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply);
3742 break;
3743 case MECHANIC_SHIELD:
3744 m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply);
3745 break;
3748 // Bestial Wrath
3749 if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
3751 // The Beast Within cast on owner if talent present
3752 if ( Unit* owner = m_target->GetOwner() )
3754 // Search talent
3755 Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
3756 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3758 if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
3760 if (apply)
3761 owner->CastSpell(owner, 34471, true, 0, this);
3762 else
3763 owner->RemoveAurasDueToSpell(34471);
3764 break;
3770 // The Beast Within and Bestial Wrath - immunity
3771 if(GetId() == 19574 || GetId() == 34471)
3773 if(apply)
3775 m_target->CastSpell(m_target,24395,true);
3776 m_target->CastSpell(m_target,24396,true);
3777 m_target->CastSpell(m_target,24397,true);
3778 m_target->CastSpell(m_target,26592,true);
3780 else
3782 m_target->RemoveAurasDueToSpell(24395);
3783 m_target->RemoveAurasDueToSpell(24396);
3784 m_target->RemoveAurasDueToSpell(24397);
3785 m_target->RemoveAurasDueToSpell(26592);
3790 void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
3792 if(!apply)
3794 if(m_target->GetTypeId() == TYPEID_PLAYER)
3796 if(((Player*)m_target)->InBattleGround())
3798 BattleGround *bg = ((Player*)m_target)->GetBattleGround();
3799 if(bg)
3801 switch(bg->GetTypeID())
3803 case BATTLEGROUND_AV:
3805 break;
3807 case BATTLEGROUND_WS:
3809 // Warsong Flag, horde // Silverwing Flag, alliance
3810 if(GetId() == 23333 || GetId() == 23335)
3811 bg->EventPlayerDroppedFlag(((Player*)m_target));
3812 break;
3814 case BATTLEGROUND_AB:
3816 break;
3818 case BATTLEGROUND_EY:
3820 if(GetId() == 34976)
3821 bg->EventPlayerDroppedFlag(((Player*)m_target));
3822 break;
3830 m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
3833 void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
3835 if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3837 Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
3838 for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
3840 if (auraList.front() != this) // skip itself aura (it already added)
3842 m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
3843 itr = auraList.begin();
3845 else
3846 ++itr;
3850 m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
3853 void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
3855 m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
3857 if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3859 if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
3861 uint32 school_mask = m_modifier.m_miscvalue;
3862 Unit::AuraMap& Auras = m_target->GetAuras();
3863 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3865 next = iter;
3866 ++next;
3867 SpellEntry const *spell = iter->second->GetSpellProto();
3868 if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
3869 && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
3870 && !iter->second->IsPositive() //Don't remove positive spells
3871 && spell->Id != GetId() ) //Don't remove self
3873 m_target->RemoveAurasDueToSpell(spell->Id);
3874 if(Auras.empty())
3875 break;
3876 else
3877 next = Auras.begin();
3882 if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
3884 if( apply )
3885 m_target->addUnitState(UNIT_STAT_ISOLATED);
3886 else
3887 m_target->clearUnitState(UNIT_STAT_ISOLATED);
3891 void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
3893 m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
3896 void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
3898 // all applied/removed only at real aura add/remove
3899 if(!Real)
3900 return;
3902 m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
3905 void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
3907 if(!Real)
3908 return;
3910 if(apply)
3912 // some spell have charges by functionality not have its in spell data
3913 switch (GetId())
3915 case 28200: // Ascendance (Talisman of Ascendance trinket)
3916 m_procCharges = 6;
3917 UpdateAuraCharges();
3918 break;
3919 default: break;
3924 void Aura::HandleAuraModStalked(bool apply, bool Real)
3926 // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
3927 if(apply)
3928 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3929 else
3930 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3933 /*********************************************************/
3934 /*** PERIODIC ***/
3935 /*********************************************************/
3937 void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
3939 if (m_periodicTimer <= 0)
3940 m_periodicTimer += m_modifier.periodictime;
3942 m_isPeriodic = apply;
3943 m_isTrigger = apply;
3945 // Curse of the Plaguebringer
3946 if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL)
3948 // Cast Wrath of the Plaguebringer if not dispelled
3949 m_target->CastSpell(m_target, 29214, true, 0, this);
3953 void Aura::HandlePeriodicEnergize(bool apply, bool Real)
3955 if (m_periodicTimer <= 0)
3956 m_periodicTimer += m_modifier.periodictime;
3958 m_isPeriodic = apply;
3961 void Aura::HandlePeriodicHeal(bool apply, bool Real)
3963 if (m_periodicTimer <= 0)
3964 m_periodicTimer += m_modifier.periodictime;
3966 m_isPeriodic = apply;
3968 // only at real apply
3969 if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE)
3971 // provided m_target as original caster to prevent apply aura caster selection for this negative buff
3972 m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID());
3975 // For prevent double apply bonuses
3976 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
3978 if(!loading && apply)
3980 switch (m_spellProto->SpellFamilyName)
3982 case SPELLFAMILY_DRUID:
3984 // Rejuvenation
3985 if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
3987 if(Unit* caster = GetCaster())
3989 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
3990 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
3992 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
3993 switch((*k)->GetModifier()->m_miscvalue)
3995 case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
3996 case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
3998 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
3999 break;
4010 void Aura::HandlePeriodicDamage(bool apply, bool Real)
4012 // spells required only Real aura add/remove
4013 if(!Real)
4014 return;
4016 if (m_periodicTimer <= 0)
4017 m_periodicTimer += m_modifier.periodictime;
4019 m_isPeriodic = apply;
4021 // For prevent double apply bonuses
4022 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4024 Unit *caster = GetCaster();
4026 switch (m_spellProto->SpellFamilyName)
4028 case SPELLFAMILY_GENERIC:
4030 // Pounce Bleed
4031 if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 )
4033 // $AP*0.18/6 bonus per tick
4034 if (apply && !loading && caster)
4035 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4036 return;
4038 break;
4040 case SPELLFAMILY_WARRIOR:
4042 // Rend
4043 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4045 // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
4046 if (apply && !loading && caster)
4048 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4049 int32 mws = caster->GetAttackTime(BASE_ATTACK);
4050 float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
4051 float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
4052 // WARNING! in 3.0 multiplier 0.00743f change to 0.6
4053 m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
4055 return;
4057 break;
4059 case SPELLFAMILY_DRUID:
4061 // Rake
4062 if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
4064 // $AP*0.06/3 bonus per tick
4065 if (apply && !loading && caster)
4066 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
4067 return;
4069 // Lacerate
4070 if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
4072 // $AP*0.05/5 bonus per tick
4073 if (apply && !loading && caster)
4074 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
4075 return;
4077 // Rip
4078 if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
4080 // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used]
4081 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4083 uint8 cp = ((Player*)caster)->GetComboPoints();
4085 // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
4086 Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
4087 for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
4089 if((*itr)->GetId()==34241)
4091 m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
4092 break;
4096 if (cp > 4) cp = 4;
4097 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4099 return;
4101 break;
4103 case SPELLFAMILY_ROGUE:
4105 // Deadly poison aura state
4106 if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100)
4108 if(apply)
4109 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
4110 else
4112 // current aura already removed, search present of another
4113 bool found = false;
4114 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
4115 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
4117 SpellEntry const* itr_spell = (*itr)->GetSpellProto();
4118 if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100)
4120 found = true;
4121 break;
4124 // this has been last deadly poison aura
4125 if(!found)
4126 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
4128 return;
4130 // Rupture
4131 if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
4133 // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP]
4134 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4136 uint8 cp = ((Player*)caster)->GetComboPoints();
4137 if (cp > 3) cp = 3;
4138 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4140 return;
4142 // Garrote
4143 if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
4145 // $AP*0.18/6 bonus per tick
4146 if (apply && !loading && caster)
4147 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4148 return;
4150 break;
4152 case SPELLFAMILY_HUNTER:
4154 // Serpent Sting
4155 if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
4157 // $RAP*0.1/5 bonus per tick
4158 if (apply && !loading && caster)
4159 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4160 return;
4162 // Immolation Trap
4163 if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
4165 // $RAP*0.1/5 bonus per tick
4166 if (apply && !loading && caster)
4167 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4168 return;
4170 break;
4172 case SPELLFAMILY_PALADIN:
4174 // Consecration
4175 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4177 if (apply && !loading)
4179 if(Unit* caster = GetCaster())
4181 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4182 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4184 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4185 switch((*k)->GetModifier()->m_miscvalue)
4187 case 5147: // Improved Consecration - Libram of the Eternal Rest
4189 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4190 break;
4196 return;
4198 break;
4200 default:
4201 break;
4205 void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
4207 if (m_periodicTimer <= 0)
4208 m_periodicTimer += m_modifier.periodictime;
4210 m_isPeriodic = apply;
4213 void Aura::HandlePeriodicLeech(bool apply, bool Real)
4215 if (m_periodicTimer <= 0)
4216 m_periodicTimer += m_modifier.periodictime;
4218 m_isPeriodic = apply;
4221 void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
4223 if (m_periodicTimer <= 0)
4224 m_periodicTimer += m_modifier.periodictime;
4226 m_isPeriodic = apply;
4229 /*********************************************************/
4230 /*** MODIFY STATS ***/
4231 /*********************************************************/
4233 /********************************/
4234 /*** RESISTANCE ***/
4235 /********************************/
4237 void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
4239 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4241 if(m_modifier.m_miscvalue & int32(1<<x))
4243 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
4244 if(m_target->GetTypeId() == TYPEID_PLAYER)
4245 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4250 void Aura::HandleAuraModResistance(bool apply, bool Real)
4252 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4254 if(m_modifier.m_miscvalue & int32(1<<x))
4256 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4257 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4258 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4262 // Faerie Fire (druid versions)
4263 if( m_spellProto->SpellIconID == 109 &&
4264 m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
4265 m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
4267 m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
4271 void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
4273 // only players have base stats
4274 if(m_target->GetTypeId() != TYPEID_PLAYER)
4276 //pets only have base armor
4277 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4278 m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
4280 else
4282 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4284 if(m_modifier.m_miscvalue & int32(1<<x))
4285 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
4290 void Aura::HandleModResistancePercent(bool apply, bool Real)
4292 for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4294 if(m_modifier.m_miscvalue & int32(1<<i))
4296 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4297 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4299 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
4300 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
4306 void Aura::HandleModBaseResistance(bool apply, bool Real)
4308 // only players have base stats
4309 if(m_target->GetTypeId() != TYPEID_PLAYER)
4311 //only pets have base stats
4312 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4313 m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4315 else
4317 for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4318 if(m_modifier.m_miscvalue & (1<<i))
4319 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4323 /********************************/
4324 /*** STAT ***/
4325 /********************************/
4327 void Aura::HandleAuraModStat(bool apply, bool Real)
4329 if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
4331 sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
4332 return;
4335 for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4337 // -1 or -2 is all stats ( misc < -2 checked in function beginning )
4338 if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
4340 //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
4341 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4342 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4343 m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
4348 void Aura::HandleModPercentStat(bool apply, bool Real)
4350 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4352 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4353 return;
4356 // only players have base stats
4357 if (m_target->GetTypeId() != TYPEID_PLAYER)
4358 return;
4360 for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
4362 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4363 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
4367 void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real)
4369 if(m_target->GetTypeId() != TYPEID_PLAYER)
4370 return;
4372 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4373 // This information for client side use only
4374 // Recalculate bonus
4375 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4378 void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real)
4380 if(m_target->GetTypeId() != TYPEID_PLAYER)
4381 return;
4383 // Recalculate bonus
4384 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4387 void Aura::HandleAuraModDispelResist(bool apply, bool Real)
4389 if(!Real || !apply)
4390 return;
4392 if(GetId()==33206)
4393 m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
4396 void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real)
4398 if(m_target->GetTypeId() != TYPEID_PLAYER)
4399 return;
4401 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4402 // This information for client side use only
4403 // Recalculate bonus
4404 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4407 void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real)
4409 if(m_target->GetTypeId() != TYPEID_PLAYER)
4410 return;
4412 // Recalculate bonus
4413 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4416 void Aura::HandleModHealingDone(bool /*apply*/, bool Real)
4418 if(m_target->GetTypeId() != TYPEID_PLAYER)
4419 return;
4420 // implemented in Unit::SpellHealingBonus
4421 // this information is for client side only
4422 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4425 void Aura::HandleModTotalPercentStat(bool apply, bool Real)
4427 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4429 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4430 return;
4433 //save current and max HP before applying aura
4434 uint32 curHPValue = m_target->GetHealth();
4435 uint32 maxHPValue = m_target->GetMaxHealth();
4437 for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4439 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4441 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4442 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4443 m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
4447 //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
4448 if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
4450 // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
4451 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
4452 m_target->SetHealth(newHPValue);
4456 void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
4458 if(m_target->GetTypeId() != TYPEID_PLAYER)
4459 return;
4461 if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
4463 // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
4464 // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
4465 sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
4466 return;
4469 // Recalculate Armor
4470 m_target->UpdateArmor();
4473 /********************************/
4474 /*** HEAL & ENERGIZE ***/
4475 /********************************/
4476 void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
4479 Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
4480 so this aura not fully working.
4482 if(apply)
4484 if(!m_target->isAlive())
4485 return;
4487 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4488 m_target->SetStandState(PLAYER_STATE_SIT);
4490 if(m_periodicTimer <= 0)
4492 m_periodicTimer += m_modifier.periodictime;
4494 if(m_target->GetHealth() < m_target->GetMaxHealth())
4496 // PeriodicTick can cast triggered spells with stats changes
4497 PeriodicTick();
4502 m_isPeriodic = apply;
4505 void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
4507 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4508 m_target->SetStandState(PLAYER_STATE_SIT);
4509 if(apply)
4511 if(m_modifier.periodictime == 0)
4512 m_modifier.periodictime = 1000;
4513 if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
4515 m_periodicTimer += m_modifier.periodictime;
4517 if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
4519 // PeriodicTick can cast triggered spells with stats changes
4520 PeriodicTick();
4525 m_isPeriodic = apply;
4528 void Aura::HandleModRegen(bool apply, bool Real) // eating
4530 if(apply)
4532 if(!m_target->isAlive())
4533 return;
4535 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4536 m_target->SetStandState(PLAYER_STATE_SIT);
4538 if(m_periodicTimer <= 0)
4540 m_periodicTimer += 5000;
4541 int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
4542 Unit *caster = GetCaster();
4543 if (caster)
4545 SpellEntry const *spellProto = GetSpellProto();
4546 if (spellProto)
4547 m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
4552 m_isPeriodic = apply;
4555 void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
4557 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4558 m_target->SetStandState(PLAYER_STATE_SIT);
4560 if(apply && m_periodicTimer <= 0)
4562 m_periodicTimer += 2000;
4564 Powers pt = m_target->getPowerType();
4565 if(int32(pt) != m_modifier.m_miscvalue)
4566 return;
4568 if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
4570 // eating anim
4571 m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
4573 else if( GetId() == 20577 )
4575 // cannibalize anim
4576 m_target->HandleEmoteCommand(398);
4579 // Warrior talent, gain 1 rage every 3 seconds while in combat
4580 if(pt == POWER_RAGE && m_target->isInCombat())
4582 m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
4583 m_periodicTimer += 1000;
4586 m_isPeriodic = apply;
4587 if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
4588 ((Player*)m_target)->UpdateManaRegen();
4591 void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
4593 // spells required only Real aura add/remove
4594 if(!Real)
4595 return;
4597 if (m_target->GetTypeId() != TYPEID_PLAYER)
4598 return;
4600 // Update manaregen value
4601 if (m_modifier.m_miscvalue == POWER_MANA)
4602 ((Player*)m_target)->UpdateManaRegen();
4605 void Aura::HandleModManaRegen(bool /*apply*/, bool Real)
4607 // spells required only Real aura add/remove
4608 if(!Real)
4609 return;
4611 if (m_target->GetTypeId() != TYPEID_PLAYER)
4612 return;
4614 //Note: an increase in regen does NOT cause threat.
4615 ((Player*)m_target)->UpdateManaRegen();
4618 void Aura::HandleComprehendLanguage(bool apply, bool Real)
4620 if(apply)
4621 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4622 else
4623 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4626 void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
4628 // Special case with temporary increase max/current health
4629 switch(GetId())
4631 case 12976: // Warrior Last Stand triggered spell
4632 case 28726: // Nightmare Seed ( Nightmare Seed )
4633 case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
4634 case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
4636 if(Real)
4638 if(apply)
4640 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4641 m_target->ModifyHealth(m_modifier.m_amount);
4643 else
4645 if (int32(m_target->GetHealth()) > m_modifier.m_amount)
4646 m_target->ModifyHealth(-m_modifier.m_amount);
4647 else
4648 m_target->SetHealth(1);
4649 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4652 return;
4656 // generic case
4657 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4660 void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
4662 uint32 oldhealth = m_target->GetHealth();
4663 double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
4665 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4667 // refresh percentage
4668 if(oldhealth > 0)
4670 uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
4671 if(newhealth==0)
4672 newhealth = 1;
4674 m_target->SetHealth(newhealth);
4678 void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
4680 Powers powerType = m_target->getPowerType();
4681 if(int32(powerType) != m_modifier.m_miscvalue)
4682 return;
4684 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4686 m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4689 void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/)
4691 Powers powerType = m_target->getPowerType();
4692 if(int32(powerType) != m_modifier.m_miscvalue)
4693 return;
4695 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4697 m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply);
4700 void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/)
4702 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
4705 /********************************/
4706 /*** FIGHT ***/
4707 /********************************/
4709 void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real)
4711 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4712 return;
4714 ((Player*)m_target)->UpdateParryPercentage();
4717 void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real)
4719 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4720 return;
4722 ((Player*)m_target)->UpdateDodgePercentage();
4723 //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
4726 void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real)
4728 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4729 return;
4731 ((Player*)m_target)->UpdateBlockPercentage();
4732 //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
4735 void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real)
4737 // spells required only Real aura add/remove
4738 if(!Real)
4739 return;
4741 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4742 return;
4744 ((Player*)m_target)->UpdateManaRegen();
4747 void Aura::HandleAuraModCritPercent(bool apply, bool Real)
4749 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4750 return;
4752 // apply item specific bonuses for already equipped weapon
4753 if(Real)
4755 for(int i = 0; i < MAX_ATTACK; ++i)
4756 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4757 ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
4760 // mods must be applied base at equipped weapon class and subclass comparison
4761 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4762 // m_modifier.m_miscvalue comparison with item generated damage types
4764 if (GetSpellProto()->EquippedItemClass == -1)
4766 ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4767 ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4768 ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4770 else
4772 // done in Player::_ApplyWeaponDependentAuraMods
4776 void Aura::HandleModHitChance(bool apply, bool Real)
4778 m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4779 m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4782 void Aura::HandleModSpellHitChance(bool apply, bool Real)
4784 m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
4787 void Aura::HandleModSpellCritChance(bool apply, bool Real)
4789 // spells required only Real aura add/remove
4790 if(!Real)
4791 return;
4793 if(m_target->GetTypeId() == TYPEID_PLAYER)
4795 ((Player*)m_target)->UpdateAllSpellCritChances();
4797 else
4799 m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
4803 void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
4805 // spells required only Real aura add/remove
4806 if(!Real)
4807 return;
4809 if(m_target->GetTypeId() != TYPEID_PLAYER)
4810 return;
4812 for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
4813 if (m_modifier.m_miscvalue & (1<<school))
4814 ((Player*)m_target)->UpdateSpellCritChance(school);
4817 /********************************/
4818 /*** ATTACK SPEED ***/
4819 /********************************/
4821 void Aura::HandleModCastingSpeed(bool apply, bool Real)
4823 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4826 void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
4828 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4829 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4830 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4833 void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
4835 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4836 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4837 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4838 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4841 void Aura::HandleModAttackSpeed(bool apply, bool Real)
4843 if(!m_target->isAlive() )
4844 return;
4846 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4849 void Aura::HandleHaste(bool apply, bool Real)
4851 m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
4852 m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
4853 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
4856 void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
4858 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4861 void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
4863 if(m_target->GetTypeId() != TYPEID_PLAYER)
4864 return;
4865 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
4868 /********************************/
4869 /*** ATTACK POWER ***/
4870 /********************************/
4872 void Aura::HandleAuraModAttackPower(bool apply, bool Real)
4874 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4877 void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
4879 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4880 return;
4882 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4885 void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
4887 //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
4888 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
4891 void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
4893 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4894 return;
4896 //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
4897 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
4900 void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
4902 // spells required only Real aura add/remove
4903 if(!Real)
4904 return;
4906 if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4907 return;
4909 if(m_modifier.m_miscvalue != STAT_INTELLECT)
4911 // support required adding UpdateAttackPowerAndDamage calls at stat update
4912 sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intelect stats!");
4913 return;
4916 // Recalculate bonus
4917 ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
4920 /********************************/
4921 /*** DAMAGE BONUS ***/
4922 /********************************/
4923 void Aura::HandleModDamageDone(bool apply, bool Real)
4925 // apply item specific bonuses for already equipped weapon
4926 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
4928 for(int i = 0; i < MAX_ATTACK; ++i)
4929 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4930 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
4933 // m_modifier.m_miscvalue is bitmask of spell schools
4934 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
4935 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
4936 // 127 - full bitmask any damages
4938 // mods must be applied base at equipped weapon class and subclass comparison
4939 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4940 // m_modifier.m_miscvalue comparison with item generated damage types
4942 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
4944 // apply generic physical damage bonuses including wand case
4945 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
4947 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4948 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4949 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4951 else
4953 // done in Player::_ApplyWeaponDependentAuraMods
4956 if(m_target->GetTypeId() == TYPEID_PLAYER)
4958 if(m_positive)
4959 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
4960 else
4961 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
4965 // Skip non magic case for speedup
4966 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
4967 return;
4969 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
4971 // wand magic case (skip generic to all item spell bonuses)
4972 // done in Player::_ApplyWeaponDependentAuraMods
4974 // Skip item specific requirements for not wand magic damage
4975 return;
4978 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4979 // This information for client side use only
4980 if(m_target->GetTypeId() == TYPEID_PLAYER)
4982 if(m_positive)
4984 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
4986 if((m_modifier.m_miscvalue & (1<<i)) != 0)
4987 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
4990 else
4992 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
4994 if((m_modifier.m_miscvalue & (1<<i)) != 0)
4995 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
4998 Pet* pet = m_target->GetPet();
4999 if(pet)
5000 pet->UpdateAttackPowerAndDamage();
5004 void Aura::HandleModDamagePercentDone(bool apply, bool Real)
5006 sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
5008 // apply item specific bonuses for already equipped weapon
5009 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5011 for(int i = 0; i < MAX_ATTACK; ++i)
5012 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5013 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5016 // m_modifier.m_miscvalue is bitmask of spell schools
5017 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5018 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
5019 // 127 - full bitmask any damages
5021 // mods must be applied base at equipped weapon class and subclass comparison
5022 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5023 // m_modifier.m_miscvalue comparison with item generated damage types
5025 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5027 // apply generic physical damage bonuses including wand case
5028 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5030 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5031 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5032 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5034 else
5036 // done in Player::_ApplyWeaponDependentAuraMods
5038 // For show in client
5039 if(m_target->GetTypeId() == TYPEID_PLAYER)
5040 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
5043 // Skip non magic case for speedup
5044 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5045 return;
5047 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5049 // wand magic case (skip generic to all item spell bonuses)
5050 // done in Player::_ApplyWeaponDependentAuraMods
5052 // Skip item specific requirements for not wand magic damage
5053 return;
5056 // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
5057 // Send info to client
5058 if(m_target->GetTypeId() == TYPEID_PLAYER)
5059 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
5060 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
5063 void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
5065 // spells required only Real aura add/remove
5066 if(!Real)
5067 return;
5069 sLog.outDebug("AURA MOD OFFHAND DAMAGE");
5071 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5074 /********************************/
5075 /*** POWER COST ***/
5076 /********************************/
5078 void Aura::HandleModPowerCostPCT(bool apply, bool Real)
5080 // spells required only Real aura add/remove
5081 if(!Real)
5082 return;
5084 float amount = m_modifier.m_amount/100.0f;
5085 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5086 if(m_modifier.m_miscvalue & (1<<i))
5087 m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
5090 void Aura::HandleModPowerCost(bool apply, bool Real)
5092 // spells required only Real aura add/remove
5093 if(!Real)
5094 return;
5096 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5097 if(m_modifier.m_miscvalue & (1<<i))
5098 m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
5101 /*********************************************************/
5102 /*** OTHERS ***/
5103 /*********************************************************/
5105 void Aura::HandleShapeshiftBoosts(bool apply)
5107 uint32 spellId = 0;
5108 uint32 spellId2 = 0;
5109 uint32 HotWSpellId = 0;
5111 switch(GetModifier()->m_miscvalue)
5113 case FORM_CAT:
5114 spellId = 3025;
5115 HotWSpellId = 24900;
5116 break;
5117 case FORM_TREE:
5118 spellId = 5420;
5119 break;
5120 case FORM_TRAVEL:
5121 spellId = 5419;
5122 break;
5123 case FORM_AQUA:
5124 spellId = 5421;
5125 break;
5126 case FORM_BEAR:
5127 spellId = 1178;
5128 spellId2 = 21178;
5129 HotWSpellId = 24899;
5130 break;
5131 case FORM_DIREBEAR:
5132 spellId = 9635;
5133 spellId2 = 21178;
5134 HotWSpellId = 24899;
5135 break;
5136 case FORM_BATTLESTANCE:
5137 spellId = 21156;
5138 break;
5139 case FORM_DEFENSIVESTANCE:
5140 spellId = 7376;
5141 break;
5142 case FORM_BERSERKERSTANCE:
5143 spellId = 7381;
5144 break;
5145 case FORM_MOONKIN:
5146 spellId = 24905;
5147 // aura from effect trigger spell
5148 spellId2 = 24907;
5149 break;
5150 case FORM_FLIGHT:
5151 spellId = 33948;
5152 break;
5153 case FORM_FLIGHT_EPIC:
5154 spellId = 40122;
5155 spellId2 = 40121;
5156 break;
5157 case FORM_SPIRITOFREDEMPTION:
5158 spellId = 27792;
5159 spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
5160 break;
5161 case FORM_GHOSTWOLF:
5162 case FORM_AMBIENT:
5163 case FORM_GHOUL:
5164 case FORM_SHADOW:
5165 case FORM_STEALTH:
5166 case FORM_CREATURECAT:
5167 case FORM_CREATUREBEAR:
5168 spellId = 0;
5169 break;
5172 uint32 form = GetModifier()->m_miscvalue-1;
5174 if(apply)
5176 if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
5177 if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
5179 if(m_target->GetTypeId() == TYPEID_PLAYER)
5181 const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
5182 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
5184 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
5185 if(itr->first==spellId || itr->first==spellId2) continue;
5186 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
5187 if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
5188 if (spellInfo->Stances & (1<<form))
5189 m_target->CastSpell(m_target, itr->first, true, NULL, this);
5191 //LotP
5192 if (((Player*)m_target)->HasSpell(17007))
5194 SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
5195 if (spellInfo && spellInfo->Stances & (1<<form))
5196 m_target->CastSpell(m_target, 24932, true, NULL, this);
5198 // HotW
5199 if (HotWSpellId)
5201 Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
5202 for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
5204 if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
5206 int32 HotWMod = (*i)->GetModifier()->m_amount;
5207 if(GetModifier()->m_miscvalue == FORM_CAT)
5208 HotWMod /= 2;
5210 m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
5211 break;
5217 else
5219 m_target->RemoveAurasDueToSpell(spellId);
5220 m_target->RemoveAurasDueToSpell(spellId2);
5222 Unit::AuraMap& tAuras = m_target->GetAuras();
5223 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
5225 if (itr->second->IsRemovedOnShapeLost())
5227 m_target->RemoveAurasDueToSpell(itr->second->GetId());
5228 itr = tAuras.begin();
5230 else
5232 ++itr;
5237 /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
5238 m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
5241 void Aura::HandleAuraEmpathy(bool apply, bool Real)
5243 if(m_target->GetTypeId() != TYPEID_UNIT)
5244 return;
5246 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
5247 if(ci && ci->type == CREATURE_TYPE_BEAST)
5248 m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
5251 void Aura::HandleAuraUntrackable(bool apply, bool Real)
5253 if(apply)
5254 m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5255 else
5256 m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5259 void Aura::HandleAuraModPacify(bool apply, bool Real)
5261 if(m_target->GetTypeId() != TYPEID_PLAYER)
5262 return;
5264 if(apply)
5265 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5266 else
5267 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5270 void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
5272 HandleAuraModPacify(apply,Real);
5273 HandleAuraModSilence(apply,Real);
5276 void Aura::HandleAuraGhost(bool apply, bool Real)
5278 if(m_target->GetTypeId() != TYPEID_PLAYER)
5279 return;
5281 if(apply)
5283 m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5285 else
5287 m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5291 void Aura::HandleAuraAllowFlight(bool apply, bool Real)
5293 // all applied/removed only at real aura add/remove
5294 if(!Real)
5295 return;
5297 // allow fly
5298 WorldPacket data;
5299 if(apply)
5300 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
5301 else
5302 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
5303 data.append(m_target->GetPackGUID());
5304 data << uint32(0); // unk
5305 m_target->SendMessageToSet(&data, true);
5308 void Aura::HandleModRating(bool apply, bool Real)
5310 // spells required only Real aura add/remove
5311 if(!Real)
5312 return;
5314 if(m_target->GetTypeId() != TYPEID_PLAYER)
5315 return;
5317 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5318 if (m_modifier.m_miscvalue & (1 << rating))
5319 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
5322 void Aura::HandleForceMoveForward(bool apply, bool Real)
5324 if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
5325 return;
5326 if(apply)
5327 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5328 else
5329 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5332 void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real)
5334 if(m_target->GetTypeId() != TYPEID_PLAYER)
5335 return;
5337 ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
5338 ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
5341 void Aura::HandleModTargetResistance(bool apply, bool Real)
5343 // spells required only Real aura add/remove
5344 if(!Real)
5345 return;
5346 // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
5348 // show armor penetration
5349 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
5350 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
5352 // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
5353 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
5354 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
5357 void Aura::HandleShieldBlockValue(bool apply, bool Real)
5359 BaseModType modType = FLAT_MOD;
5360 if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
5361 modType = PCT_MOD;
5363 if(m_target->GetTypeId() == TYPEID_PLAYER)
5364 ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
5367 void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
5369 // spells required only Real aura add/remove
5370 if(!Real)
5371 return;
5373 if(m_target->GetTypeId() != TYPEID_PLAYER)
5374 return;
5376 Player *target = (Player*)m_target;
5378 // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
5379 // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
5380 if( !apply && m_duration==0 && target->GetComboTarget())
5381 if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
5382 target->AddComboPoints(unit, -m_modifier.m_amount);
5385 void Aura::HandleModUnattackable( bool Apply, bool Real )
5387 if(Real && Apply)
5388 m_target->CombatStop();
5390 m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
5393 void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
5395 // spells required only Real aura add/remove
5396 if(!Real)
5397 return;
5399 // prepare spirit state
5400 if(apply)
5402 if(m_target->GetTypeId()==TYPEID_PLAYER)
5404 // disable breath/etc timers
5405 ((Player*)m_target)->StopMirrorTimers();
5407 // set stand state (expected in this form)
5408 if(!m_target->IsStandState())
5409 m_target->SetStandState(PLAYER_STATE_NONE);
5412 m_target->SetHealth(1);
5414 // die at aura end
5415 else
5416 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
5419 void Aura::CleanupTriggeredSpells()
5421 uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
5422 if(!tSpellId)
5423 return;
5425 SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
5426 if(!tProto)
5427 return;
5429 if(GetSpellDuration(tProto) != -1)
5430 return;
5432 // needed for spell 43680, maybe others
5433 // TODO: is there a spell flag, which can solve this in a more sophisticated way?
5434 if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
5435 GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
5436 return;
5437 m_target->RemoveAurasDueToSpell(tSpellId);
5440 void Aura::HandleAuraPowerBurn(bool apply, bool Real)
5442 if (m_periodicTimer <= 0)
5443 m_periodicTimer += m_modifier.periodictime;
5445 m_isPeriodic = apply;
5448 void Aura::HandleSchoolAbsorb(bool apply, bool Real)
5450 if(!Real)
5451 return;
5453 // prevent double apply bonuses
5454 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
5456 if(Unit* caster = GetCaster())
5458 float DoneActualBenefit = 0.0f;
5459 switch(m_spellProto->SpellFamilyName)
5461 case SPELLFAMILY_PRIEST:
5462 if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
5464 //+30% from +healing bonus
5465 DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
5466 break;
5468 break;
5469 case SPELLFAMILY_MAGE:
5470 if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
5472 //frost ward, fire ward, ice barrier
5473 //+10% from +spd bonus
5474 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5475 break;
5477 break;
5478 case SPELLFAMILY_WARLOCK:
5479 if(m_spellProto->SpellFamilyFlags == 0x00)
5481 //shadow ward
5482 //+10% from +spd bonus
5483 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5484 break;
5486 break;
5487 default:
5488 break;
5491 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
5493 m_modifier.m_amount += (int32)DoneActualBenefit;
5498 void Aura::PeriodicTick()
5500 if(!m_target->isAlive())
5501 return;
5503 switch(m_modifier.m_auraname)
5505 case SPELL_AURA_PERIODIC_DAMAGE:
5506 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
5508 Unit *pCaster = GetCaster();
5509 if(!pCaster)
5510 return;
5512 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5513 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5514 return;
5516 // Check for immune (not use charges)
5517 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5518 return;
5520 // some auras remove at specific health level or more
5521 if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
5523 switch(GetId())
5525 case 43093: case 31956: case 38801:
5526 case 35321: case 38363: case 39215:
5527 if(m_target->GetHealth() == m_target->GetMaxHealth() )
5529 m_target->RemoveAurasDueToSpell(GetId());
5530 return;
5532 break;
5533 case 38772:
5535 uint32 percent =
5536 GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
5537 pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
5538 100;
5539 if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
5541 m_target->RemoveAurasDueToSpell(GetId());
5542 return;
5544 break;
5546 default:
5547 break;
5551 uint32 absorb=0;
5552 uint32 resist=0;
5553 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5555 // ignore non positive values (can be result apply spellmods to aura damage
5556 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5558 uint32 pdamage;
5560 if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
5562 pdamage = amount;
5564 // Calculate armor mitigation if it is a physical spell
5565 // But not for bleed mechanic spells
5566 if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
5567 GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
5569 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5570 cleanDamage.damage += pdamage - pdamageReductedArmor;
5571 pdamage = pdamageReductedArmor;
5574 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5576 // Curse of Agony damage-per-tick calculation
5577 if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
5579 // 1..4 ticks, 1/2 from normal tick damage
5580 if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
5581 pdamage = pdamage/2;
5582 // 9..12 ticks, 3/2 from normal tick damage
5583 else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
5584 pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
5585 // 5..8 ticks have normal tick damage
5588 else
5589 pdamage = uint32(m_target->GetMaxHealth()*amount/100);
5591 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5592 // Reduce dot damage from resilience for players
5593 if (m_target->GetTypeId()==TYPEID_PLAYER)
5594 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5596 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5598 sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5599 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5601 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5602 data.append(m_target->GetPackGUID());
5603 data.appendPackGUID(GetCasterGUID());
5604 data << uint32(GetId());
5605 data << uint32(1);
5606 data << uint32(m_modifier.m_auraname);
5607 data << (uint32)pdamage;
5608 data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
5609 data << (uint32)absorb;
5610 data << (uint32)resist;
5611 m_target->SendMessageToSet(&data,true);
5613 Unit* target = m_target; // aura can be deleted in DealDamage
5614 SpellEntry const* spellProto = GetSpellProto();
5616 // Set trigger flag
5617 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
5618 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
5619 pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
5620 if (pdamage)
5621 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
5622 pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5624 pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true);
5625 break;
5627 case SPELL_AURA_PERIODIC_LEECH:
5629 Unit *pCaster = GetCaster();
5630 if(!pCaster)
5631 return;
5633 if(!pCaster->isAlive())
5634 return;
5636 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5637 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5638 return;
5640 // Check for immune (not use charges)
5641 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5642 return;
5644 uint32 absorb=0;
5645 uint32 resist=0;
5646 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5648 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5650 //Calculate armor mitigation if it is a physical spell
5651 if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
5653 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5654 cleanDamage.damage += pdamage - pdamageReductedArmor;
5655 pdamage = pdamageReductedArmor;
5658 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5660 // talent Soul Siphon add bonus to Drain Life spells
5661 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
5663 // find talent max bonus percentage
5664 Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5665 for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
5667 if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
5669 if((*i)->GetEffIndex()!=1)
5671 sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
5672 break;
5675 // effect 1 m_amount
5676 int32 maxPercent = (*i)->GetModifier()->m_amount;
5677 // effect 0 m_amount
5678 int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
5680 // count affliction effects and calc additional damage in percentage
5681 int32 modPercent = 0;
5682 Unit::AuraMap const& victimAuras = m_target->GetAuras();
5683 for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
5685 Aura* aura = itr->second;
5686 if (aura->IsPositive())continue;
5687 SpellEntry const* m_spell = aura->GetSpellProto();
5688 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
5689 continue;
5691 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
5692 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
5694 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
5696 if(_spell_idx->second->skillId == SKILL_AFFLICTION)
5698 modPercent += stepPercent;
5699 if (modPercent >= maxPercent)
5701 modPercent = maxPercent;
5702 break;
5707 pdamage += (pdamage*modPercent/100);
5708 break;
5713 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5714 // Reduce dot damage from resilience for players
5715 if (m_target->GetTypeId()==TYPEID_PLAYER)
5716 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5718 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5720 if(m_target->GetHealth() < pdamage)
5721 pdamage = uint32(m_target->GetHealth());
5723 sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5724 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5726 pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
5729 Unit* target = m_target; // aura can be deleted in DealDamage
5730 SpellEntry const* spellProto = GetSpellProto();
5731 float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
5733 // Set trigger flag
5734 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
5735 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
5736 pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
5737 if (pdamage)
5738 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
5739 pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5740 int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false);
5742 if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
5744 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
5746 if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
5747 pCaster->m_currentSpells[i]->cancel();
5752 if(Player *modOwner = pCaster->GetSpellModOwner())
5753 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
5755 uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
5757 int32 gain = pCaster->ModifyHealth(heal);
5758 pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
5760 pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
5761 break;
5763 case SPELL_AURA_PERIODIC_HEAL:
5764 case SPELL_AURA_OBS_MOD_HEALTH:
5766 Unit *pCaster = GetCaster();
5767 if(!pCaster)
5768 return;
5770 // heal for caster damage (must be alive)
5771 if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive())
5772 return;
5774 // ignore non positive values (can be result apply spellmods to aura damage
5775 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5777 uint32 pdamage;
5779 if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
5780 pdamage = uint32(m_target->GetMaxHealth() * amount/100);
5781 else
5782 pdamage = amount;
5784 pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
5786 sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
5787 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5789 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5790 data.append(m_target->GetPackGUID());
5791 data.appendPackGUID(GetCasterGUID());
5792 data << uint32(GetId());
5793 data << uint32(1);
5794 data << uint32(m_modifier.m_auraname);
5795 data << (uint32)pdamage;
5796 m_target->SendMessageToSet(&data,true);
5798 int32 gain = m_target->ModifyHealth(pdamage);
5800 // add HoTs to amount healed in bgs
5801 if( pCaster->GetTypeId() == TYPEID_PLAYER )
5802 if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
5803 bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
5805 //Do check before because m_modifier.auraName can be invalidate by DealDamage.
5806 bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
5808 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5810 Unit* target = m_target; // aura can be deleted in DealDamage
5811 SpellEntry const* spellProto = GetSpellProto();
5812 bool haveCastItem = GetCastItemGUID()!=0;
5814 // heal for caster damage
5815 if(m_target!=pCaster && spellProto->SpellVisual==163)
5817 uint32 dmg = spellProto->manaPerSecond;
5818 if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
5820 pCaster->RemoveAurasDueToSpell(GetId());
5822 // finish current generic/channeling spells, don't affect autorepeat
5823 if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
5825 pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
5827 if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
5829 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
5830 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
5833 else
5835 pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
5837 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5838 pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5842 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HEAL;
5843 uint32 procVictim = 0;//ROC_FLAG_ON_TAKE_PERIODIC | PROC_FLAG_TAKEN_HEAL;
5844 // ignore item heals
5845 // if(procSpell && !haveCastItem)
5846 // pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5847 break;
5849 case SPELL_AURA_PERIODIC_MANA_LEECH:
5851 Unit *pCaster = GetCaster();
5852 if(!pCaster)
5853 return;
5855 if(!pCaster->isAlive())
5856 return;
5858 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5859 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5860 return;
5862 // Check for immune (not use charges)
5863 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5864 return;
5866 // ignore non positive values (can be result apply spellmods to aura damage
5867 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5869 sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
5870 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5872 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5873 break;
5875 Powers power = Powers(m_modifier.m_miscvalue);
5877 // power type might have changed between aura applying and tick (druid's shapeshift)
5878 if(m_target->getPowerType() != power)
5879 break;
5881 int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
5883 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
5884 if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
5885 drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
5887 m_target->ModifyPower(power, -drain_amount);
5889 float gain_multiplier = 0;
5891 if(pCaster->GetMaxPower(power) > 0)
5893 gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
5895 if(Player *modOwner = pCaster->GetSpellModOwner())
5896 modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
5899 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5900 data.append(m_target->GetPackGUID());
5901 data.appendPackGUID(GetCasterGUID());
5902 data << uint32(GetId());
5903 data << uint32(1);
5904 data << uint32(m_modifier.m_auraname);
5905 data << (uint32)power; // power type
5906 data << (uint32)drain_amount;
5907 data << (float)gain_multiplier;
5908 m_target->SendMessageToSet(&data,true);
5910 int32 gain_amount = int32(drain_amount*gain_multiplier);
5912 if(gain_amount)
5914 int32 gain = pCaster->ModifyPower(power,gain_amount);
5915 m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
5917 break;
5919 case SPELL_AURA_PERIODIC_ENERGIZE:
5921 // ignore non positive values (can be result apply spellmods to aura damage
5922 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5924 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
5925 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5927 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5928 break;
5930 Powers power = Powers(m_modifier.m_miscvalue);
5932 if(m_target->GetMaxPower(power) == 0)
5933 break;
5935 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5936 data.append(m_target->GetPackGUID());
5937 data.appendPackGUID(GetCasterGUID());
5938 data << uint32(GetId());
5939 data << uint32(1);
5940 data << uint32(m_modifier.m_auraname);
5941 data << (uint32)power; // power type
5942 data << (uint32)pdamage;
5943 m_target->SendMessageToSet(&data,true);
5945 int32 gain = m_target->ModifyPower(power,pdamage);
5947 if(Unit* pCaster = GetCaster())
5948 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5949 break;
5951 case SPELL_AURA_OBS_MOD_MANA:
5953 // ignore non positive values (can be result apply spellmods to aura damage
5954 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5956 uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
5958 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
5959 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5961 if(m_target->GetMaxPower(POWER_MANA) == 0)
5962 break;
5964 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5965 data.append(m_target->GetPackGUID());
5966 data.appendPackGUID(GetCasterGUID());
5967 data << uint32(GetId());
5968 data << uint32(1);
5969 data << uint32(m_modifier.m_auraname);
5970 data << (uint32)0; // ?
5971 data << (uint32)pdamage;
5972 m_target->SendMessageToSet(&data,true);
5974 int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
5976 if(Unit* pCaster = GetCaster())
5977 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5978 break;
5980 case SPELL_AURA_POWER_BURN_MANA:
5982 Unit *pCaster = GetCaster();
5983 if(!pCaster)
5984 return;
5986 // Check for immune (not use charges)
5987 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5988 return;
5990 int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5992 Powers powerType = Powers(m_modifier.m_miscvalue);
5994 if(!m_target->isAlive() || m_target->getPowerType() != powerType)
5995 return;
5997 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
5998 if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
5999 pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
6001 uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
6003 gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
6005 SpellEntry const* spellProto = GetSpellProto();
6006 //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
6007 SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask);
6008 pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto);
6009 pCaster->SendSpellNonMeleeDamageLog(&damageInfo);
6011 // Set trigger flag
6012 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
6013 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
6014 uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE);
6015 if (damageInfo.damage)
6016 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
6018 pCaster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);
6020 pCaster->DealSpellDamage(&damageInfo, true);
6021 break;
6023 // Here tick dummy auras
6024 case SPELL_AURA_PERIODIC_DUMMY:
6026 PeriodicDummyTick();
6027 break;
6029 default:
6030 break;
6034 void Aura::PeriodicDummyTick()
6036 SpellEntry const* spell = GetSpellProto();
6037 switch (spell->Id)
6039 // Drink
6040 case 430:
6041 case 431:
6042 case 432:
6043 case 1133:
6044 case 1135:
6045 case 1137:
6046 case 10250:
6047 case 22734:
6048 case 27089:
6049 case 34291:
6050 case 43706:
6051 case 46755:
6053 if (m_target->GetTypeId() != TYPEID_PLAYER)
6054 return;
6055 // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
6056 Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
6057 for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
6059 if ((*i)->GetId() == GetId())
6061 // Get tick number
6062 int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
6063 // Default case (not on arenas)
6064 if (tick == 0)
6066 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6067 ((Player*)m_target)->UpdateManaRegen();
6068 // Disable continue
6069 m_isPeriodic = false;
6071 return;
6072 //**********************************************
6073 // Code commended since arena patch not added
6074 // This feature uses only in arenas
6075 //**********************************************
6076 // Here need increase mana regen per tick (6 second rule)
6077 // on 0 tick - 0 (handled in 2 second)
6078 // on 1 tick - 166% (handled in 4 second)
6079 // on 2 tick - 133% (handled in 6 second)
6080 // Not need update after 3 tick
6082 if (tick > 3)
6083 return;
6084 // Apply bonus for 0 - 3 tick
6085 switch (tick)
6087 case 0: // 0%
6088 (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
6089 break;
6090 case 1: // 166%
6091 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
6092 break;
6093 case 2: // 133%
6094 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
6095 break;
6096 default: // 100% - normal regen
6097 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6098 break;
6100 ((Player*)m_target)->UpdateManaRegen();
6101 return;*/
6104 return;
6106 // // Panda
6107 // case 19230: break;
6108 // // Master of Subtlety
6109 // case 31666: break;
6110 // // Gossip NPC Periodic - Talk
6111 // case 33208: break;
6112 // // Gossip NPC Periodic - Despawn
6113 // case 33209: break;
6114 // // Force of Nature
6115 // case 33831: break;
6116 // Aspect of the Viper
6117 case 34074:
6119 if (m_target->GetTypeId() != TYPEID_PLAYER)
6120 return;
6121 // Should be manauser
6122 if (m_target->getPowerType()!=POWER_MANA)
6123 return;
6124 Unit *caster = GetCaster();
6125 if (!caster)
6126 return;
6127 // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
6128 int mana = m_target->GetPower(POWER_MANA);
6129 int max_mana = m_target->GetMaxPower(POWER_MANA);
6130 int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
6131 float regen_pct = 1.20f - 1.1f * mana / max_mana;
6132 if (regen_pct > 1.0f) regen_pct = 1.0f;
6133 else if (regen_pct < 0.2f) regen_pct = 0.2f;
6134 m_modifier.m_amount = int32 (base_regen * regen_pct);
6135 ((Player*)m_target)->UpdateManaRegen();
6136 return;
6138 // // Steal Weapon
6139 // case 36207: break;
6140 // // Simon Game START timer, (DND)
6141 // case 39993: break;
6142 // // Harpooner's Mark
6143 // case 40084: break;
6144 // // Knockdown Fel Cannon: break; The Aggro Burst
6145 // case 40119: break;
6146 // // Old Mount Spell
6147 // case 40154: break;
6148 // // Magnetic Pull
6149 // case 40581: break;
6150 // // Ethereal Ring: break; The Bolt Burst
6151 // case 40801: break;
6152 // // Crystal Prison
6153 // case 40846: break;
6154 // // Copy Weapon
6155 // case 41054: break;
6156 // // Ethereal Ring Visual, Lightning Aura
6157 // case 41477: break;
6158 // // Ethereal Ring Visual, Lightning Aura (Fork)
6159 // case 41525: break;
6160 // // Ethereal Ring Visual, Lightning Jumper Aura
6161 // case 41567: break;
6162 // // No Man's Land
6163 // case 41955: break;
6164 // // Headless Horseman - Fire
6165 // case 42074: break;
6166 // // Headless Horseman - Visual - Large Fire
6167 // case 42075: break;
6168 // // Headless Horseman - Start Fire, Periodic Aura
6169 // case 42140: break;
6170 // // Ram Speed Boost
6171 // case 42152: break;
6172 // // Headless Horseman - Fires Out Victory Aura
6173 // case 42235: break;
6174 // // Pumpkin Life Cycle
6175 // case 42280: break;
6176 // // Brewfest Request Chick Chuck Mug Aura
6177 // case 42537: break;
6178 // // Squashling
6179 // case 42596: break;
6180 // // Headless Horseman Climax, Head: Periodic
6181 // case 42603: break;
6182 // // Fire Bomb
6183 // case 42621: break;
6184 // // Headless Horseman - Conflagrate, Periodic Aura
6185 // case 42637: break;
6186 // // Headless Horseman - Create Pumpkin Treats Aura
6187 // case 42774: break;
6188 // // Headless Horseman Climax - Summoning Rhyme Aura
6189 // case 42879: break;
6190 // // Tricky Treat
6191 // case 42919: break;
6192 // // Giddyup!
6193 // case 42924: break;
6194 // // Ram - Trot
6195 // case 42992: break;
6196 // // Ram - Canter
6197 // case 42993: break;
6198 // // Ram - Gallop
6199 // case 42994: break;
6200 // // Ram Level - Neutral
6201 // case 43310: break;
6202 // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
6203 // case 43884: break;
6204 // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
6205 // case 44000: break;
6206 // // Energy Feedback
6207 // case 44328: break;
6208 // // Romantic Picnic
6209 // case 45102: break;
6210 // // Romantic Picnic
6211 // case 45123: break;
6212 // // Looking for Love
6213 // case 45124: break;
6214 // // Kite - Lightning Strike Kite Aura
6215 // case 45197: break;
6216 // // Rocket Chicken
6217 // case 45202: break;
6218 // // Copy Offhand Weapon
6219 // case 45205: break;
6220 // // Upper Deck - Kite - Lightning Periodic Aura
6221 // case 45207: break;
6222 // // Kite -Sky Lightning Strike Kite Aura
6223 // case 45251: break;
6224 // // Ribbon Pole Dancer Check Aura
6225 // case 45390: break;
6226 // // Holiday - Midsummer, Ribbon Pole Periodic Visual
6227 // case 45406: break;
6228 // // Parachute
6229 // case 45472: break;
6230 // // Alliance Flag, Extra Damage Debuff
6231 // case 45898: break;
6232 // // Horde Flag, Extra Damage Debuff
6233 // case 45899: break;
6234 // // Ahune - Summoning Rhyme Aura
6235 // case 45926: break;
6236 // // Ahune - Slippery Floor
6237 // case 45945: break;
6238 // // Ahune's Shield
6239 // case 45954: break;
6240 // // Nether Vapor Lightning
6241 // case 45960: break;
6242 // // Darkness
6243 // case 45996: break;
6244 // // Summon Blood Elves Periodic
6245 // case 46041: break;
6246 // // Transform Visual Missile Periodic
6247 // case 46205: break;
6248 // // Find Opening Beam End
6249 // case 46333: break;
6250 // // Ice Spear Control Aura
6251 // case 46371: break;
6252 // // Hailstone Chill
6253 // case 46458: break;
6254 // // Hailstone Chill, Internal
6255 // case 46465: break;
6256 // // Chill, Internal Shifter
6257 // case 46549: break;
6258 // // Summon Ice Spear Knockback Delayer
6259 // case 46878: break;
6260 // // Burninate Effect
6261 // case 47214: break;
6262 // // Fizzcrank Practice Parachute
6263 // case 47228: break;
6264 // // Send Mug Control Aura
6265 // case 47369: break;
6266 // // Direbrew's Disarm (precast)
6267 // case 47407: break;
6268 // // Mole Machine Port Schedule
6269 // case 47489: break;
6270 // // Mole Machine Portal Schedule
6271 // case 49466: break;
6272 // // Drink Coffee
6273 // case 49472: break;
6274 // // Listening to Music
6275 // case 50493: break;
6276 // // Love Rocket Barrage
6277 // case 50530: break;
6278 default:
6279 break;
6283 void Aura::HandlePreventFleeing(bool apply, bool Real)
6285 if(!Real)
6286 return;
6288 Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
6289 if( !fearAuras.empty() )
6291 if (apply)
6292 m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
6293 else
6294 m_target->SetFeared(true);
6298 void Aura::HandleManaShield(bool apply, bool Real)
6300 if(!Real)
6301 return;
6303 // prevent double apply bonuses
6304 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
6306 if(Unit* caster = GetCaster())
6308 float DoneActualBenefit = 0.0f;
6309 switch(m_spellProto->SpellFamilyName)
6311 case SPELLFAMILY_MAGE:
6312 if(m_spellProto->SpellFamilyFlags & 0x8000)
6314 // Mana Shield
6315 // +50% from +spd bonus
6316 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
6317 break;
6319 break;
6320 default:
6321 break;
6324 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
6326 m_modifier.m_amount += (int32)DoneActualBenefit;
6331 void Aura::HandleArenaPreparation(bool apply, bool Real)
6333 if(!Real)
6334 return;
6336 if(apply)
6337 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6338 else
6339 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);