Fixed possible crash
[getmangos.git] / src / game / SpellAuras.cpp
blobf427fb4220b4c52f894a1921b6478c5f657d3799
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "Opcodes.h"
24 #include "Log.h"
25 #include "UpdateMask.h"
26 #include "World.h"
27 #include "ObjectMgr.h"
28 #include "SpellMgr.h"
29 #include "Player.h"
30 #include "Unit.h"
31 #include "Spell.h"
32 #include "SpellAuras.h"
33 #include "DynamicObject.h"
34 #include "Group.h"
35 #include "UpdateData.h"
36 #include "MapManager.h"
37 #include "ObjectAccessor.h"
38 #include "Policies/SingletonImp.h"
39 #include "Totem.h"
40 #include "Creature.h"
41 #include "Formulas.h"
42 #include "BattleGround.h"
43 #include "CreatureAI.h"
44 #include "Util.h"
45 #include "GridNotifiers.h"
46 #include "GridNotifiersImpl.h"
47 #include "CellImpl.h"
49 #define NULL_AURA_SLOT 0xFF
51 pAuraHandler AuraHandler[TOTAL_AURAS]=
53 &Aura::HandleNULL, // 0 SPELL_AURA_NONE
54 &Aura::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT
55 &Aura::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS
56 &Aura::HandlePeriodicDamage, // 3 SPELL_AURA_PERIODIC_DAMAGE
57 &Aura::HandleAuraDummy, // 4 SPELL_AURA_DUMMY
58 &Aura::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE
59 &Aura::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM
60 &Aura::HandleModFear, // 7 SPELL_AURA_MOD_FEAR
61 &Aura::HandlePeriodicHeal, // 8 SPELL_AURA_PERIODIC_HEAL
62 &Aura::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED
63 &Aura::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT
64 &Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT
65 &Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN
66 &Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE
67 &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
68 &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage
69 &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH
70 &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT
71 &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY
72 &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION
73 &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH
74 &Aura::HandleAuraModTotalManaPercentRegen, // 21 SPELL_AURA_OBS_MOD_MANA
75 &Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE
76 &Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL
77 &Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE
78 &Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY
79 &Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT
80 &Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE
81 &Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult
82 &Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT
83 &Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL
84 &Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED
85 &Aura::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED
86 &Aura::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED
87 &Aura::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH
88 &Aura::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY
89 &Aura::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT
90 &Aura::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY
91 &Aura::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY
92 &Aura::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY
93 &Aura::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY
94 &Aura::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY
95 &Aura::HandleAuraProcTriggerSpell, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell
96 &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor
97 &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES
98 &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES
99 &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete?
100 &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT
101 &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete?
102 &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT
103 &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete?
104 &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT
105 &Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT
106 &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH
107 &Aura::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE
108 &Aura::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE
109 &Aura::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM
110 &Aura::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE
111 &Aura::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED
112 &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
113 &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
114 &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
115 &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
116 &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete?
117 &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH
118 &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED
119 &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
120 &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM
121 &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED
122 &Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
123 &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect
124 &Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
125 &Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
126 &Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL
127 &Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult
128 &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE
129 &Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT
130 &Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY
131 &Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED
132 &Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
133 &Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT
134 &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT
135 &Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING
136 &Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE
137 &Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN
138 &Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN
139 &Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM
140 &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
141 &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT
142 &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
143 &Aura::HandleUnused, // 90 SPELL_AURA_MOD_RESIST_CHANCE Useless
144 &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
145 &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING
146 &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE
147 &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll
148 &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST
149 &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget
150 &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist
151 &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT
152 &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER
153 &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now
154 &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT
155 &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
156 &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT
157 &Aura::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK
158 &Aura::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL
159 &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER
160 &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER
161 &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER
162 &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER
163 &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT
164 &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER
165 &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
166 &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
167 &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
168 &Aura::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim
169 &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
170 &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
171 &Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus
172 &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless
173 &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
174 &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
175 &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
176 &Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE
177 &Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER
178 &Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
179 &Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
180 &Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
181 &Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET
182 &Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS
183 &Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
184 &Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
185 &Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT
186 &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
187 &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
188 &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE
189 &Aura::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus
190 &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
191 &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE
192 &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
193 &Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
194 &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
195 &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
196 &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
197 &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
198 &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete?
199 &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete?
200 &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
201 &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
202 &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK
203 &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
204 &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
205 &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
206 &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
207 &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL
208 &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
209 &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
210 &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
211 &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
212 &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
213 &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
214 &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
215 &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA
216 &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE
217 &Aura::HandleUnused, //164 useless, only one test spell
218 &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
219 &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
220 &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
221 &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
222 &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
223 &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell
224 &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
225 &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
226 &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
227 &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT)
228 &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
229 &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
230 &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM
231 &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
232 &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
233 &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
234 &Aura::HandleUnused, //181 SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS unused
235 &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
236 &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT
237 &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
238 &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
239 &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult
240 &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
241 &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
242 &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING
243 &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
244 &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
245 &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
246 &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
247 &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT)
248 &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT)
249 &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
250 &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
251 &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
252 &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
253 &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP
254 &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
255 &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
256 &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::DoAttackDamage
257 &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::DoAttackDamage
258 &Aura::HandleNULL, //205 vulnerable to school dmg?
259 &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED
260 &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
261 &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive)
262 &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS
263 &Aura::HandleNULL, //210 Commentator's Command
264 &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
265 &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
266 &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
267 &Aura::HandleNULL, //214 Tamed Pet Passive
268 &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
269 &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
270 &Aura::HandleUnused, //217 unused
271 &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
272 &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
273 &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT
274 &Aura::HandleNULL, //221 ignored
275 &Aura::HandleUnused, //222 unused
276 &Aura::HandleNULL, //223 Cold Stare
277 &Aura::HandleUnused, //224 unused
278 &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING
279 &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY
280 &Aura::HandleNULL, //227 periodic trigger spell
281 &Aura::HandleNoImmediateEffect, //228 stealth detection
282 &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
283 &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
284 &Aura::HandleNULL, //231
285 &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
286 &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
287 &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
288 &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
289 &Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE
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::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
303 &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
304 &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE
305 &Aura::HandleNULL, //252
306 &Aura::HandleNULL, //253
307 &Aura::HandleNULL, //254
308 &Aura::HandleNULL, //255 SPELL_AURA_MOD_DAMAGE_PERCENT_MECHANIC
309 &Aura::HandleNULL, //256
310 &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS
311 &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
312 &Aura::HandleNULL, //259 corrupt healing over time spell
313 &Aura::HandleNULL, //260
314 &Aura::HandleNULL, //261 out of phase?
315 &Aura::HandleNULL, //262
316 &Aura::HandleNULL, //263 melee AOE
317 &Aura::HandleNULL, //264 unused
318 &Aura::HandleNULL, //265 unused
319 &Aura::HandleNULL, //266 unused
320 &Aura::HandleNULL, //267 some immunity?
321 &Aura::HandleNULL, //268 attack power from stat X
322 &Aura::HandleNULL, //269 ignore DR effects?
323 &Aura::HandleNULL, //270
324 &Aura::HandleNULL, //271 increase damage done?
325 &Aura::HandleNULL, //272 reduce spell cast time?
326 &Aura::HandleNULL, //273
327 &Aura::HandleNULL, //274 proc free shot?
328 &Aura::HandleNULL, //275 ignore shapeshift?
329 &Aura::HandleNULL, //276 mod damage % mechanic?
330 &Aura::HandleNULL, //277 increase max targets?
331 &Aura::HandleNULL, //278 disarm/silence
332 &Aura::HandleNULL, //279
333 &Aura::HandleNULL, //280 ignore armor?
334 &Aura::HandleNULL, //281 increase honor gain?
335 &Aura::HandleNULL, //282
336 &Aura::HandleNULL //283 SPD/heal from AP?
339 Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
340 m_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target),
341 m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS),
342 m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false),
343 m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false),
344 m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
346 assert(target);
348 assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
350 m_spellProto = spellproto;
352 m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff];
354 m_isPassive = IsPassiveSpell(GetId());
355 m_positive = IsPositiveEffect(GetId(), m_effIndex);
357 m_applyTime = time(NULL);
359 int32 damage;
360 if(!caster)
362 m_caster_guid = target->GetGUID();
363 damage = m_currentBasePoints+1; // stored value-1
364 m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target);
366 else
368 m_caster_guid = caster->GetGUID();
370 damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target);
371 m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target);
373 if (!damage && castItem && castItem->GetItemSuffixFactor())
375 ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
376 if(item_rand_suffix)
378 for (int k=0; k<3; k++)
380 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
381 if(pEnchant)
383 for (int t=0; t<3; t++)
384 if(pEnchant->spellid[t] == m_spellProto->Id)
386 damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 );
387 break;
391 if(damage)
392 break;
398 if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0)
399 m_permanent = true;
401 Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
403 if(!m_permanent && modOwner)
404 modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration);
406 m_duration = m_maxduration;
408 if(modOwner)
409 modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
411 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);
413 m_effIndex = eff;
414 SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
416 m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
418 if(m_spellProto->procCharges)
420 m_procCharges = m_spellProto->procCharges;
422 if(modOwner)
423 modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
425 else
426 m_procCharges = -1;
428 m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances &&
429 !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000));
432 Aura::~Aura()
436 AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
437 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
439 m_isAreaAura = true;
441 // caster==NULL in constructor args if target==caster in fact
442 Unit* caster_ptr = caster ? caster : target;
444 m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex]));
445 if(Player* modOwner = caster_ptr->GetSpellModOwner())
446 modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius);
448 switch(spellproto->Effect[eff])
450 case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
451 m_areaAuraType = AREA_AURA_PARTY;
452 if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
453 m_modifier.m_auraname = SPELL_AURA_NONE;
454 break;
455 case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
456 m_areaAuraType = AREA_AURA_RAID;
457 if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
458 m_modifier.m_auraname = SPELL_AURA_NONE;
459 break;
460 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
461 m_areaAuraType = AREA_AURA_FRIEND;
462 break;
463 case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
464 m_areaAuraType = AREA_AURA_ENEMY;
465 if(target == caster_ptr)
466 m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self
467 break;
468 case SPELL_EFFECT_APPLY_AREA_AURA_PET:
469 m_areaAuraType = AREA_AURA_PET;
470 break;
471 case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
472 m_areaAuraType = AREA_AURA_OWNER;
473 if(target == caster_ptr)
474 m_modifier.m_auraname = SPELL_AURA_NONE;
475 break;
476 default:
477 sLog.outError("Wrong spell effect in AreaAura constructor");
478 ASSERT(false);
479 break;
483 AreaAura::~AreaAura()
487 PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
488 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
490 m_isPersistent = true;
493 PersistentAreaAura::~PersistentAreaAura()
497 SingleEnemyTargetAura::SingleEnemyTargetAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
498 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
500 if (caster)
501 m_casters_target_guid = caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)caster)->GetSelection() : caster->GetUInt64Value(UNIT_FIELD_TARGET);
502 else
503 m_casters_target_guid = 0;
506 SingleEnemyTargetAura::~SingleEnemyTargetAura()
510 Unit* SingleEnemyTargetAura::GetTriggerTarget() const
512 return ObjectAccessor::GetUnit(*m_target, m_casters_target_guid);
515 Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem)
517 if (IsAreaAuraEffect(spellproto->Effect[eff]))
518 return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem);
520 uint32 triggeredSpellId = spellproto->EffectTriggerSpell[eff];
522 if(SpellEntry const* triggeredSpellInfo = sSpellStore.LookupEntry(triggeredSpellId))
523 for (int i = 0; i < 3; ++i)
524 if (triggeredSpellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_ENEMY)
525 return new SingleEnemyTargetAura(spellproto, eff, currentBasePoints, target, caster, castItem);
527 return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem);
530 Unit* Aura::GetCaster() const
532 if(m_caster_guid==m_target->GetGUID())
533 return m_target;
535 //return ObjectAccessor::GetUnit(*m_target,m_caster_guid);
536 //must return caster even if it's in another grid/map
537 Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL);
538 return unit && unit->IsInWorld() ? unit : NULL;
541 void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
543 m_modifier.m_auraname = t;
544 m_modifier.m_amount = a;
545 m_modifier.m_miscvalue = miscValue;
546 m_modifier.periodictime = pt;
549 void Aura::Update(uint32 diff)
551 if (m_duration > 0)
553 m_duration -= diff;
554 if (m_duration < 0)
555 m_duration = 0;
556 m_timeCla -= diff;
558 // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras
559 // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0
560 if(GetEffIndex()==0 && m_timeCla <= 0)
562 if(Unit* caster = GetCaster())
564 Powers powertype = Powers(m_spellProto->powerType);
565 int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel();
566 m_timeCla = 1000;
567 if (manaPerSecond)
569 if(powertype==POWER_HEALTH)
570 caster->ModifyHealth(-manaPerSecond);
571 else
572 caster->ModifyPower(powertype,-manaPerSecond);
578 // Channeled aura required check distance from caster
579 if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID())
581 Unit* caster = GetCaster();
582 if(!caster)
584 m_target->RemoveAura(GetId(),GetEffIndex());
585 return;
588 // Get spell range
589 float radius;
590 SpellModOp mod;
591 if (m_spellProto->EffectRadiusIndex[GetEffIndex()])
593 radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()]));
594 mod = SPELLMOD_RADIUS;
596 else
598 radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
599 mod = SPELLMOD_RANGE;
602 if(Player* modOwner = caster->GetSpellModOwner())
603 modOwner->ApplySpellMod(GetId(), mod, radius,NULL);
605 if(!caster->IsWithinDistInMap(m_target,radius))
607 m_target->RemoveAura(GetId(),GetEffIndex());
608 return;
612 if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
614 m_periodicTimer -= diff;
615 if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
617 if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN ||
618 m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN ||
619 // Cannibalize, eating items and other spells
620 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH ||
621 // Eating items and other spells
622 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA )
624 ApplyModifier(true);
625 return;
627 // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
628 m_periodicTimer += m_modifier.periodictime;
630 if(m_isTrigger)
631 TriggerSpell();
632 else
633 PeriodicTick();
638 void AreaAura::Update(uint32 diff)
640 // update for the caster of the aura
641 if(m_caster_guid == m_target->GetGUID())
643 Unit* caster = m_target;
645 if( !caster->hasUnitState(UNIT_STAT_ISOLATED) )
647 Unit* owner = caster->GetCharmerOrOwner();
648 if (!owner)
649 owner = caster;
650 std::list<Unit *> targets;
652 switch(m_areaAuraType)
654 case AREA_AURA_PARTY:
656 Group *pGroup = NULL;
658 if (owner->GetTypeId() == TYPEID_PLAYER)
659 pGroup = ((Player*)owner)->GetGroup();
661 if( pGroup)
663 uint8 subgroup = ((Player*)owner)->GetSubGroup();
664 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
666 Player* Target = itr->getSource();
667 if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target))
669 if(caster->IsWithinDistInMap(Target, m_radius))
670 targets.push_back(Target);
671 Pet *pet = Target->GetPet();
672 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
673 targets.push_back(pet);
677 else
679 // add owner
680 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
681 targets.push_back(owner);
682 // add caster's pet
683 Unit* pet = caster->GetPet();
684 if( pet && caster->IsWithinDistInMap(pet, m_radius))
685 targets.push_back(pet);
687 break;
689 case AREA_AURA_RAID:
691 Group *pGroup = NULL;
693 if (owner->GetTypeId() == TYPEID_PLAYER)
694 pGroup = ((Player*)owner)->GetGroup();
696 if( pGroup)
698 uint8 subgroup = ((Player*)owner)->GetSubGroup();
699 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
701 Player* Target = itr->getSource();
702 if(Target && Target->isAlive() && caster->IsFriendlyTo(Target))
704 if(caster->IsWithinDistInMap(Target, m_radius))
705 targets.push_back(Target);
706 Pet *pet = Target->GetPet();
707 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
708 targets.push_back(pet);
712 else
714 // add owner
715 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
716 targets.push_back(owner);
717 // add caster's pet
718 Unit* pet = caster->GetPet();
719 if( pet && caster->IsWithinDistInMap(pet, m_radius))
720 targets.push_back(pet);
722 break;
724 case AREA_AURA_FRIEND:
726 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
727 Cell cell(p);
728 cell.data.Part.reserved = ALL_DISTRICT;
729 cell.SetNoCreate();
731 MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius);
732 MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
733 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
734 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
735 CellLock<GridReadGuard> cell_lock(cell, p);
736 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
737 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
738 break;
740 case AREA_AURA_ENEMY:
742 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
743 Cell cell(p);
744 cell.data.Part.reserved = ALL_DISTRICT;
745 cell.SetNoCreate();
747 MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
748 MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);
749 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
750 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
751 CellLock<GridReadGuard> cell_lock(cell, p);
752 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
753 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
754 break;
756 case AREA_AURA_OWNER:
757 case AREA_AURA_PET:
759 if(owner != caster)
760 targets.push_back(owner);
761 break;
765 for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
767 if((*tIter)->HasAura(GetId(), m_effIndex))
768 continue;
770 if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
772 int32 actualBasePoints = m_currentBasePoints;
773 // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
774 if(actualSpellInfo != GetSpellProto())
775 actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
776 AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL);
777 (*tIter)->AddAura(aur);
781 Aura::Update(diff);
783 else // aura at non-caster
785 Unit * tmp_target = m_target;
786 Unit* caster = GetCaster();
787 uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
789 // WARNING: the aura may get deleted during the update
790 // DO NOT access its members after update!
791 Aura::Update(diff);
793 // remove aura if out-of-range from caster (after teleport for example)
794 // or caster is isolated or caster no longer has the aura
795 // or caster is (no longer) friendly
796 bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
797 if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
798 !caster->IsWithinDistInMap(tmp_target, m_radius) ||
799 !caster->HasAura(tmp_spellId, tmp_effIndex) ||
800 caster->IsFriendlyTo(tmp_target) != needFriendly
803 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
805 else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
807 // not check group if target == owner or target == pet
808 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
810 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
812 Group *pGroup = check ? check->GetGroup() : NULL;
813 if( pGroup )
815 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
816 if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
817 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
819 else
820 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
823 else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
825 // not check group if target == owner or target == pet
826 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
828 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
830 Group *pGroup = check ? check->GetGroup() : NULL;
831 if( pGroup )
833 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
834 if(!checkTarget)
835 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
837 else
838 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
841 else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
843 if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
844 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
849 void PersistentAreaAura::Update(uint32 diff)
851 bool remove = false;
853 // remove the aura if its caster or the dynamic object causing it was removed
854 // or if the target moves too far from the dynamic object
855 Unit *caster = GetCaster();
856 if (caster)
858 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
859 if (dynObj)
861 if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius()))
862 remove = true;
864 else
865 remove = true;
867 else
868 remove = true;
870 Unit *tmp_target = m_target;
871 uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
873 // WARNING: the aura may get deleted during the update
874 // DO NOT access its members after update!
875 Aura::Update(diff);
877 if(remove)
878 tmp_target->RemoveAura(tmp_id, tmp_index);
881 void Aura::ApplyModifier(bool apply, bool Real)
883 AuraType aura = m_modifier.m_auraname;
885 m_in_use = true;
886 if(aura<TOTAL_AURAS)
887 (*this.*AuraHandler [aura])(apply,Real);
888 m_in_use = false;
891 void Aura::_AddAura()
893 if (!GetId())
894 return;
895 if(!m_target)
896 return;
898 // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT
899 bool samespell = false;
900 bool secondaura = false;
901 uint8 slot = NULL_AURA_SLOT;
903 for(uint8 i = 0; i < 3; i++)
905 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
906 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
908 // allow use single slot only by auras from same caster
909 if(itr->second->GetCasterGUID()==GetCasterGUID())
911 samespell = true;
912 if (m_effIndex > itr->second->GetEffIndex())
913 secondaura = true;
914 slot = itr->second->GetAuraSlot();
915 break;
919 if(samespell)
920 break;
923 // not call total regen auras at adding
924 switch (m_modifier.m_auraname)
926 case SPELL_AURA_OBS_MOD_HEALTH:
927 case SPELL_AURA_OBS_MOD_MANA:
928 m_periodicTimer = m_modifier.periodictime;
929 break;
930 case SPELL_AURA_MOD_REGEN:
931 case SPELL_AURA_MOD_POWER_REGEN:
932 case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
933 m_periodicTimer = 5000;
934 break;
937 // register aura
938 if (getDiminishGroup() != DIMINISHING_NONE )
939 m_target->ApplyDiminishingAura(getDiminishGroup(),true);
941 Unit* caster = GetCaster();
943 // passive auras (except totem auras) do not get placed in the slots
944 // area auras with SPELL_AURA_NONE are not shown on target
945 if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
946 (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
948 if(!samespell) // new slot need
950 if(m_target->GetVisibleAurasCount() < MAX_AURAS)
952 Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras();
953 for(uint8 i = 0; i < MAX_AURAS; ++i)
955 Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i);
956 if(itr == visibleAuras->end())
958 slot = i;
959 break;
964 SetAuraSlot( slot );
966 // Not update fields for not first spell's aura, all data already in fields
967 if(!secondaura)
969 if(slot < MAX_AURAS) // slot found
971 SetAura(false);
972 SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE));
973 SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
974 UpdateAuraCharges();
975 SendAuraUpdate(false);
977 // update for out of range group members
978 m_target->UpdateAuraForGroup(slot);
982 else // use found slot
984 SetAuraSlot( slot );
985 // Not recalculate stack count for second aura of the same spell
986 if (!secondaura)
987 UpdateSlotCounterAndDuration(true);
990 // Update Seals information
991 if( IsSealSpell(GetSpellProto()) )
992 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
994 // Conflagrate aura state
995 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
996 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
998 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
999 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
1001 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
1006 void Aura::_RemoveAura()
1008 // Remove all triggered by aura spells vs unlimited duration
1009 // except same aura replace case
1010 if(m_removeMode!=AURA_REMOVE_BY_STACK)
1011 CleanupTriggeredSpells();
1013 Unit* caster = GetCaster();
1015 if(caster && IsPersistent())
1017 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
1018 if (dynObj)
1019 dynObj->RemoveAffected(m_target);
1022 // unregister aura
1023 if (getDiminishGroup() != DIMINISHING_NONE )
1024 m_target->ApplyDiminishingAura(getDiminishGroup(),false);
1026 //passive auras do not get put in slots
1027 // Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
1028 //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
1029 // return;
1031 uint8 slot = GetAuraSlot();
1033 if(slot >= MAX_AURAS) // slot not set
1034 return;
1036 if(m_target->GetVisibleAura(slot) == 0)
1037 return;
1039 bool samespell = false;
1040 bool sameaura = false;
1042 // find other aura in same slot (current already removed from list)
1043 for(uint8 i = 0; i < 3; i++)
1045 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
1046 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
1048 if(itr->second->GetAuraSlot()==slot)
1050 samespell = true;
1052 if(GetEffIndex()==i)
1053 sameaura = true;
1055 break;
1058 if(samespell)
1059 break;
1062 // only remove icon when the last aura of the spell is removed (current aura already removed from list)
1063 if (!samespell)
1065 SetAura(true);
1066 SetAuraFlags(AFLAG_NONE);
1067 SetAuraLevel(0);
1068 SetAuraCharges(0);
1069 SendAuraUpdate(true);
1071 // update for out of range group members
1072 m_target->UpdateAuraForGroup(slot);
1074 if( IsSealSpell(GetSpellProto()) )
1075 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
1077 // Conflagrate aura state
1078 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
1079 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false);
1081 // Swiftmend aura state
1082 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1083 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
1085 bool found = false;
1086 Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
1087 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
1089 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1090 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
1092 found = true;
1093 break;
1096 if(!found)
1097 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false);
1100 // reset cooldown state for spells
1101 if(caster && caster->GetTypeId() == TYPEID_PLAYER)
1103 if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
1104 ((Player*)caster)->SendCooldownEvent(GetSpellProto());
1107 else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove process.
1108 UpdateSlotCounterAndDuration(false);
1111 void Aura::SendAuraUpdate(bool remove)
1113 WorldPacket data(SMSG_AURA_UPDATE);
1114 data.append(m_target->GetPackGUID());
1115 data << uint8(GetAuraSlot());
1116 data << uint32(remove ? 0 : GetId());
1118 if(remove)
1120 m_target->SendMessageToSet(&data, true);
1121 return;
1124 uint8 auraFlags = GetAuraFlags();
1125 data << uint8(auraFlags);
1126 data << uint8(GetAuraLevel());
1127 data << uint8(m_procCharges >= 0 ? m_procCharges : 0);
1129 if(!(auraFlags & AFLAG_NOT_CASTER))
1131 data << uint8(0); // pguid
1134 if(auraFlags & AFLAG_DURATION)
1136 data << uint32(GetAuraMaxDuration());
1137 data << uint32(GetAuraDuration());
1140 m_target->SendMessageToSet(&data, true);
1143 void Aura::UpdateSlotCounterAndDuration(bool add)
1145 uint8 slot = GetAuraSlot();
1146 if(slot >= MAX_AURAS)
1147 return;
1149 // calculate amount of similar auras by same effect index (similar different spells)
1150 int8 count = 0;
1152 // calculate auras and update durations in case aura adding
1153 Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname);
1154 for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i)
1156 if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex &&
1157 (*i)->GetCasterGUID()==GetCasterGUID() )
1159 ++count;
1161 if(add)
1162 (*i)->SetAuraDuration(GetAuraDuration());
1166 // at aura add aura not added yet, at aura remove aura already removed
1167 // in field stored (count-1)
1168 if(!add)
1169 --count;
1171 SetAuraCharges(count);
1172 SendAuraUpdate(false);
1175 /*********************************************************/
1176 /*** BASIC AURA FUNCTION ***/
1177 /*********************************************************/
1178 void Aura::HandleAddModifier(bool apply, bool Real)
1180 if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
1181 return;
1183 SpellEntry const *spellInfo = GetSpellProto();
1184 if(!spellInfo)
1185 return;
1187 if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
1188 return;
1190 if (apply)
1192 // Add custom charges for some mod aura
1193 switch (m_spellProto->Id)
1195 case 17941: // Shadow Trance
1196 case 22008: // Netherwind Focus
1197 case 34936: // Backlash
1198 m_procCharges = 1;
1199 break;
1202 SpellModifier *mod = new SpellModifier;
1203 mod->op = SpellModOp(m_modifier.m_miscvalue);
1204 mod->value = m_modifier.m_amount;
1205 mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
1206 mod->spellId = GetId();
1207 mod->effectId = m_effIndex;
1208 mod->lastAffected = NULL;
1210 uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex);
1212 if (spellAffectMask)
1213 mod->mask = spellAffectMask;
1214 else
1215 mod->mask = spellInfo->EffectItemType[m_effIndex];
1217 if (m_procCharges > 0)
1218 mod->charges = m_procCharges;
1219 else
1220 mod->charges = 0;
1222 m_spellmod = mod;
1225 uint64 spellFamilyMask = m_spellmod->mask;
1227 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
1229 // reapply some passive spells after add/remove related spellmods
1230 if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
1232 m_target->RemoveAurasDueToSpell(45471);
1234 if(apply)
1235 m_target->CastSpell(m_target,45471,true);
1239 void Aura::TriggerSpell()
1241 Unit* caster = GetCaster();
1242 Unit* target = GetTriggerTarget();
1244 if(!caster || !target)
1245 return;
1247 // generic casting code with custom spells and target/caster customs
1248 uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
1250 uint64 originalCasterGUID = GetCasterGUID();
1252 SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1253 SpellEntry const *auraSpellInfo = GetSpellProto();
1254 uint32 auraId = auraSpellInfo->Id;
1256 // specific code for cases with no trigger spell provided in field
1257 if (triggeredSpellInfo == NULL)
1259 switch(auraSpellInfo->SpellFamilyName)
1261 case SPELLFAMILY_GENERIC:
1263 switch(auraId)
1265 // Firestone Passive (1-5 ranks)
1266 case 758:
1267 case 17945:
1268 case 17947:
1269 case 17949:
1270 case 27252:
1272 if (caster->GetTypeId()!=TYPEID_PLAYER)
1273 return;
1274 Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
1275 if (!item)
1276 return;
1277 uint32 enchant_id = 0;
1278 switch (GetId())
1280 case 758: enchant_id = 1803; break; // Rank 1
1281 case 17945: enchant_id = 1823; break; // Rank 2
1282 case 17947: enchant_id = 1824; break; // Rank 3
1283 case 17949: enchant_id = 1825; break; // Rank 4
1284 case 27252: enchant_id = 2645; break; // Rank 5
1285 default:
1286 return;
1288 // remove old enchanting before applying new
1289 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1290 item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
1291 // add new enchanting
1292 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
1293 return;
1295 // // Periodic Mana Burn
1296 // case 812: break;
1297 // // Polymorphic Ray
1298 // case 6965: break;
1299 // // Fire Nova (1-7 ranks)
1300 // case 8350:
1301 // case 8508:
1302 // case 8509:
1303 // case 11312:
1304 // case 11313:
1305 // case 25540:
1306 // case 25544:
1307 // break;
1308 // Thaumaturgy Channel
1309 case 9712: trigger_spell_id = 21029; break;
1310 // // Egan's Blaster
1311 // case 17368: break;
1312 // // Haunted
1313 // case 18347: break;
1314 // // Ranshalla Waiting
1315 // case 18953: break;
1316 // // Inferno
1317 // case 19695: break;
1318 // // Frostwolf Muzzle DND
1319 // case 21794: break;
1320 // // Alterac Ram Collar DND
1321 // case 21866: break;
1322 // // Celebras Waiting
1323 // case 21916: break;
1324 // Brood Affliction: Bronze
1325 case 23170:
1327 m_target->CastSpell(m_target, 23171, true, 0, this);
1328 return;
1330 // // Mark of Frost
1331 // case 23184: break;
1332 // Restoration
1333 case 23493:
1335 int32 heal = caster->GetMaxHealth() / 10;
1336 caster->ModifyHealth( heal );
1337 caster->SendHealSpellLog(caster, 23493, heal);
1339 int32 mana = caster->GetMaxPower(POWER_MANA);
1340 if (mana)
1342 mana /= 10;
1343 caster->ModifyPower( POWER_MANA, mana );
1344 caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
1346 break;
1348 // // Stoneclaw Totem Passive TEST
1349 // case 23792: break;
1350 // // Axe Flurry
1351 // case 24018: break;
1352 // // Mark of Arlokk
1353 // case 24210: break;
1354 // // Restoration
1355 // case 24379: break;
1356 // // Happy Pet
1357 // case 24716: break;
1358 // // Dream Fog
1359 // case 24780: break;
1360 // // Cannon Prep
1361 // case 24832: break;
1362 // // Shadow Bolt Whirl
1363 // case 24834: break;
1364 // // Stink Trap
1365 // case 24918: break;
1366 // // Mark of Nature
1367 // case 25041: break;
1368 // // Agro Drones
1369 // case 25152: break;
1370 // // Consume
1371 // case 25371: break;
1372 // // Pain Spike
1373 // case 25572: break;
1374 // // Rotate 360
1375 // case 26009: break;
1376 // // Rotate -360
1377 // case 26136: break;
1378 // // Consume
1379 // case 26196: break;
1380 // // Berserk
1381 // case 26615: break;
1382 // // Defile
1383 // case 27177: break;
1384 // // Teleport: IF/UC
1385 // case 27601: break;
1386 // // Five Fat Finger Exploding Heart Technique
1387 // case 27673: break;
1388 // // Nitrous Boost
1389 // case 27746: break;
1390 // // Steam Tank Passive
1391 // case 27747: break;
1392 // // Frost Blast
1393 // case 27808: break;
1394 // // Detonate Mana
1395 // case 27819: break;
1396 // // Controller Timer
1397 // case 28095: break;
1398 // // Stalagg Chain
1399 // case 28096: break;
1400 // // Stalagg Tesla Passive
1401 // case 28097: break;
1402 // // Feugen Tesla Passive
1403 // case 28109: break;
1404 // // Feugen Chain
1405 // case 28111: break;
1406 // // Mark of Didier
1407 // case 28114: break;
1408 // // Communique Timer, camp
1409 // case 28346: break;
1410 // // Icebolt
1411 // case 28522: break;
1412 // // Silithyst
1413 // case 29519: break;
1414 // // Inoculate Nestlewood Owlkin
1415 case 29528: trigger_spell_id = 28713; break;
1416 // // Overload
1417 // case 29768: break;
1418 // // Return Fire
1419 // case 29788: break;
1420 // // Return Fire
1421 // case 29793: break;
1422 // // Return Fire
1423 // case 29794: break;
1424 // // Guardian of Icecrown Passive
1425 // case 29897: break;
1426 // Feed Captured Animal
1427 case 29917: trigger_spell_id = 29916; break;
1428 // // Flame Wreath
1429 // case 29946: break;
1430 // // Flame Wreath
1431 // case 29947: break;
1432 // // Mind Exhaustion Passive
1433 // case 30025: break;
1434 // // Nether Beam - Serenity
1435 // case 30401: break;
1436 // Extract Gas
1437 case 30427:
1439 // move loot to player inventory and despawn target
1440 if(caster->GetTypeId() ==TYPEID_PLAYER &&
1441 target->GetTypeId() == TYPEID_UNIT &&
1442 ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
1444 Player* player = (Player*)caster;
1445 Creature* creature = (Creature*)target;
1446 // missing lootid has been reported on startup - just return
1447 if (!creature->GetCreatureInfo()->SkinLootId)
1449 return;
1451 Loot *loot = &creature->loot;
1452 loot->clear();
1453 loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL);
1454 for(uint8 i=0;i<loot->items.size();i++)
1456 LootItem *item = loot->LootItemInSlot(i,player);
1457 ItemPosCountVec dest;
1458 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count );
1459 if ( msg == EQUIP_ERR_OK )
1461 Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId);
1463 player->SendNewItem(newitem, uint32(item->count), false, false, true);
1465 else
1466 player->SendEquipError( msg, NULL, NULL );
1468 creature->setDeathState(JUST_DIED);
1469 creature->RemoveCorpse();
1470 creature->SetHealth(0); // just for nice GM-mode view
1472 return;
1473 break;
1475 // Quake
1476 case 30576: trigger_spell_id = 30571; break;
1477 // // Burning Maul
1478 // case 30598: break;
1479 // // Regeneration
1480 // case 30799:
1481 // case 30800:
1482 // case 30801:
1483 // break;
1484 // // Despawn Self - Smoke cloud
1485 // case 31269: break;
1486 // // Time Rift Periodic
1487 // case 31320: break;
1488 // // Corrupt Medivh
1489 // case 31326: break;
1490 // Doom
1491 case 31347:
1493 m_target->CastSpell(m_target,31350,true);
1494 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
1495 return;
1497 // Spellcloth
1498 case 31373:
1500 // Summon Elemental after create item
1501 caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
1502 return;
1504 // // Bloodmyst Tesla
1505 // case 31611: break;
1506 // // Doomfire
1507 // case 31944: break;
1508 // // Teleport Test
1509 // case 32236: break;
1510 // // Earthquake
1511 // case 32686: break;
1512 // // Possess
1513 // case 33401: break;
1514 // // Draw Shadows
1515 // case 33563: break;
1516 // // Murmur's Touch
1517 // case 33711: break;
1518 // Flame Quills
1519 case 34229:
1521 // cast 24 spells 34269-34289, 34314-34316
1522 for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
1523 caster->CastSpell(m_target,spell_id,true);
1524 for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
1525 caster->CastSpell(m_target,spell_id,true);
1526 return;
1528 // // Gravity Lapse
1529 // case 34480: break;
1530 // // Tornado
1531 // case 34683: break;
1532 // // Frostbite Rotate
1533 // case 34748: break;
1534 // // Arcane Flurry
1535 // case 34821: break;
1536 // // Interrupt Shutdown
1537 // case 35016: break;
1538 // // Interrupt Shutdown
1539 // case 35176: break;
1540 // // Inferno
1541 // case 35268: break;
1542 // // Salaadin's Tesla
1543 // case 35515: break;
1544 // // Ethereal Channel (Red)
1545 // case 35518: break;
1546 // // Nether Vapor
1547 // case 35879: break;
1548 // // Dark Portal Storm
1549 // case 36018: break;
1550 // // Burning Maul
1551 // case 36056: break;
1552 // // Living Grove Defender Lifespan
1553 // case 36061: break;
1554 // // Professor Dabiri Talks
1555 // case 36064: break;
1556 // // Kael Gaining Power
1557 // case 36091: break;
1558 // // They Must Burn Bomb Aura
1559 // case 36344: break;
1560 // // They Must Burn Bomb Aura (self)
1561 // case 36350: break;
1562 // // Stolen Ravenous Ravager Egg
1563 // case 36401: break;
1564 // // Activated Cannon
1565 // case 36410: break;
1566 // // Stolen Ravenous Ravager Egg
1567 // case 36418: break;
1568 // // Enchanted Weapons
1569 // case 36510: break;
1570 // // Cursed Scarab Periodic
1571 // case 36556: break;
1572 // // Cursed Scarab Despawn Periodic
1573 // case 36561: break;
1574 // // Vision Guide
1575 // case 36573: break;
1576 // // Cannon Charging (platform)
1577 // case 36785: break;
1578 // // Cannon Charging (self)
1579 // case 36860: break;
1580 // Remote Toy
1581 case 37027: trigger_spell_id = 37029; break;
1582 // // Mark of Death
1583 // case 37125: break;
1584 // // Arcane Flurry
1585 // case 37268: break;
1586 // // Spout
1587 // case 37429: break;
1588 // // Spout
1589 // case 37430: break;
1590 // // Karazhan - Chess NPC AI, Snapshot timer
1591 // case 37440: break;
1592 // // Karazhan - Chess NPC AI, action timer
1593 // case 37504: break;
1594 // // Karazhan - Chess: Is Square OCCUPIED aura (DND)
1595 // case 39400: break;
1596 // // Banish
1597 // case 37546: break;
1598 // // Shriveling Gaze
1599 // case 37589: break;
1600 // // Fake Aggro Radius (2 yd)
1601 // case 37815: break;
1602 // // Corrupt Medivh
1603 // case 37853: break;
1604 // Eye of Grillok
1605 case 38495:
1607 m_target->CastSpell(m_target, 38530, true);
1608 return;
1610 // Absorb Eye of Grillok (Zezzak's Shard)
1611 case 38554:
1613 if(m_target->GetTypeId() != TYPEID_UNIT)
1614 return;
1616 caster->CastSpell(caster, 38495, true);
1618 Creature* creatureTarget = (Creature*)m_target;
1620 creatureTarget->setDeathState(JUST_DIED);
1621 creatureTarget->RemoveCorpse();
1622 creatureTarget->SetHealth(0); // just for nice GM-mode view
1623 return;
1625 // // Magic Sucker Device timer
1626 // case 38672: break;
1627 // // Tomb Guarding Charging
1628 // case 38751: break;
1629 // // Murmur's Touch
1630 // case 38794: break;
1631 // // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item)
1632 // case 39105: break;
1633 // // Drain World Tree Visual
1634 // case 39140: break;
1635 // // Quest - Dustin's Undead Dragon Visual aura
1636 // case 39259: break;
1637 // // Hellfire - The Exorcism, Jules releases darkness, aura
1638 // case 39306: break;
1639 // // Inferno
1640 // case 39346: break;
1641 // // Enchanted Weapons
1642 // case 39489: break;
1643 // // Shadow Bolt Whirl
1644 // case 39630: break;
1645 // // Shadow Bolt Whirl
1646 // case 39634: break;
1647 // // Shadow Inferno
1648 // case 39645: break;
1649 // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
1650 case 39857: trigger_spell_id = 39856; break;
1651 // // Soulgrinder Ritual Visual (Smashed)
1652 // case 39974: break;
1653 // // Simon Game Pre-game timer
1654 // case 40041: break;
1655 // // Knockdown Fel Cannon: The Aggro Check Aura
1656 // case 40113: break;
1657 // // Spirit Lance
1658 // case 40157: break;
1659 // // Demon Transform 2
1660 // case 40398: break;
1661 // // Demon Transform 1
1662 // case 40511: break;
1663 // // Ancient Flames
1664 // case 40657: break;
1665 // // Ethereal Ring Cannon: Cannon Aura
1666 // case 40734: break;
1667 // // Cage Trap
1668 // case 40760: break;
1669 // // Random Periodic
1670 // case 40867: break;
1671 // // Prismatic Shield
1672 // case 40879: break;
1673 // // Aura of Desire
1674 // case 41350: break;
1675 // // Dementia
1676 // case 41404: break;
1677 // // Chaos Form
1678 // case 41629: break;
1679 // // Alert Drums
1680 // case 42177: break;
1681 // // Spout
1682 // case 42581: break;
1683 // // Spout
1684 // case 42582: break;
1685 // // Return to the Spirit Realm
1686 // case 44035: break;
1687 // // Curse of Boundless Agony
1688 // case 45050: break;
1689 // // Earthquake
1690 // case 46240: break;
1691 // Personalized Weather
1692 case 46736: trigger_spell_id = 46737; break;
1693 // // Stay Submerged
1694 // case 46981: break;
1695 // // Dragonblight Ram
1696 // case 47015: break;
1697 // // Party G.R.E.N.A.D.E.
1698 // case 51510: break;
1699 default:
1700 break;
1702 break;
1704 case SPELLFAMILY_MAGE:
1706 switch(auraId)
1708 // Invisibility
1709 case 66:
1711 if(!m_duration)
1712 m_target->CastSpell(m_target, 32612, true, NULL, this);
1713 return;
1715 default:
1716 break;
1718 break;
1720 // case SPELLFAMILY_WARRIOR:
1721 // {
1722 // switch(auraId)
1723 // {
1724 // // Wild Magic
1725 // case 23410: break;
1726 // // Corrupted Totems
1727 // case 23425: break;
1728 // default:
1729 // break;
1730 // }
1731 // break;
1732 // }
1733 // case SPELLFAMILY_PRIEST:
1734 // {
1735 // switch(auraId)
1736 // {
1737 // // Blue Beam
1738 // case 32930: break;
1739 // // Fury of the Dreghood Elders
1740 // case 35460: break;
1741 // default:
1742 // break;
1743 // }
1744 // break;
1745 // }
1746 case SPELLFAMILY_DRUID:
1748 switch(auraId)
1750 // Cat Form
1751 // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while
1752 case 768:
1753 return;
1754 // Frenzied Regeneration
1755 case 22842:
1756 case 22895:
1757 case 22896:
1758 case 26999:
1760 int32 LifePerRage = GetModifier()->m_amount;
1762 int32 lRage = m_target->GetPower(POWER_RAGE);
1763 if(lRage > 100) // rage stored as rage*10
1764 lRage = 100;
1765 m_target->ModifyPower(POWER_RAGE, -lRage);
1766 int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10);
1767 m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this);
1768 return;
1770 default:
1771 break;
1773 break;
1776 // case SPELLFAMILY_HUNTER:
1777 // {
1778 // switch(auraId)
1779 // {
1780 // //Frost Trap Aura
1781 // case 13810:
1782 // return;
1783 // //Rizzle's Frost Trap
1784 // case 39900:
1785 // return;
1786 // // Tame spells
1787 // case 19597: // Tame Ice Claw Bear
1788 // case 19676: // Tame Snow Leopard
1789 // case 19677: // Tame Large Crag Boar
1790 // case 19678: // Tame Adult Plainstrider
1791 // case 19679: // Tame Prairie Stalker
1792 // case 19680: // Tame Swoop
1793 // case 19681: // Tame Dire Mottled Boar
1794 // case 19682: // Tame Surf Crawler
1795 // case 19683: // Tame Armored Scorpid
1796 // case 19684: // Tame Webwood Lurker
1797 // case 19685: // Tame Nightsaber Stalker
1798 // case 19686: // Tame Strigid Screecher
1799 // case 30100: // Tame Crazed Dragonhawk
1800 // case 30103: // Tame Elder Springpaw
1801 // case 30104: // Tame Mistbat
1802 // case 30647: // Tame Barbed Crawler
1803 // case 30648: // Tame Greater Timberstrider
1804 // case 30652: // Tame Nightstalker
1805 // return;
1806 // default:
1807 // break;
1808 // }
1809 // break;
1810 // }
1811 case SPELLFAMILY_SHAMAN:
1813 switch(auraId)
1815 // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
1816 case 28820:
1818 // Need remove self if Lightning Shield not active
1819 Unit::AuraMap const& auras = target->GetAuras();
1820 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1822 SpellEntry const* spell = itr->second->GetSpellProto();
1823 if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
1824 spell->SpellFamilyFlags & 0x0000000000000400L)
1825 return;
1827 target->RemoveAurasDueToSpell(28820);
1828 return;
1830 // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
1831 case 38443:
1833 bool all = true;
1834 for(int i = 0; i < MAX_TOTEM; ++i)
1836 if(!caster->m_TotemSlot[i])
1838 all = false;
1839 break;
1843 if(all)
1844 caster->CastSpell(caster,38437,true);
1845 else
1846 caster->RemoveAurasDueToSpell(38437);
1847 return;
1849 default:
1850 break;
1852 break;
1854 default:
1855 break;
1857 // Reget trigger spell proto
1858 triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1859 if(triggeredSpellInfo == NULL)
1861 sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
1862 return;
1865 else
1867 // Spell exist but require custom code
1868 switch(auraId)
1870 // Curse of Idiocy
1871 case 1010:
1873 // TODO: spell casted by result in correct way mostly
1874 // BUT:
1875 // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell
1876 // but must show affect apply like item casting
1877 // 2) maybe aura must be replace by new with accumulative stat mods instead stacking
1879 // prevent cast by triggered auras
1880 if(m_caster_guid == m_target->GetGUID())
1881 return;
1883 // stop triggering after each affected stats lost > 90
1884 int32 intelectLoss = 0;
1885 int32 spiritLoss = 0;
1887 Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT);
1888 for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
1890 if ((*i)->GetId() == 1010)
1892 switch((*i)->GetModifier()->m_miscvalue)
1894 case STAT_INTELLECT: intelectLoss += (*i)->GetModifier()->m_amount; break;
1895 case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
1896 default: break;
1901 if(intelectLoss <= -90 && spiritLoss <= -90)
1902 return;
1904 caster = target;
1905 originalCasterGUID = 0;
1906 break;
1908 // Mana Tide
1909 case 16191:
1911 caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID);
1912 return;
1916 // All ok cast by default case
1917 Spell *spell = new Spell(caster, triggeredSpellInfo, true, originalCasterGUID );
1919 SpellCastTargets targets;
1920 targets.setUnitTarget( target );
1922 // if spell create dynamic object extract area from it
1923 if(DynamicObject* dynObj = caster->GetDynObject(GetId()))
1924 targets.setDestination(dynObj->GetPositionX(),dynObj->GetPositionY(),dynObj->GetPositionZ());
1926 spell->prepare(&targets, this);
1929 /*********************************************************/
1930 /*** AURA EFFECTS ***/
1931 /*********************************************************/
1933 void Aura::HandleAuraDummy(bool apply, bool Real)
1935 // spells required only Real aura add/remove
1936 if(!Real)
1937 return;
1939 Unit* caster = GetCaster();
1941 // AT APPLY
1942 if(apply)
1944 switch(GetId())
1946 case 1515: // Tame beast
1947 // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
1948 if( caster && m_target->CanHaveThreatList())
1949 m_target->AddThreat(caster, 10.0f);
1950 return;
1951 case 13139: // net-o-matic
1952 // root to self part of (root_target->charge->root_self sequence
1953 if(caster)
1954 caster->CastSpell(caster,13138,true,NULL,this);
1955 return;
1956 case 39850: // Rocket Blast
1957 if(roll_chance_i(20)) // backfire stun
1958 m_target->CastSpell(m_target, 51581, true, NULL, this);
1959 return;
1960 case 43873: // Headless Horseman Laugh
1961 if(caster->GetTypeId() == TYPEID_PLAYER)
1962 ((Player*)caster)->PlaySound(11965, false);
1963 return;
1964 case 46354: // Blood Elf Illusion
1965 if(caster)
1967 switch(caster->getGender())
1969 case GENDER_FEMALE:
1970 caster->CastSpell(m_target,46356,true,NULL,this);
1971 break;
1972 case GENDER_MALE:
1973 caster->CastSpell(m_target,46355,true,NULL,this);
1974 break;
1975 default:
1976 break;
1979 return;
1980 case 46699: // Requires No Ammo
1981 if(m_target->GetTypeId()==TYPEID_PLAYER)
1982 ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
1983 return;
1986 // Earth Shield
1987 if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
1989 // prevent double apply bonuses
1990 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
1991 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
1992 return;
1995 // AT REMOVE
1996 else
1998 if( m_target->GetTypeId() == TYPEID_PLAYER &&
1999 ( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
2000 ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
2002 // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
2003 ((Player*)m_target)->SetFarSight(NULL);
2004 WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
2005 ((Player*)m_target)->GetSession()->SendPacket(&data);
2006 return;
2009 if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive())
2011 uint32 finalSpelId = 0;
2012 switch(GetId())
2014 case 19548: finalSpelId = 19597; break;
2015 case 19674: finalSpelId = 19677; break;
2016 case 19687: finalSpelId = 19676; break;
2017 case 19688: finalSpelId = 19678; break;
2018 case 19689: finalSpelId = 19679; break;
2019 case 19692: finalSpelId = 19680; break;
2020 case 19693: finalSpelId = 19684; break;
2021 case 19694: finalSpelId = 19681; break;
2022 case 19696: finalSpelId = 19682; break;
2023 case 19697: finalSpelId = 19683; break;
2024 case 19699: finalSpelId = 19685; break;
2025 case 19700: finalSpelId = 19686; break;
2026 case 30646: finalSpelId = 30647; break;
2027 case 30653: finalSpelId = 30648; break;
2028 case 30654: finalSpelId = 30652; break;
2029 case 30099: finalSpelId = 30100; break;
2030 case 30102: finalSpelId = 30103; break;
2031 case 30105: finalSpelId = 30104; break;
2034 if(finalSpelId)
2035 caster->CastSpell(m_target,finalSpelId,true,NULL,this);
2036 return;
2039 // Waiting to Resurrect
2040 if(GetId()==2584)
2042 // Waiting to resurrect spell cancel, we must remove player from resurrect queue
2043 if(m_target->GetTypeId() == TYPEID_PLAYER)
2044 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
2045 bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
2046 return;
2049 // Dark Fiend
2050 if(GetId()==45934)
2052 // Kill target if dispelled
2053 if (m_removeMode==AURA_REMOVE_BY_DISPEL)
2054 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2055 return;
2058 // Burning Winds
2059 if(GetId()==46308) // casted only at creatures at spawn
2061 m_target->CastSpell(m_target,47287,true,NULL,this);
2062 return;
2066 // AT APPLY & REMOVE
2068 switch(m_spellProto->SpellFamilyName)
2070 case SPELLFAMILY_GENERIC:
2072 // Unstable Power
2073 if( GetId()==24658 )
2075 uint32 spellId = 24659;
2076 if (apply)
2078 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2079 if (!spell)
2080 return;
2081 for (int i=0; i < spell->StackAmount; ++i)
2082 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2083 return;
2085 m_target->RemoveAurasDueToSpell(spellId);
2086 return;
2088 // Restless Strength
2089 if( GetId()==24661 )
2091 uint32 spellId = 24662;
2092 if (apply)
2094 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2095 if (!spell)
2096 return;
2097 for (int i=0; i < spell->StackAmount; ++i)
2098 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2099 return;
2101 m_target->RemoveAurasDueToSpell(spellId);
2102 return;
2104 // Victorious
2105 if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
2107 m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
2108 return;
2110 //Summon Fire Elemental
2111 if (GetId() == 40133 && caster)
2113 Unit *owner = caster->GetOwner();
2114 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2116 if(apply)
2117 owner->CastSpell(owner,8985,true);
2118 else
2119 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2121 return;
2124 //Summon Earth Elemental
2125 if (GetId() == 40132 && caster)
2127 Unit *owner = caster->GetOwner();
2128 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2130 if(apply)
2131 owner->CastSpell(owner,19704,true);
2132 else
2133 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2135 return;
2137 break;
2139 case SPELLFAMILY_MAGE:
2141 // Hypothermia
2142 if( GetId()==41425 )
2144 m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply);
2145 return;
2147 break;
2149 case SPELLFAMILY_DRUID:
2151 // Lifebloom
2152 if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
2154 if ( apply )
2156 if ( caster )
2157 // prevent double apply bonuses
2158 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2159 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2161 else
2163 // Final heal only on dispelled or duration end
2164 if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
2165 return;
2167 // have a look if there is still some other Lifebloom dummy aura
2168 Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2169 for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); itr++)
2170 if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2171 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
2172 return;
2174 // final heal
2175 m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
2177 return;
2180 // Predatory Strikes
2181 if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
2183 ((Player*)m_target)->UpdateAttackPowerAndDamage();
2184 return;
2186 // Idol of the Emerald Queen
2187 if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
2189 if(apply)
2191 SpellModifier *mod = new SpellModifier;
2192 mod->op = SPELLMOD_DOT;
2193 mod->value = m_modifier.m_amount/7;
2194 mod->type = SPELLMOD_FLAT;
2195 mod->spellId = GetId();
2196 mod->effectId = m_effIndex;
2197 mod->lastAffected = NULL;
2198 mod->mask = 0x001000000000LL;
2199 mod->charges = 0;
2201 m_spellmod = mod;
2204 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2205 return;
2207 break;
2209 case SPELLFAMILY_HUNTER:
2211 // Improved Aspect of the Viper
2212 if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
2214 if(apply)
2216 // + effect value for Aspect of the Viper
2217 SpellModifier *mod = new SpellModifier;
2218 mod->op = SPELLMOD_EFFECT1;
2219 mod->value = m_modifier.m_amount;
2220 mod->type = SPELLMOD_FLAT;
2221 mod->spellId = GetId();
2222 mod->effectId = m_effIndex;
2223 mod->lastAffected = NULL;
2224 mod->mask = 0x4000000000000LL;
2225 mod->charges = 0;
2227 m_spellmod = mod;
2230 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2231 return;
2233 break;
2235 case SPELLFAMILY_SHAMAN:
2237 // Improved Weapon Totems
2238 if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
2240 if(apply)
2242 SpellModifier *mod = new SpellModifier;
2243 mod->op = SPELLMOD_EFFECT1;
2244 mod->value = m_modifier.m_amount;
2245 mod->type = SPELLMOD_PCT;
2246 mod->spellId = GetId();
2247 mod->effectId = m_effIndex;
2248 mod->lastAffected = NULL;
2249 switch (m_effIndex)
2251 case 0:
2252 mod->mask = 0x00200000000LL; // Windfury Totem
2253 break;
2254 case 1:
2255 mod->mask = 0x00400000000LL; // Flametongue Totem
2256 break;
2258 mod->charges = 0;
2260 m_spellmod = mod;
2263 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2264 return;
2266 break;
2270 // pet auras
2271 if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
2273 if(apply)
2274 m_target->AddPetAura(petSpell);
2275 else
2276 m_target->RemovePetAura(petSpell);
2277 return;
2281 void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
2283 // spells required only Real aura add/remove
2284 if(!Real)
2285 return;
2287 SpellEntry const*spell = GetSpellProto();
2288 switch( spell->SpellFamilyName)
2290 case SPELLFAMILY_ROGUE:
2292 // Master of Subtlety
2293 if (spell->Id==31666 && !apply && Real)
2295 m_target->RemoveAurasDueToSpell(31665);
2296 break;
2298 break;
2300 case SPELLFAMILY_HUNTER:
2302 // Aspect of the Viper
2303 if (spell->SpellFamilyFlags&0x0004000000000000LL)
2305 // Update regen on remove
2306 if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
2307 ((Player*)m_target)->UpdateManaRegen();
2308 break;
2310 break;
2314 m_isPeriodic = apply;
2317 void Aura::HandleAuraMounted(bool apply, bool Real)
2319 // only at real add/remove aura
2320 if(!Real)
2321 return;
2323 if(apply)
2325 CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2326 if(!ci)
2328 sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
2329 return;
2332 uint32 team = 0;
2333 if (m_target->GetTypeId()==TYPEID_PLAYER)
2334 team = ((Player*)m_target)->GetTeam();
2336 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2337 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2338 if (minfo)
2339 display_id = minfo->modelid;
2341 m_target->Mount(display_id);
2343 else
2345 m_target->Unmount();
2349 void Aura::HandleAuraWaterWalk(bool apply, bool Real)
2351 // only at real add/remove aura
2352 if(!Real)
2353 return;
2355 WorldPacket data;
2356 if(apply)
2357 data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
2358 else
2359 data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
2360 data.append(m_target->GetPackGUID());
2361 data << uint32(0);
2362 m_target->SendMessageToSet(&data,true);
2365 void Aura::HandleAuraFeatherFall(bool apply, bool Real)
2367 // only at real add/remove aura
2368 if(!Real)
2369 return;
2371 WorldPacket data;
2372 if(apply)
2373 data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
2374 else
2375 data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
2376 data.append(m_target->GetPackGUID());
2377 data << (uint32)0;
2378 m_target->SendMessageToSet(&data,true);
2381 void Aura::HandleAuraHover(bool apply, bool Real)
2383 // only at real add/remove aura
2384 if(!Real)
2385 return;
2387 WorldPacket data;
2388 if(apply)
2389 data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
2390 else
2391 data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
2392 data.append(m_target->GetPackGUID());
2393 data << uint32(0);
2394 m_target->SendMessageToSet(&data,true);
2397 void Aura::HandleWaterBreathing(bool apply, bool Real)
2399 if(apply)
2400 m_target->waterbreath = true;
2401 else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
2403 m_target->waterbreath = false;
2405 // update for enable timer in case not moving target
2406 if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
2408 ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
2409 ((Player*)m_target)->HandleDrowning();
2414 void Aura::HandleAuraModShapeshift(bool apply, bool Real)
2416 if(!Real)
2417 return;
2419 uint32 modelid = 0;
2420 Powers PowerType = POWER_MANA;
2421 ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
2422 switch(form)
2424 case FORM_CAT:
2425 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2426 modelid = 892;
2427 else
2428 modelid = 8571;
2429 PowerType = POWER_ENERGY;
2430 break;
2431 case FORM_TRAVEL:
2432 modelid = 632;
2433 break;
2434 case FORM_AQUA:
2435 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2436 modelid = 2428;
2437 else
2438 modelid = 2428;
2439 break;
2440 case FORM_BEAR:
2441 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2442 modelid = 2281;
2443 else
2444 modelid = 2289;
2445 PowerType = POWER_RAGE;
2446 break;
2447 case FORM_GHOUL:
2448 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2449 modelid = 10045;
2450 break;
2451 case FORM_DIREBEAR:
2452 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2453 modelid = 2281;
2454 else
2455 modelid = 2289;
2456 PowerType = POWER_RAGE;
2457 break;
2458 case FORM_CREATUREBEAR:
2459 modelid = 902;
2460 break;
2461 case FORM_GHOSTWOLF:
2462 modelid = 4613;
2463 break;
2464 case FORM_FLIGHT:
2465 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2466 modelid = 20857;
2467 else
2468 modelid = 20872;
2469 break;
2470 case FORM_MOONKIN:
2471 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2472 modelid = 15374;
2473 else
2474 modelid = 15375;
2475 break;
2476 case FORM_FLIGHT_EPIC:
2477 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2478 modelid = 21243;
2479 else
2480 modelid = 21244;
2481 break;
2482 case FORM_AMBIENT:
2483 case FORM_SHADOW:
2484 case FORM_STEALTH:
2485 break;
2486 case FORM_TREE:
2487 modelid = 864;
2488 break;
2489 case FORM_BATTLESTANCE:
2490 case FORM_BERSERKERSTANCE:
2491 case FORM_DEFENSIVESTANCE:
2492 PowerType = POWER_RAGE;
2493 break;
2494 case FORM_SPIRITOFREDEMPTION:
2495 modelid = 16031;
2496 break;
2497 default:
2498 sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
2501 // remove polymorph before changing display id to keep new display id
2502 switch ( form )
2504 case FORM_CAT:
2505 case FORM_TREE:
2506 case FORM_TRAVEL:
2507 case FORM_AQUA:
2508 case FORM_BEAR:
2509 case FORM_DIREBEAR:
2510 case FORM_FLIGHT_EPIC:
2511 case FORM_FLIGHT:
2512 case FORM_MOONKIN:
2513 // remove movement affects
2514 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2515 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2517 // and polymorphic affects
2518 if(m_target->IsPolymorphed())
2519 m_target->RemoveAurasDueToSpell(m_target->getTransForm());
2520 break;
2521 default:
2522 break;
2525 if(apply)
2527 // remove other shapeshift before applying a new one
2528 if(m_target->m_ShapeShiftFormSpellId)
2529 m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
2531 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
2533 if(modelid > 0)
2534 m_target->SetDisplayId(modelid);
2536 if(PowerType != POWER_MANA)
2538 // reset power to default values only at power change
2539 if(m_target->getPowerType()!=PowerType)
2540 m_target->setPowerType(PowerType);
2542 switch(form)
2544 case FORM_CAT:
2545 case FORM_BEAR:
2546 case FORM_DIREBEAR:
2548 // get furor proc chance
2549 uint32 FurorChance = 0;
2550 Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2551 for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
2553 if ((*i)->GetSpellProto()->SpellIconID == 238)
2555 FurorChance = (*i)->GetModifier()->m_amount;
2556 break;
2560 if (m_modifier.m_miscvalue == FORM_CAT)
2562 m_target->SetPower(POWER_ENERGY,0);
2563 if(urand(1,100) <= FurorChance)
2564 m_target->CastSpell(m_target,17099,true,NULL,this);
2566 else
2568 m_target->SetPower(POWER_RAGE,0);
2569 if(urand(1,100) <= FurorChance)
2570 m_target->CastSpell(m_target,17057,true,NULL,this);
2572 break;
2574 case FORM_BATTLESTANCE:
2575 case FORM_DEFENSIVESTANCE:
2576 case FORM_BERSERKERSTANCE:
2578 uint32 Rage_val = 0;
2579 // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
2580 if(m_target->GetTypeId() == TYPEID_PLAYER)
2582 PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
2583 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2585 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
2586 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2587 if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
2588 Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
2592 if (m_target->GetPower(POWER_RAGE) > Rage_val)
2593 m_target->SetPower(POWER_RAGE,Rage_val);
2594 break;
2596 default:
2597 break;
2601 m_target->m_ShapeShiftFormSpellId = GetId();
2602 m_target->m_form = form;
2604 else
2606 if(modelid > 0)
2607 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2608 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
2609 if(m_target->getClass() == CLASS_DRUID)
2610 m_target->setPowerType(POWER_MANA);
2611 m_target->m_ShapeShiftFormSpellId = 0;
2612 m_target->m_form = FORM_NONE;
2614 switch(form)
2616 // Nordrassil Harness - bonus
2617 case FORM_BEAR:
2618 case FORM_DIREBEAR:
2619 case FORM_CAT:
2621 if(Aura* dummy = m_target->GetDummyAura(37315) )
2622 m_target->CastSpell(m_target,37316,true,NULL,dummy);
2623 break;
2625 // Nordrassil Regalia - bonus
2626 case FORM_MOONKIN:
2628 if(Aura* dummy = m_target->GetDummyAura(37324) )
2629 m_target->CastSpell(m_target,37325,true,NULL,dummy);
2630 break;
2635 // adding/removing linked auras
2636 // add/remove the shapeshift aura's boosts
2637 HandleShapeshiftBoosts(apply);
2639 if(m_target->GetTypeId()==TYPEID_PLAYER)
2640 ((Player*)m_target)->InitDataForForm();
2643 void Aura::HandleAuraTransform(bool apply, bool Real)
2645 if (apply)
2647 // special case (spell specific functionality)
2648 if(m_modifier.m_miscvalue==0)
2650 // player applied only
2651 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2652 return;
2654 switch(GetId())
2656 // Orb of Deception
2657 case 16739:
2659 uint32 orb_model = m_target->GetNativeDisplayId();
2660 switch(orb_model)
2662 // Troll Female
2663 case 1479: m_target->SetDisplayId(10134); break;
2664 // Troll Male
2665 case 1478: m_target->SetDisplayId(10135); break;
2666 // Tauren Male
2667 case 59: m_target->SetDisplayId(10136); break;
2668 // Human Male
2669 case 49: m_target->SetDisplayId(10137); break;
2670 // Human Female
2671 case 50: m_target->SetDisplayId(10138); break;
2672 // Orc Male
2673 case 51: m_target->SetDisplayId(10139); break;
2674 // Orc Female
2675 case 52: m_target->SetDisplayId(10140); break;
2676 // Dwarf Male
2677 case 53: m_target->SetDisplayId(10141); break;
2678 // Dwarf Female
2679 case 54: m_target->SetDisplayId(10142); break;
2680 // NightElf Male
2681 case 55: m_target->SetDisplayId(10143); break;
2682 // NightElf Female
2683 case 56: m_target->SetDisplayId(10144); break;
2684 // Undead Female
2685 case 58: m_target->SetDisplayId(10145); break;
2686 // Undead Male
2687 case 57: m_target->SetDisplayId(10146); break;
2688 // Tauren Female
2689 case 60: m_target->SetDisplayId(10147); break;
2690 // Gnome Male
2691 case 1563: m_target->SetDisplayId(10148); break;
2692 // Gnome Female
2693 case 1564: m_target->SetDisplayId(10149); break;
2694 // BloodElf Female
2695 case 15475: m_target->SetDisplayId(17830); break;
2696 // BloodElf Male
2697 case 15476: m_target->SetDisplayId(17829); break;
2698 // Dranei Female
2699 case 16126: m_target->SetDisplayId(17828); break;
2700 // Dranei Male
2701 case 16125: m_target->SetDisplayId(17827); break;
2702 default: break;
2704 break;
2706 // Murloc costume
2707 case 42365: m_target->SetDisplayId(21723); break;
2708 default: break;
2711 else
2713 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2714 if(!ci)
2716 //pig pink ^_^
2717 m_target->SetDisplayId(16358);
2718 sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
2720 else
2722 // Will use the default model here
2723 m_target->SetDisplayId(ci->DisplayID_A);
2725 // Dragonmaw Illusion (set mount model also)
2726 if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
2727 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
2729 m_target->setTransForm(GetId());
2732 // polymorph case
2733 if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
2735 // for players, start regeneration after 1s (in polymorph fast regeneration case)
2736 // only if caster is Player (after patch 2.4.2)
2737 if(IS_PLAYER_GUID(GetCasterGUID()) )
2738 ((Player*)m_target)->setRegenTimer(1000);
2740 //dismount polymorphed target (after patch 2.4.2)
2741 if (m_target->IsMounted())
2742 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2745 else
2747 Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
2748 if(otherTransforms.empty())
2750 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2751 m_target->setTransForm(0);
2753 else
2755 // look for other transform auras
2756 Aura* handledAura = *otherTransforms.begin();
2757 for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
2759 // negative auras are preferred
2760 if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
2762 handledAura = *i;
2763 break;
2766 handledAura->ApplyModifier(true);
2769 // Dragonmaw Illusion (restore mount model)
2770 if(GetId()==42016 && m_target->GetMountID()==16314)
2772 if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
2774 uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
2775 if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
2777 uint32 team = 0;
2778 if (m_target->GetTypeId()==TYPEID_PLAYER)
2779 team = ((Player*)m_target)->GetTeam();
2781 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2782 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2783 if (minfo)
2784 display_id = minfo->modelid;
2786 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
2793 void Aura::HandleForceReaction(bool apply, bool Real)
2795 if(m_target->GetTypeId() != TYPEID_PLAYER)
2796 return;
2798 if(!Real)
2799 return;
2801 Player* player = (Player*)m_target;
2803 uint32 faction_id = m_modifier.m_miscvalue;
2804 uint32 faction_rank = m_modifier.m_amount;
2806 if(apply)
2807 player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
2808 else
2809 player->m_forcedReactions.erase(faction_id);
2811 WorldPacket data;
2812 data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
2813 data << uint32(player->m_forcedReactions.size());
2814 for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
2816 data << uint32(itr->first); // faction_id (Faction.dbc)
2817 data << uint32(itr->second); // reputation rank
2819 player->SendDirectMessage(&data);
2822 void Aura::HandleAuraModSkill(bool apply, bool Real)
2824 if(m_target->GetTypeId() != TYPEID_PLAYER)
2825 return;
2827 uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
2828 int32 points = GetModifier()->m_amount;
2830 ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
2831 if(prot == SKILL_DEFENSE)
2832 ((Player*)m_target)->UpdateDefenseBonusesMod();
2835 void Aura::HandleChannelDeathItem(bool apply, bool Real)
2837 if(Real && !apply)
2839 Unit* caster = GetCaster();
2840 Unit* victim = GetTarget();
2841 if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
2842 return;
2844 SpellEntry const *spellInfo = GetSpellProto();
2845 if(spellInfo->EffectItemType[m_effIndex] == 0)
2846 return;
2848 // Soul Shard only from non-grey units
2849 if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
2850 (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
2851 victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
2852 return;
2853 ItemPosCountVec dest;
2854 uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
2855 if( msg != EQUIP_ERR_OK )
2857 ((Player*)caster)->SendEquipError( msg, NULL, NULL );
2858 return;
2861 Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
2862 ((Player*)caster)->SendNewItem(newitem, 1, true, false);
2866 void Aura::HandleBindSight(bool apply, bool Real)
2868 Unit* caster = GetCaster();
2869 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2870 return;
2872 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2875 void Aura::HandleFarSight(bool apply, bool Real)
2877 Unit* caster = GetCaster();
2878 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2879 return;
2881 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2884 void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
2886 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2887 return;
2889 if(apply)
2890 m_target->RemoveNoStackAurasDueToAura(this);
2891 m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
2894 void Aura::HandleAuraTrackResources(bool apply, bool Real)
2896 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2897 return;
2899 if(apply)
2900 m_target->RemoveNoStackAurasDueToAura(this);
2901 m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
2904 void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
2906 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2907 return;
2909 if(apply)
2910 m_target->RemoveNoStackAurasDueToAura(this);
2912 m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
2915 void Aura::HandleAuraModScale(bool apply, bool Real)
2917 m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
2920 void Aura::HandleModPossess(bool apply, bool Real)
2922 if(!Real)
2923 return;
2925 if(m_target->getLevel() > m_modifier.m_amount)
2926 return;
2928 // not possess yourself
2929 if(GetCasterGUID() == m_target->GetGUID())
2930 return;
2932 Unit* caster = GetCaster();
2933 if(!caster)
2934 return;
2936 if( apply )
2938 m_target->SetCharmerGUID(GetCasterGUID());
2939 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
2940 caster->SetCharm(m_target);
2942 m_target->CombatStop();
2943 m_target->DeleteThreatList();
2944 if(m_target->GetTypeId() == TYPEID_UNIT)
2946 m_target->StopMoving();
2947 m_target->GetMotionMaster()->Clear();
2948 m_target->GetMotionMaster()->MoveIdle();
2949 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
2950 charmInfo->InitPossessCreateSpells();
2953 if(caster->GetTypeId() == TYPEID_PLAYER)
2955 ((Player*)caster)->PossessSpellInitialize();
2958 else
2960 m_target->SetCharmerGUID(0);
2962 if(m_target->GetTypeId() == TYPEID_PLAYER)
2963 ((Player*)m_target)->setFactionForRace(m_target->getRace());
2964 else if(m_target->GetTypeId() == TYPEID_UNIT)
2966 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
2967 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
2970 caster->SetCharm(0);
2972 if(caster->GetTypeId() == TYPEID_PLAYER)
2974 WorldPacket data(SMSG_PET_SPELLS, 8);
2975 data << uint64(0);
2976 data << uint32(0);
2977 ((Player*)caster)->GetSession()->SendPacket(&data);
2979 if(m_target->GetTypeId() == TYPEID_UNIT)
2981 ((Creature*)m_target)->AIM_Initialize();
2983 if (((Creature*)m_target)->AI())
2984 ((Creature*)m_target)->AI()->AttackStart(caster);
2987 if(caster->GetTypeId() == TYPEID_PLAYER)
2988 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2991 void Aura::HandleModPossessPet(bool apply, bool Real)
2993 if(!Real)
2994 return;
2996 Unit* caster = GetCaster();
2997 Pet *pet = caster->GetPet();
2998 if(!pet || (pet != m_target) || !caster || (caster->GetTypeId() != TYPEID_PLAYER))
2999 return;
3001 if(apply)
3002 pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
3003 else
3004 pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
3006 ((Player*)caster)->SetFarSight(apply ? pet->GetGUID() : NULL);
3007 ((Player*)caster)->SetCharm(apply ? pet : NULL);
3008 ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0);
3010 if(apply)
3012 pet->StopMoving();
3013 pet->GetMotionMaster()->Clear();
3014 pet->GetMotionMaster()->MoveIdle();
3016 else
3018 pet->AttackStop();
3019 pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
3020 pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
3024 void Aura::HandleModCharm(bool apply, bool Real)
3026 if(!Real)
3027 return;
3029 // not charm yourself
3030 if(GetCasterGUID() == m_target->GetGUID())
3031 return;
3033 Unit* caster = GetCaster();
3034 if(!caster)
3035 return;
3037 if(int32(m_target->getLevel()) <= m_modifier.m_amount)
3039 if( apply )
3041 m_target->SetCharmerGUID(GetCasterGUID());
3042 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
3043 m_target->CastStop(m_target==caster ? GetId() : 0);
3044 caster->SetCharm(m_target);
3046 m_target->CombatStop();
3047 m_target->DeleteThreatList();
3049 if(m_target->GetTypeId() == TYPEID_UNIT)
3051 ((Creature*)m_target)->AIM_Initialize();
3052 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3053 charmInfo->InitCharmCreateSpells();
3054 charmInfo->SetReactState( REACT_DEFENSIVE );
3056 if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
3058 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3059 if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
3061 //to prevent client crash
3062 m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
3063 //just to enable stat window
3064 charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
3065 //if charmed two demons the same session, the 2nd gets the 1st one's name
3066 m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
3071 if(caster->GetTypeId() == TYPEID_PLAYER)
3073 ((Player*)caster)->CharmSpellInitialize();
3076 else
3078 m_target->SetCharmerGUID(0);
3080 if(m_target->GetTypeId() == TYPEID_PLAYER)
3081 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3082 else
3084 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3086 // restore faction
3087 if(((Creature*)m_target)->isPet())
3089 if(Unit* owner = m_target->GetOwner())
3090 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
3091 else if(cinfo)
3092 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3094 else if(cinfo) // normal creature
3095 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3097 // restore UNIT_FIELD_BYTES_0
3098 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
3100 CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
3101 if(cainfo && cainfo->bytes0 != 0)
3102 m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
3103 else
3104 m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
3106 if(m_target->GetCharmInfo())
3107 m_target->GetCharmInfo()->SetPetNumber(0, true);
3108 else
3109 sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
3113 caster->SetCharm(0);
3115 if(caster->GetTypeId() == TYPEID_PLAYER)
3117 WorldPacket data(SMSG_PET_SPELLS, 8);
3118 data << uint64(0);
3119 data << uint32(0);
3120 ((Player*)caster)->GetSession()->SendPacket(&data);
3122 if(m_target->GetTypeId() == TYPEID_UNIT)
3124 ((Creature*)m_target)->AIM_Initialize();
3125 if (((Creature*)m_target)->AI())
3126 ((Creature*)m_target)->AI()->AttackStart(caster);
3132 void Aura::HandleModConfuse(bool apply, bool Real)
3134 if(!Real)
3135 return;
3137 m_target->SetConfused(apply, GetCasterGUID(), GetId());
3140 void Aura::HandleModFear(bool apply, bool Real)
3142 if (!Real)
3143 return;
3145 m_target->SetFeared(apply, GetCasterGUID(), GetId());
3148 void Aura::HandleFeignDeath(bool apply, bool Real)
3150 if(!Real)
3151 return;
3153 if(m_target->GetTypeId() != TYPEID_PLAYER)
3154 return;
3156 if( apply )
3159 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3160 data<<m_target->GetGUID();
3161 data<<uint8(0);
3162 m_target->SendMessageToSet(&data,true);
3164 // blizz like 2.0.x
3165 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3166 // blizz like 2.0.x
3167 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3168 // blizz like 2.0.x
3169 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3171 m_target->addUnitState(UNIT_STAT_DIED);
3172 m_target->CombatStop();
3174 // prevent interrupt message
3175 if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
3176 m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
3177 m_target->InterruptNonMeleeSpells(true);
3178 m_target->getHostilRefManager().deleteReferences();
3180 else
3183 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3184 data<<m_target->GetGUID();
3185 data<<uint8(1);
3186 m_target->SendMessageToSet(&data,true);
3188 // blizz like 2.0.x
3189 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3190 // blizz like 2.0.x
3191 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3192 // blizz like 2.0.x
3193 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3195 m_target->clearUnitState(UNIT_STAT_DIED);
3199 void Aura::HandleAuraModDisarm(bool apply, bool Real)
3201 if(!Real)
3202 return;
3204 if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
3205 return;
3207 // not sure for it's correctness
3208 if(apply)
3209 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3210 else
3211 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3213 // only at real add/remove aura
3214 if (m_target->GetTypeId() != TYPEID_PLAYER)
3215 return;
3217 // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
3218 if (((Player *)m_target)->IsInFeralForm())
3219 return;
3221 if (apply)
3222 m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
3223 else
3224 ((Player *)m_target)->SetRegularAttackTime();
3226 m_target->UpdateDamagePhysical(BASE_ATTACK);
3229 void Aura::HandleAuraModStun(bool apply, bool Real)
3231 if(!Real)
3232 return;
3234 if (apply)
3236 m_target->addUnitState(UNIT_STAT_STUNNED);
3237 m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
3239 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3240 m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
3242 // Creature specific
3243 if(m_target->GetTypeId() != TYPEID_PLAYER)
3244 ((Creature*)m_target)->StopMoving();
3245 else
3246 m_target->SetUnitMovementFlags(0); //Clear movement flags
3248 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
3250 data.append(m_target->GetPackGUID());
3251 data << uint32(0);
3252 m_target->SendMessageToSet(&data,true);
3254 else
3256 // Real remove called after current aura remove from lists, check if other similar auras active
3257 if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
3258 return;
3260 m_target->clearUnitState(UNIT_STAT_STUNNED);
3261 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3263 if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
3265 if(m_target->getVictim() && m_target->isAlive())
3266 m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3268 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
3269 data.append(m_target->GetPackGUID());
3270 data << uint32(0);
3271 m_target->SendMessageToSet(&data,true);
3274 // Wyvern Sting
3275 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
3277 Unit* caster = GetCaster();
3278 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
3279 return;
3281 uint32 spell_id = 0;
3283 switch(GetId())
3285 case 19386: spell_id = 24131; break;
3286 case 24132: spell_id = 24134; break;
3287 case 24133: spell_id = 24135; break;
3288 case 27068: spell_id = 27069; break;
3289 default:
3290 sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
3291 return;
3294 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
3296 if(!spellInfo)
3297 return;
3299 caster->CastSpell(m_target,spellInfo,true,NULL,this);
3300 return;
3305 void Aura::HandleModStealth(bool apply, bool Real)
3307 if(apply)
3309 // drop flag at stealth in bg
3310 if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
3311 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3312 bg->EventPlayerDroppedFlag((Player*)m_target);
3314 // only at real aura add
3315 if(Real)
3317 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
3318 if(m_target->GetTypeId()==TYPEID_PLAYER)
3319 m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
3321 // apply only if not in GM invisibility (and overwrite invisibility state)
3322 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3324 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3325 m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
3328 // for RACE_NIGHTELF stealth
3329 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3330 m_target->CastSpell(m_target, 21009, true, NULL, this);
3333 else
3335 // only at real aura remove
3336 if(Real)
3338 // for RACE_NIGHTELF stealth
3339 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3340 m_target->RemoveAurasDueToSpell(21009);
3342 // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
3343 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
3345 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
3346 if(m_target->GetTypeId()==TYPEID_PLAYER)
3347 m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
3349 // restore invisibility if any
3350 if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
3352 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3353 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3355 else
3356 m_target->SetVisibility(VISIBILITY_ON);
3361 // Master of Subtlety
3362 Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
3363 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
3365 if ((*i)->GetSpellProto()->SpellIconID == 2114)
3367 if (apply)
3369 int32 bp = (*i)->GetModifier()->m_amount;
3370 m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
3372 else
3373 m_target->CastSpell(m_target,31666,true);
3374 break;
3379 void Aura::HandleInvisibility(bool apply, bool Real)
3381 if(apply)
3383 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3385 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3387 // apply glow vision
3388 m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3390 // drop flag at invisible in bg
3391 if(((Player*)m_target)->InBattleGround())
3392 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3393 bg->EventPlayerDroppedFlag((Player*)m_target);
3396 // apply only if not in GM invisibility and not stealth
3397 if(m_target->GetVisibility()==VISIBILITY_ON)
3399 // Aura not added yet but visibility code expect temporary add aura
3400 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3401 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3404 else
3406 // recalculate value at modifier remove (current aura already removed)
3407 m_target->m_invisibilityMask = 0;
3408 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
3409 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3410 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3412 // only at real aura remove and if not have different invisibility auras.
3413 if(Real && m_target->m_invisibilityMask==0)
3415 // remove glow vision
3416 if(m_target->GetTypeId() == TYPEID_PLAYER)
3417 m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3419 // apply only if not in GM invisibility & not stealthed while invisible
3420 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3422 // if have stealth aura then already have stealth visibility
3423 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
3424 m_target->SetVisibility(VISIBILITY_ON);
3430 void Aura::HandleInvisibilityDetect(bool apply, bool Real)
3432 if(apply)
3434 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3436 else
3438 // recalculate value at modifier remove (current aura already removed)
3439 m_target->m_detectInvisibilityMask = 0;
3440 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
3441 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3442 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3444 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3445 ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
3448 void Aura::HandleAuraModRoot(bool apply, bool Real)
3450 // only at real add/remove aura
3451 if(!Real)
3452 return;
3454 uint32 apply_stat = UNIT_STAT_ROOT;
3455 if (apply)
3457 m_target->addUnitState(UNIT_STAT_ROOT);
3458 m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
3459 // probably wrong
3460 m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3462 //Save last orientation
3463 if( m_target->getVictim() )
3464 m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
3466 if(m_target->GetTypeId() == TYPEID_PLAYER)
3468 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
3469 data.append(m_target->GetPackGUID());
3470 data << (uint32)2;
3471 m_target->SendMessageToSet(&data,true);
3473 //Clear unit movement flags
3474 m_target->SetUnitMovementFlags(0);
3476 else
3477 ((Creature *)m_target)->StopMoving();
3479 else
3481 // Real remove called after current aura remove from lists, check if other similar auras active
3482 if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
3483 return;
3485 m_target->clearUnitState(UNIT_STAT_ROOT);
3486 // probably wrong
3487 m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3489 if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
3491 if(m_target->getVictim() && m_target->isAlive())
3492 m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3494 if(m_target->GetTypeId() == TYPEID_PLAYER)
3496 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
3497 data.append(m_target->GetPackGUID());
3498 data << (uint32)2;
3499 m_target->SendMessageToSet(&data,true);
3505 void Aura::HandleAuraModSilence(bool apply, bool Real)
3507 // only at real add/remove aura
3508 if(!Real)
3509 return;
3511 if(apply)
3513 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3514 // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3515 for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
3517 Spell* currentSpell = m_target->m_currentSpells[i];
3518 if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
3520 uint32 state = currentSpell->getState();
3521 // Stop spells on prepare or casting state
3522 if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
3524 currentSpell->cancel();
3525 currentSpell->SetReferencedFromCurrent(false);
3526 m_target->m_currentSpells[i] = NULL;
3531 switch (GetId())
3533 // Arcane Torrent (Energy)
3534 case 25046:
3536 Unit * caster = GetCaster();
3537 if (!caster)
3538 return;
3540 // Search Mana Tap auras on caster
3541 int32 energy = 0;
3542 Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
3543 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3544 if ((*i)->GetId() == 28734)
3545 ++energy;
3546 if (energy)
3548 energy *= 10;
3549 caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true);
3550 caster->RemoveAurasDueToSpell(28734);
3555 else
3557 // Real remove called after current aura remove from lists, check if other similar auras active
3558 if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
3559 return;
3561 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3565 void Aura::HandleModThreat(bool apply, bool Real)
3567 // only at real add/remove aura
3568 if(!Real)
3569 return;
3571 if(!m_target->isAlive())
3572 return;
3574 Unit* caster = GetCaster();
3576 if(!caster || !caster->isAlive())
3577 return;
3579 int level_diff = 0;
3580 int multiplier = 0;
3581 switch (GetId())
3583 // Arcane Shroud
3584 case 26400:
3585 level_diff = m_target->getLevel() - 60;
3586 multiplier = 2;
3587 break;
3588 // The Eye of Diminution
3589 case 28862:
3590 level_diff = m_target->getLevel() - 60;
3591 multiplier = 1;
3592 break;
3594 if (level_diff > 0)
3595 m_modifier.m_amount += multiplier * level_diff;
3597 for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
3599 if(m_modifier.m_miscvalue & int32(1<<x))
3601 if(m_target->GetTypeId() == TYPEID_PLAYER)
3602 ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
3607 void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
3609 // only at real add/remove aura
3610 if(!Real)
3611 return;
3613 if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
3614 return;
3616 Unit* caster = GetCaster();
3618 if(!caster || !caster->isAlive())
3619 return;
3621 float threatMod = 0.0f;
3622 if(apply)
3623 threatMod = float(m_modifier.m_amount);
3624 else
3625 threatMod = float(-m_modifier.m_amount);
3627 m_target->getHostilRefManager().threatAssist(caster, threatMod);
3630 void Aura::HandleModTaunt(bool apply, bool Real)
3632 // only at real add/remove aura
3633 if(!Real)
3634 return;
3636 if(!m_target->isAlive() || !m_target->CanHaveThreatList())
3637 return;
3639 Unit* caster = GetCaster();
3641 if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
3642 return;
3644 if(apply)
3645 m_target->TauntApply(caster);
3646 else
3648 // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
3649 m_target->TauntFadeOut(caster);
3653 /*********************************************************/
3654 /*** MODIFY SPEED ***/
3655 /*********************************************************/
3656 void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real)
3658 // all applied/removed only at real aura add/remove
3659 if(!Real)
3660 return;
3662 m_target->UpdateSpeed(MOVE_RUN, true);
3665 void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real)
3667 // all applied/removed only at real aura add/remove
3668 if(!Real)
3669 return;
3671 m_target->UpdateSpeed(MOVE_RUN, true);
3674 void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
3676 // all applied/removed only at real aura add/remove
3677 if(!Real)
3678 return;
3680 // Enable Fly mode for flying mounts
3681 if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
3683 WorldPacket data;
3684 if(apply)
3685 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
3686 else
3687 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
3688 data.append(m_target->GetPackGUID());
3689 data << uint32(0); // unknown
3690 m_target->SendMessageToSet(&data, true);
3692 //Players on flying mounts must be immune to polymorph
3693 if (m_target->GetTypeId()==TYPEID_PLAYER)
3694 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
3696 // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
3697 if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
3698 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
3701 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3704 void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
3706 // all applied/removed only at real aura add/remove
3707 if(!Real)
3708 return;
3710 m_target->UpdateSpeed(MOVE_SWIM, true);
3713 void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
3715 // all applied/removed only at real aura add/remove
3716 if(!Real)
3717 return;
3719 m_target->UpdateSpeed(MOVE_RUN, true);
3720 m_target->UpdateSpeed(MOVE_SWIM, true);
3721 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3724 void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
3726 // all applied/removed only at real aura add/remove
3727 if(!Real)
3728 return;
3730 m_target->UpdateSpeed(MOVE_RUN, true);
3731 m_target->UpdateSpeed(MOVE_SWIM, true);
3732 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3735 /*********************************************************/
3736 /*** IMMUNITY ***/
3737 /*********************************************************/
3739 void Aura::HandleModMechanicImmunity(bool apply, bool Real)
3741 uint32 mechanic = 1 << m_modifier.m_miscvalue;
3743 //immune movement impairment and loss of control
3744 if(GetId()==42292)
3745 mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
3747 if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3749 Unit::AuraMap& Auras = m_target->GetAuras();
3750 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3752 next = iter;
3753 ++next;
3754 SpellEntry const *spell = iter->second->GetSpellProto();
3755 if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
3756 && !iter->second->IsPositive() // only remove negative spells
3757 && spell->Id != GetId())
3759 //check for mechanic mask
3760 if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
3762 m_target->RemoveAurasDueToSpell(spell->Id);
3763 if(Auras.empty())
3764 break;
3765 else
3766 next = Auras.begin();
3772 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
3774 // special cases
3775 switch(m_modifier.m_miscvalue)
3777 case MECHANIC_INVULNERABILITY:
3778 m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply);
3779 break;
3780 case MECHANIC_SHIELD:
3781 m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply);
3782 break;
3785 // Bestial Wrath
3786 if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
3788 // The Beast Within cast on owner if talent present
3789 if ( Unit* owner = m_target->GetOwner() )
3791 // Search talent
3792 Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
3793 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3795 if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
3797 if (apply)
3798 owner->CastSpell(owner, 34471, true, 0, this);
3799 else
3800 owner->RemoveAurasDueToSpell(34471);
3801 break;
3807 // The Beast Within and Bestial Wrath - immunity
3808 if(GetId() == 19574 || GetId() == 34471)
3810 if(apply)
3812 m_target->CastSpell(m_target,24395,true);
3813 m_target->CastSpell(m_target,24396,true);
3814 m_target->CastSpell(m_target,24397,true);
3815 m_target->CastSpell(m_target,26592,true);
3817 else
3819 m_target->RemoveAurasDueToSpell(24395);
3820 m_target->RemoveAurasDueToSpell(24396);
3821 m_target->RemoveAurasDueToSpell(24397);
3822 m_target->RemoveAurasDueToSpell(26592);
3827 void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
3829 if(!apply)
3831 if(m_target->GetTypeId() == TYPEID_PLAYER)
3833 if(((Player*)m_target)->InBattleGround())
3835 BattleGround *bg = ((Player*)m_target)->GetBattleGround();
3836 if(bg)
3838 switch(bg->GetTypeID())
3840 case BATTLEGROUND_AV:
3842 break;
3844 case BATTLEGROUND_WS:
3846 // Warsong Flag, horde // Silverwing Flag, alliance
3847 if(GetId() == 23333 || GetId() == 23335)
3848 bg->EventPlayerDroppedFlag(((Player*)m_target));
3849 break;
3851 case BATTLEGROUND_AB:
3853 break;
3855 case BATTLEGROUND_EY:
3857 if(GetId() == 34976)
3858 bg->EventPlayerDroppedFlag(((Player*)m_target));
3859 break;
3867 m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
3870 void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
3872 if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3874 Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
3875 for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
3877 if (auraList.front() != this) // skip itself aura (it already added)
3879 m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
3880 itr = auraList.begin();
3882 else
3883 ++itr;
3887 m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
3890 void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
3892 m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
3894 if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3896 if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
3898 uint32 school_mask = m_modifier.m_miscvalue;
3899 Unit::AuraMap& Auras = m_target->GetAuras();
3900 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3902 next = iter;
3903 ++next;
3904 SpellEntry const *spell = iter->second->GetSpellProto();
3905 if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
3906 && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
3907 && !iter->second->IsPositive() //Don't remove positive spells
3908 && spell->Id != GetId() ) //Don't remove self
3910 m_target->RemoveAurasDueToSpell(spell->Id);
3911 if(Auras.empty())
3912 break;
3913 else
3914 next = Auras.begin();
3919 if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
3921 if( apply )
3922 m_target->addUnitState(UNIT_STAT_ISOLATED);
3923 else
3924 m_target->clearUnitState(UNIT_STAT_ISOLATED);
3928 void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
3930 m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
3933 void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
3935 // all applied/removed only at real aura add/remove
3936 if(!Real)
3937 return;
3939 m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
3942 void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
3944 if(!Real)
3945 return;
3947 if(apply)
3949 // some spell have charges by functionality not have its in spell data
3950 switch (GetId())
3952 case 28200: // Ascendance (Talisman of Ascendance trinket)
3953 m_procCharges = 6;
3954 UpdateAuraCharges();
3955 break;
3956 default: break;
3961 void Aura::HandleAuraModStalked(bool apply, bool Real)
3963 // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
3964 if(apply)
3965 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3966 else
3967 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3970 /*********************************************************/
3971 /*** PERIODIC ***/
3972 /*********************************************************/
3974 void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
3976 if (m_periodicTimer <= 0)
3977 m_periodicTimer += m_modifier.periodictime;
3979 m_isPeriodic = apply;
3980 m_isTrigger = apply;
3982 // Curse of the Plaguebringer
3983 if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL)
3985 // Cast Wrath of the Plaguebringer if not dispelled
3986 m_target->CastSpell(m_target, 29214, true, 0, this);
3990 void Aura::HandlePeriodicEnergize(bool apply, bool Real)
3992 if (m_periodicTimer <= 0)
3993 m_periodicTimer += m_modifier.periodictime;
3995 m_isPeriodic = apply;
3998 void Aura::HandlePeriodicHeal(bool apply, bool Real)
4000 if (m_periodicTimer <= 0)
4001 m_periodicTimer += m_modifier.periodictime;
4003 m_isPeriodic = apply;
4005 // only at real apply
4006 if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE)
4008 // provided m_target as original caster to prevent apply aura caster selection for this negative buff
4009 m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID());
4012 // For prevent double apply bonuses
4013 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4015 if(!loading && apply)
4017 switch (m_spellProto->SpellFamilyName)
4019 case SPELLFAMILY_DRUID:
4021 // Rejuvenation
4022 if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
4024 if(Unit* caster = GetCaster())
4026 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4027 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4029 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4030 switch((*k)->GetModifier()->m_miscvalue)
4032 case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
4033 case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
4035 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4036 break;
4047 void Aura::HandlePeriodicDamage(bool apply, bool Real)
4049 // spells required only Real aura add/remove
4050 if(!Real)
4051 return;
4053 if (m_periodicTimer <= 0)
4054 m_periodicTimer += m_modifier.periodictime;
4056 m_isPeriodic = apply;
4058 // For prevent double apply bonuses
4059 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4061 Unit *caster = GetCaster();
4063 switch (m_spellProto->SpellFamilyName)
4065 case SPELLFAMILY_GENERIC:
4067 // Pounce Bleed
4068 if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 )
4070 // $AP*0.18/6 bonus per tick
4071 if (apply && !loading && caster)
4072 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4073 return;
4075 break;
4077 case SPELLFAMILY_WARRIOR:
4079 // Rend
4080 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4082 // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
4083 if (apply && !loading && caster)
4085 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4086 int32 mws = caster->GetAttackTime(BASE_ATTACK);
4087 float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
4088 float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
4089 // WARNING! in 3.0 multiplier 0.00743f change to 0.6
4090 m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
4092 return;
4094 break;
4096 case SPELLFAMILY_DRUID:
4098 // Rake
4099 if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
4101 // $AP*0.06/3 bonus per tick
4102 if (apply && !loading && caster)
4103 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
4104 return;
4106 // Lacerate
4107 if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
4109 // $AP*0.05/5 bonus per tick
4110 if (apply && !loading && caster)
4111 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
4112 return;
4114 // Rip
4115 if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
4117 // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used]
4118 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4120 uint8 cp = ((Player*)caster)->GetComboPoints();
4122 // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
4123 Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
4124 for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
4126 if((*itr)->GetId()==34241)
4128 m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
4129 break;
4133 if (cp > 4) cp = 4;
4134 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4136 return;
4138 break;
4140 case SPELLFAMILY_ROGUE:
4142 // Deadly poison aura state
4143 if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual[0]==5100)
4145 if(apply)
4146 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
4147 else
4149 // current aura already removed, search present of another
4150 bool found = false;
4151 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
4152 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
4154 SpellEntry const* itr_spell = (*itr)->GetSpellProto();
4155 if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual[0]==5100)
4157 found = true;
4158 break;
4161 // this has been last deadly poison aura
4162 if(!found)
4163 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
4165 return;
4167 // Rupture
4168 if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
4170 // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP]
4171 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4173 uint8 cp = ((Player*)caster)->GetComboPoints();
4174 if (cp > 3) cp = 3;
4175 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4177 return;
4179 // Garrote
4180 if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
4182 // $AP*0.18/6 bonus per tick
4183 if (apply && !loading && caster)
4184 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4185 return;
4187 break;
4189 case SPELLFAMILY_HUNTER:
4191 // Serpent Sting
4192 if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
4194 // $RAP*0.1/5 bonus per tick
4195 if (apply && !loading && caster)
4196 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4197 return;
4199 // Immolation Trap
4200 if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
4202 // $RAP*0.1/5 bonus per tick
4203 if (apply && !loading && caster)
4204 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4205 return;
4207 break;
4209 case SPELLFAMILY_PALADIN:
4211 // Consecration
4212 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4214 if (apply && !loading)
4216 if(Unit* caster = GetCaster())
4218 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4219 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4221 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4222 switch((*k)->GetModifier()->m_miscvalue)
4224 case 5147: // Improved Consecration - Libram of the Eternal Rest
4226 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4227 break;
4233 return;
4235 break;
4237 default:
4238 break;
4242 void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
4244 if (m_periodicTimer <= 0)
4245 m_periodicTimer += m_modifier.periodictime;
4247 m_isPeriodic = apply;
4250 void Aura::HandlePeriodicLeech(bool apply, bool Real)
4252 if (m_periodicTimer <= 0)
4253 m_periodicTimer += m_modifier.periodictime;
4255 m_isPeriodic = apply;
4258 void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
4260 if (m_periodicTimer <= 0)
4261 m_periodicTimer += m_modifier.periodictime;
4263 m_isPeriodic = apply;
4266 /*********************************************************/
4267 /*** MODIFY STATS ***/
4268 /*********************************************************/
4270 /********************************/
4271 /*** RESISTANCE ***/
4272 /********************************/
4274 void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
4276 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4278 if(m_modifier.m_miscvalue & int32(1<<x))
4280 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
4281 if(m_target->GetTypeId() == TYPEID_PLAYER)
4282 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4287 void Aura::HandleAuraModResistance(bool apply, bool Real)
4289 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4291 if(m_modifier.m_miscvalue & int32(1<<x))
4293 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4294 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4295 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4299 // Faerie Fire (druid versions)
4300 if( m_spellProto->SpellIconID == 109 &&
4301 m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
4302 m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
4304 m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
4308 void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
4310 // only players have base stats
4311 if(m_target->GetTypeId() != TYPEID_PLAYER)
4313 //pets only have base armor
4314 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4315 m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
4317 else
4319 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4321 if(m_modifier.m_miscvalue & int32(1<<x))
4322 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
4327 void Aura::HandleModResistancePercent(bool apply, bool Real)
4329 for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4331 if(m_modifier.m_miscvalue & int32(1<<i))
4333 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4334 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4336 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
4337 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
4343 void Aura::HandleModBaseResistance(bool apply, bool Real)
4345 // only players have base stats
4346 if(m_target->GetTypeId() != TYPEID_PLAYER)
4348 //only pets have base stats
4349 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4350 m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4352 else
4354 for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4355 if(m_modifier.m_miscvalue & (1<<i))
4356 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4360 /********************************/
4361 /*** STAT ***/
4362 /********************************/
4364 void Aura::HandleAuraModStat(bool apply, bool Real)
4366 if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
4368 sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
4369 return;
4372 for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4374 // -1 or -2 is all stats ( misc < -2 checked in function beginning )
4375 if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
4377 //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
4378 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4379 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4380 m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
4385 void Aura::HandleModPercentStat(bool apply, bool Real)
4387 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4389 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4390 return;
4393 // only players have base stats
4394 if (m_target->GetTypeId() != TYPEID_PLAYER)
4395 return;
4397 for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
4399 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4400 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
4404 void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real)
4406 if(m_target->GetTypeId() != TYPEID_PLAYER)
4407 return;
4409 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4410 // This information for client side use only
4411 // Recalculate bonus
4412 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4415 void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real)
4417 if(m_target->GetTypeId() != TYPEID_PLAYER)
4418 return;
4420 // Recalculate bonus
4421 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4424 void Aura::HandleAuraModDispelResist(bool apply, bool Real)
4426 if(!Real || !apply)
4427 return;
4429 if(GetId()==33206)
4430 m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
4433 void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real)
4435 if(m_target->GetTypeId() != TYPEID_PLAYER)
4436 return;
4438 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4439 // This information for client side use only
4440 // Recalculate bonus
4441 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4444 void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real)
4446 if(m_target->GetTypeId() != TYPEID_PLAYER)
4447 return;
4449 // Recalculate bonus
4450 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4453 void Aura::HandleModHealingDone(bool /*apply*/, bool Real)
4455 if(m_target->GetTypeId() != TYPEID_PLAYER)
4456 return;
4457 // implemented in Unit::SpellHealingBonus
4458 // this information is for client side only
4459 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4462 void Aura::HandleModTotalPercentStat(bool apply, bool Real)
4464 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4466 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4467 return;
4470 //save current and max HP before applying aura
4471 uint32 curHPValue = m_target->GetHealth();
4472 uint32 maxHPValue = m_target->GetMaxHealth();
4474 for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4476 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4478 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4479 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4480 m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
4484 //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
4485 if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
4487 // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
4488 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
4489 m_target->SetHealth(newHPValue);
4493 void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
4495 if(m_target->GetTypeId() != TYPEID_PLAYER)
4496 return;
4498 if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
4500 // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
4501 // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
4502 sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
4503 return;
4506 // Recalculate Armor
4507 m_target->UpdateArmor();
4510 /********************************/
4511 /*** HEAL & ENERGIZE ***/
4512 /********************************/
4513 void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
4516 Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
4517 so this aura not fully working.
4519 if(apply)
4521 if(!m_target->isAlive())
4522 return;
4524 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4525 m_target->SetStandState(PLAYER_STATE_SIT);
4527 if(m_periodicTimer <= 0)
4529 m_periodicTimer += m_modifier.periodictime;
4531 if(m_target->GetHealth() < m_target->GetMaxHealth())
4533 // PeriodicTick can cast triggered spells with stats changes
4534 PeriodicTick();
4539 m_isPeriodic = apply;
4542 void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
4544 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4545 m_target->SetStandState(PLAYER_STATE_SIT);
4546 if(apply)
4548 if(m_modifier.periodictime == 0)
4549 m_modifier.periodictime = 1000;
4550 if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
4552 m_periodicTimer += m_modifier.periodictime;
4554 if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
4556 // PeriodicTick can cast triggered spells with stats changes
4557 PeriodicTick();
4562 m_isPeriodic = apply;
4565 void Aura::HandleModRegen(bool apply, bool Real) // eating
4567 if(apply)
4569 if(!m_target->isAlive())
4570 return;
4572 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4573 m_target->SetStandState(PLAYER_STATE_SIT);
4575 if(m_periodicTimer <= 0)
4577 m_periodicTimer += 5000;
4578 int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
4579 Unit *caster = GetCaster();
4580 if (caster)
4582 SpellEntry const *spellProto = GetSpellProto();
4583 if (spellProto)
4584 m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
4589 m_isPeriodic = apply;
4592 void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
4594 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4595 m_target->SetStandState(PLAYER_STATE_SIT);
4597 if(apply && m_periodicTimer <= 0)
4599 m_periodicTimer += 2000;
4601 Powers pt = m_target->getPowerType();
4602 if(int32(pt) != m_modifier.m_miscvalue)
4603 return;
4605 if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
4607 // eating anim
4608 m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
4610 else if( GetId() == 20577 )
4612 // cannibalize anim
4613 m_target->HandleEmoteCommand(398);
4616 // Warrior talent, gain 1 rage every 3 seconds while in combat
4617 if(pt == POWER_RAGE && m_target->isInCombat())
4619 m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
4620 m_periodicTimer += 1000;
4623 m_isPeriodic = apply;
4624 if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
4625 ((Player*)m_target)->UpdateManaRegen();
4628 void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
4630 // spells required only Real aura add/remove
4631 if(!Real)
4632 return;
4634 if (m_target->GetTypeId() != TYPEID_PLAYER)
4635 return;
4637 // Update manaregen value
4638 if (m_modifier.m_miscvalue == POWER_MANA)
4639 ((Player*)m_target)->UpdateManaRegen();
4642 void Aura::HandleModManaRegen(bool /*apply*/, bool Real)
4644 // spells required only Real aura add/remove
4645 if(!Real)
4646 return;
4648 if (m_target->GetTypeId() != TYPEID_PLAYER)
4649 return;
4651 //Note: an increase in regen does NOT cause threat.
4652 ((Player*)m_target)->UpdateManaRegen();
4655 void Aura::HandleComprehendLanguage(bool apply, bool Real)
4657 if(apply)
4658 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4659 else
4660 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4663 void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
4665 // Special case with temporary increase max/current health
4666 switch(GetId())
4668 case 12976: // Warrior Last Stand triggered spell
4669 case 28726: // Nightmare Seed ( Nightmare Seed )
4670 case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
4671 case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
4673 if(Real)
4675 if(apply)
4677 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4678 m_target->ModifyHealth(m_modifier.m_amount);
4680 else
4682 if (int32(m_target->GetHealth()) > m_modifier.m_amount)
4683 m_target->ModifyHealth(-m_modifier.m_amount);
4684 else
4685 m_target->SetHealth(1);
4686 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4689 return;
4693 // generic case
4694 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4697 void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
4699 uint32 oldhealth = m_target->GetHealth();
4700 double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
4702 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4704 // refresh percentage
4705 if(oldhealth > 0)
4707 uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
4708 if(newhealth==0)
4709 newhealth = 1;
4711 m_target->SetHealth(newhealth);
4715 void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
4717 Powers powerType = m_target->getPowerType();
4718 if(int32(powerType) != m_modifier.m_miscvalue)
4719 return;
4721 m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4724 void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool Real)
4726 Powers powerType = m_target->getPowerType();
4727 if(int32(powerType) != m_modifier.m_miscvalue)
4728 return;
4730 m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_PCT, float(m_modifier.m_amount), apply);
4733 void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real)
4735 //m_target->ApplyMaxHealthPercentMod(m_modifier.m_amount,apply);
4736 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
4739 /********************************/
4740 /*** FIGHT ***/
4741 /********************************/
4743 void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real)
4745 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4746 return;
4748 ((Player*)m_target)->UpdateParryPercentage();
4751 void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real)
4753 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4754 return;
4756 ((Player*)m_target)->UpdateDodgePercentage();
4757 //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
4760 void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real)
4762 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4763 return;
4765 ((Player*)m_target)->UpdateBlockPercentage();
4766 //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
4769 void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real)
4771 // spells required only Real aura add/remove
4772 if(!Real)
4773 return;
4775 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4776 return;
4778 ((Player*)m_target)->UpdateManaRegen();
4781 void Aura::HandleAuraModCritPercent(bool apply, bool Real)
4783 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4784 return;
4786 // apply item specific bonuses for already equipped weapon
4787 if(Real)
4789 for(int i = 0; i < MAX_ATTACK; ++i)
4790 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4791 ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
4794 // mods must be applied base at equipped weapon class and subclass comparison
4795 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4796 // m_modifier.m_miscvalue comparison with item generated damage types
4798 if (GetSpellProto()->EquippedItemClass == -1)
4800 ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4801 ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4802 ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4804 else
4806 // done in Player::_ApplyWeaponDependentAuraMods
4810 void Aura::HandleModHitChance(bool apply, bool Real)
4812 m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4813 m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4816 void Aura::HandleModSpellHitChance(bool apply, bool Real)
4818 m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
4821 void Aura::HandleModSpellCritChance(bool apply, bool Real)
4823 // spells required only Real aura add/remove
4824 if(!Real)
4825 return;
4827 if(m_target->GetTypeId() == TYPEID_PLAYER)
4829 ((Player*)m_target)->UpdateAllSpellCritChances();
4831 else
4833 m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
4837 void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
4839 // spells required only Real aura add/remove
4840 if(!Real)
4841 return;
4843 if(m_target->GetTypeId() != TYPEID_PLAYER)
4844 return;
4846 for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
4847 if (m_modifier.m_miscvalue & (1<<school))
4848 ((Player*)m_target)->UpdateSpellCritChance(school);
4851 /********************************/
4852 /*** ATTACK SPEED ***/
4853 /********************************/
4855 void Aura::HandleModCastingSpeed(bool apply, bool Real)
4857 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4860 void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
4862 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4863 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4864 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4867 void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
4869 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4870 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4871 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4872 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4875 void Aura::HandleModAttackSpeed(bool apply, bool Real)
4877 if(!m_target->isAlive() )
4878 return;
4880 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4883 void Aura::HandleHaste(bool apply, bool Real)
4885 m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
4886 m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
4887 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
4890 void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
4892 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4895 void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
4897 if(m_target->GetTypeId() != TYPEID_PLAYER)
4898 return;
4899 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
4902 /********************************/
4903 /*** ATTACK POWER ***/
4904 /********************************/
4906 void Aura::HandleAuraModAttackPower(bool apply, bool Real)
4908 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4911 void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
4913 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4914 return;
4916 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4919 void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
4921 //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
4922 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
4925 void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
4927 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4928 return;
4930 //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
4931 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
4934 void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
4936 // spells required only Real aura add/remove
4937 if(!Real)
4938 return;
4940 if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4941 return;
4943 if(m_modifier.m_miscvalue != STAT_INTELLECT)
4945 // support required adding UpdateAttackPowerAndDamage calls at stat update
4946 sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intelect stats!");
4947 return;
4950 // Recalculate bonus
4951 ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
4954 /********************************/
4955 /*** DAMAGE BONUS ***/
4956 /********************************/
4957 void Aura::HandleModDamageDone(bool apply, bool Real)
4959 // apply item specific bonuses for already equipped weapon
4960 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
4962 for(int i = 0; i < MAX_ATTACK; ++i)
4963 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4964 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
4967 // m_modifier.m_miscvalue is bitmask of spell schools
4968 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
4969 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
4970 // 127 - full bitmask any damages
4972 // mods must be applied base at equipped weapon class and subclass comparison
4973 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4974 // m_modifier.m_miscvalue comparison with item generated damage types
4976 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
4978 // apply generic physical damage bonuses including wand case
4979 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
4981 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4982 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4983 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4985 else
4987 // done in Player::_ApplyWeaponDependentAuraMods
4990 if(m_target->GetTypeId() == TYPEID_PLAYER)
4992 if(m_positive)
4993 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
4994 else
4995 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
4999 // Skip non magic case for speedup
5000 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5001 return;
5003 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5005 // wand magic case (skip generic to all item spell bonuses)
5006 // done in Player::_ApplyWeaponDependentAuraMods
5008 // Skip item specific requirements for not wand magic damage
5009 return;
5012 // Magic damage modifiers implemented in Unit::SpellDamageBonus
5013 // This information for client side use only
5014 if(m_target->GetTypeId() == TYPEID_PLAYER)
5016 if(m_positive)
5018 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5020 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5021 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
5024 else
5026 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5028 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5029 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
5032 Pet* pet = m_target->GetPet();
5033 if(pet)
5034 pet->UpdateAttackPowerAndDamage();
5038 void Aura::HandleModDamagePercentDone(bool apply, bool Real)
5040 sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
5042 // apply item specific bonuses for already equipped weapon
5043 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5045 for(int i = 0; i < MAX_ATTACK; ++i)
5046 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5047 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5050 // m_modifier.m_miscvalue is bitmask of spell schools
5051 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5052 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
5053 // 127 - full bitmask any damages
5055 // mods must be applied base at equipped weapon class and subclass comparison
5056 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5057 // m_modifier.m_miscvalue comparison with item generated damage types
5059 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5061 // apply generic physical damage bonuses including wand case
5062 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5064 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5065 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5066 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5068 else
5070 // done in Player::_ApplyWeaponDependentAuraMods
5072 // For show in client
5073 if(m_target->GetTypeId() == TYPEID_PLAYER)
5074 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
5077 // Skip non magic case for speedup
5078 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5079 return;
5081 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5083 // wand magic case (skip generic to all item spell bonuses)
5084 // done in Player::_ApplyWeaponDependentAuraMods
5086 // Skip item specific requirements for not wand magic damage
5087 return;
5090 // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
5091 // Send info to client
5092 if(m_target->GetTypeId() == TYPEID_PLAYER)
5093 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
5094 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
5097 void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
5099 // spells required only Real aura add/remove
5100 if(!Real)
5101 return;
5103 sLog.outDebug("AURA MOD OFFHAND DAMAGE");
5105 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5108 /********************************/
5109 /*** POWER COST ***/
5110 /********************************/
5112 void Aura::HandleModPowerCostPCT(bool apply, bool Real)
5114 // spells required only Real aura add/remove
5115 if(!Real)
5116 return;
5118 float amount = m_modifier.m_amount/100.0f;
5119 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5120 if(m_modifier.m_miscvalue & (1<<i))
5121 m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
5124 void Aura::HandleModPowerCost(bool apply, bool Real)
5126 // spells required only Real aura add/remove
5127 if(!Real)
5128 return;
5130 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5131 if(m_modifier.m_miscvalue & (1<<i))
5132 m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
5135 /*********************************************************/
5136 /*** OTHERS ***/
5137 /*********************************************************/
5139 void Aura::HandleShapeshiftBoosts(bool apply)
5141 uint32 spellId = 0;
5142 uint32 spellId2 = 0;
5143 uint32 HotWSpellId = 0;
5145 switch(GetModifier()->m_miscvalue)
5147 case FORM_CAT:
5148 spellId = 3025;
5149 HotWSpellId = 24900;
5150 break;
5151 case FORM_TREE:
5152 spellId = 5420;
5153 break;
5154 case FORM_TRAVEL:
5155 spellId = 5419;
5156 break;
5157 case FORM_AQUA:
5158 spellId = 5421;
5159 break;
5160 case FORM_BEAR:
5161 spellId = 1178;
5162 spellId2 = 21178;
5163 HotWSpellId = 24899;
5164 break;
5165 case FORM_DIREBEAR:
5166 spellId = 9635;
5167 spellId2 = 21178;
5168 HotWSpellId = 24899;
5169 break;
5170 case FORM_BATTLESTANCE:
5171 spellId = 21156;
5172 break;
5173 case FORM_DEFENSIVESTANCE:
5174 spellId = 7376;
5175 break;
5176 case FORM_BERSERKERSTANCE:
5177 spellId = 7381;
5178 break;
5179 case FORM_MOONKIN:
5180 spellId = 24905;
5181 // aura from effect trigger spell
5182 spellId2 = 24907;
5183 break;
5184 case FORM_FLIGHT:
5185 spellId = 33948;
5186 break;
5187 case FORM_FLIGHT_EPIC:
5188 spellId = 40122;
5189 spellId2 = 40121;
5190 break;
5191 case FORM_SPIRITOFREDEMPTION:
5192 spellId = 27792;
5193 spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
5194 break;
5195 case FORM_GHOSTWOLF:
5196 case FORM_AMBIENT:
5197 case FORM_GHOUL:
5198 case FORM_SHADOW:
5199 case FORM_STEALTH:
5200 case FORM_CREATURECAT:
5201 case FORM_CREATUREBEAR:
5202 spellId = 0;
5203 break;
5206 uint32 form = GetModifier()->m_miscvalue-1;
5208 if(apply)
5210 if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
5211 if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
5213 if(m_target->GetTypeId() == TYPEID_PLAYER)
5215 const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
5216 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
5218 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
5219 if(itr->first==spellId || itr->first==spellId2) continue;
5220 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
5221 if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
5222 if (spellInfo->Stances & (1<<form))
5223 m_target->CastSpell(m_target, itr->first, true, NULL, this);
5225 //LotP
5226 if (((Player*)m_target)->HasSpell(17007))
5228 SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
5229 if (spellInfo && spellInfo->Stances & (1<<form))
5230 m_target->CastSpell(m_target, 24932, true, NULL, this);
5232 // HotW
5233 if (HotWSpellId)
5235 Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
5236 for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
5238 if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
5240 int32 HotWMod = (*i)->GetModifier()->m_amount;
5241 if(GetModifier()->m_miscvalue == FORM_CAT)
5242 HotWMod /= 2;
5244 m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
5245 break;
5251 else
5253 m_target->RemoveAurasDueToSpell(spellId);
5254 m_target->RemoveAurasDueToSpell(spellId2);
5256 Unit::AuraMap& tAuras = m_target->GetAuras();
5257 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
5259 if (itr->second->IsRemovedOnShapeLost())
5261 m_target->RemoveAurasDueToSpell(itr->second->GetId());
5262 itr = tAuras.begin();
5264 else
5266 ++itr;
5271 /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
5272 m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
5275 void Aura::HandleAuraEmpathy(bool apply, bool Real)
5277 if(m_target->GetTypeId() != TYPEID_UNIT)
5278 return;
5280 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
5281 if(ci && ci->type == CREATURE_TYPE_BEAST)
5282 m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
5285 void Aura::HandleAuraUntrackable(bool apply, bool Real)
5287 if(apply)
5288 m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5289 else
5290 m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5293 void Aura::HandleAuraModPacify(bool apply, bool Real)
5295 if(m_target->GetTypeId() != TYPEID_PLAYER)
5296 return;
5298 if(apply)
5299 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5300 else
5301 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5304 void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
5306 HandleAuraModPacify(apply,Real);
5307 HandleAuraModSilence(apply,Real);
5310 void Aura::HandleAuraGhost(bool apply, bool Real)
5312 if(m_target->GetTypeId() != TYPEID_PLAYER)
5313 return;
5315 if(apply)
5317 m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5319 else
5321 m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5325 void Aura::HandleAuraAllowFlight(bool apply, bool Real)
5327 // all applied/removed only at real aura add/remove
5328 if(!Real)
5329 return;
5331 // allow fly
5332 WorldPacket data;
5333 if(apply)
5334 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
5335 else
5336 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
5337 data.append(m_target->GetPackGUID());
5338 data << uint32(0); // unk
5339 m_target->SendMessageToSet(&data, true);
5342 void Aura::HandleModRating(bool apply, bool Real)
5344 // spells required only Real aura add/remove
5345 if(!Real)
5346 return;
5348 if(m_target->GetTypeId() != TYPEID_PLAYER)
5349 return;
5351 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5352 if (m_modifier.m_miscvalue & (1 << rating))
5353 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
5356 void Aura::HandleForceMoveForward(bool apply, bool Real)
5358 if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
5359 return;
5360 if(apply)
5361 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5362 else
5363 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5366 void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real)
5368 if(m_target->GetTypeId() != TYPEID_PLAYER)
5369 return;
5371 ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
5372 ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
5375 void Aura::HandleModTargetResistance(bool apply, bool Real)
5377 // spells required only Real aura add/remove
5378 if(!Real)
5379 return;
5380 // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
5382 // show armor penetration
5383 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
5384 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
5386 // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
5387 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
5388 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
5391 void Aura::HandleShieldBlockValue(bool apply, bool Real)
5393 BaseModType modType = FLAT_MOD;
5394 if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
5395 modType = PCT_MOD;
5397 if(m_target->GetTypeId() == TYPEID_PLAYER)
5398 ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
5401 void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
5403 // spells required only Real aura add/remove
5404 if(!Real)
5405 return;
5407 if(m_target->GetTypeId() != TYPEID_PLAYER)
5408 return;
5410 Player *target = (Player*)m_target;
5412 // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
5413 // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
5414 if( !apply && m_duration==0 && target->GetComboTarget())
5415 if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
5416 target->AddComboPoints(unit, -m_modifier.m_amount);
5419 void Aura::HandleModUnattackable( bool Apply, bool Real )
5421 if(Real && Apply)
5422 m_target->CombatStop();
5424 m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
5427 void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
5429 // spells required only Real aura add/remove
5430 if(!Real)
5431 return;
5433 // prepare spirit state
5434 if(apply)
5436 if(m_target->GetTypeId()==TYPEID_PLAYER)
5438 // disable breath/etc timers
5439 ((Player*)m_target)->StopMirrorTimers();
5441 // set stand state (expected in this form)
5442 if(!m_target->IsStandState())
5443 m_target->SetStandState(PLAYER_STATE_NONE);
5446 m_target->SetHealth(1);
5448 // die at aura end
5449 else
5450 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
5453 void Aura::CleanupTriggeredSpells()
5455 uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
5456 if(!tSpellId)
5457 return;
5459 SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
5460 if(!tProto)
5461 return;
5463 if(GetSpellDuration(tProto) != -1)
5464 return;
5466 // needed for spell 43680, maybe others
5467 // TODO: is there a spell flag, which can solve this in a more sophisticated way?
5468 if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
5469 GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
5470 return;
5471 m_target->RemoveAurasDueToSpell(tSpellId);
5474 void Aura::HandleAuraPowerBurn(bool apply, bool Real)
5476 if (m_periodicTimer <= 0)
5477 m_periodicTimer += m_modifier.periodictime;
5479 m_isPeriodic = apply;
5482 void Aura::HandleSchoolAbsorb(bool apply, bool Real)
5484 if(!Real)
5485 return;
5487 // prevent double apply bonuses
5488 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
5490 if(Unit* caster = GetCaster())
5492 float DoneActualBenefit = 0.0f;
5493 switch(m_spellProto->SpellFamilyName)
5495 case SPELLFAMILY_PRIEST:
5496 if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
5498 //+30% from +healing bonus
5499 DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
5500 break;
5502 break;
5503 case SPELLFAMILY_MAGE:
5504 if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
5506 //frost ward, fire ward, ice barrier
5507 //+10% from +spd bonus
5508 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5509 break;
5511 break;
5512 case SPELLFAMILY_WARLOCK:
5513 if(m_spellProto->SpellFamilyFlags == 0x00)
5515 //shadow ward
5516 //+10% from +spd bonus
5517 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5518 break;
5520 break;
5521 default:
5522 break;
5525 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
5527 m_modifier.m_amount += (int32)DoneActualBenefit;
5532 void Aura::PeriodicTick()
5534 if(!m_target->isAlive())
5535 return;
5537 switch(m_modifier.m_auraname)
5539 case SPELL_AURA_PERIODIC_DAMAGE:
5540 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
5542 Unit *pCaster = GetCaster();
5543 if(!pCaster)
5544 return;
5546 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5547 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5548 return;
5550 // Check for immune (not use charges)
5551 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5552 return;
5554 // some auras remove at specific health level or more
5555 if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
5557 switch(GetId())
5559 case 43093: case 31956: case 38801:
5560 case 35321: case 38363: case 39215:
5561 if(m_target->GetHealth() == m_target->GetMaxHealth() )
5563 m_target->RemoveAurasDueToSpell(GetId());
5564 return;
5566 break;
5567 case 38772:
5569 uint32 percent =
5570 GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
5571 pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
5572 100;
5573 if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
5575 m_target->RemoveAurasDueToSpell(GetId());
5576 return;
5578 break;
5580 default:
5581 break;
5585 uint32 absorb=0;
5586 uint32 resist=0;
5587 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5589 // ignore non positive values (can be result apply spellmods to aura damage
5590 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5592 uint32 pdamage;
5594 if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
5596 pdamage = amount;
5598 // Calculate armor mitigation if it is a physical spell
5599 // But not for bleed mechanic spells
5600 if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
5601 GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
5603 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5604 cleanDamage.damage += pdamage - pdamageReductedArmor;
5605 pdamage = pdamageReductedArmor;
5608 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5610 // Curse of Agony damage-per-tick calculation
5611 if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
5613 // 1..4 ticks, 1/2 from normal tick damage
5614 if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
5615 pdamage = pdamage/2;
5616 // 9..12 ticks, 3/2 from normal tick damage
5617 else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
5618 pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
5619 // 5..8 ticks have normal tick damage
5622 else
5623 pdamage = uint32(m_target->GetMaxHealth()*amount/100);
5625 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5626 // Reduce dot damage from resilience for players
5627 if (m_target->GetTypeId()==TYPEID_PLAYER)
5628 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5630 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5632 sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5633 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5635 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5636 data.append(m_target->GetPackGUID());
5637 data.appendPackGUID(GetCasterGUID());
5638 data << uint32(GetId());
5639 data << uint32(1);
5640 data << uint32(m_modifier.m_auraname);
5641 data << (uint32)pdamage;
5642 data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
5643 data << (uint32)absorb;
5644 data << (uint32)resist;
5645 data << uint32(0); // wotlk
5646 m_target->SendMessageToSet(&data,true);
5648 Unit* target = m_target; // aura can be deleted in DealDamage
5649 SpellEntry const* spellProto = GetSpellProto();
5651 pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5653 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5655 pCaster->ProcDamageAndSpell(target, PROC_FLAG_NONE, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), GetSpellSchoolMask(spellProto), spellProto);
5656 break;
5658 case SPELL_AURA_PERIODIC_LEECH:
5660 Unit *pCaster = GetCaster();
5661 if(!pCaster)
5662 return;
5664 if(!pCaster->isAlive())
5665 return;
5667 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5668 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5669 return;
5671 // Check for immune (not use charges)
5672 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5673 return;
5675 uint32 absorb=0;
5676 uint32 resist=0;
5677 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5679 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5681 //Calculate armor mitigation if it is a physical spell
5682 if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
5684 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5685 cleanDamage.damage += pdamage - pdamageReductedArmor;
5686 pdamage = pdamageReductedArmor;
5689 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5691 // talent Soul Siphon add bonus to Drain Life spells
5692 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
5694 // find talent max bonus percentage
5695 Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5696 for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
5698 if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
5700 if((*i)->GetEffIndex()!=1)
5702 sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
5703 break;
5706 // effect 1 m_amount
5707 int32 maxPercent = (*i)->GetModifier()->m_amount;
5708 // effect 0 m_amount
5709 int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
5711 // count affliction effects and calc additional damage in percentage
5712 int32 modPercent = 0;
5713 Unit::AuraMap const& victimAuras = m_target->GetAuras();
5714 for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
5716 Aura* aura = itr->second;
5717 if (aura->IsPositive())continue;
5718 SpellEntry const* m_spell = aura->GetSpellProto();
5719 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
5720 continue;
5722 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
5723 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
5725 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
5727 if(_spell_idx->second->skillId == SKILL_AFFLICTION)
5729 modPercent += stepPercent;
5730 if (modPercent >= maxPercent)
5732 modPercent = maxPercent;
5733 break;
5738 pdamage += (pdamage*modPercent/100);
5739 break;
5744 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5745 // Reduce dot damage from resilience for players
5746 if (m_target->GetTypeId()==TYPEID_PLAYER)
5747 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5749 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5751 if(m_target->GetHealth() < pdamage)
5752 pdamage = uint32(m_target->GetHealth());
5754 sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5755 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5757 pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
5760 Unit* target = m_target; // aura can be deleted in DealDamage
5761 SpellEntry const* spellProto = GetSpellProto();
5762 float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
5764 uint32 new_damage = pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
5766 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5768 pCaster->ProcDamageAndSpell(target, PROC_FLAG_HEALED, PROC_FLAG_TAKE_DAMAGE, new_damage, GetSpellSchoolMask(spellProto), spellProto);
5769 if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
5771 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
5773 if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
5774 pCaster->m_currentSpells[i]->cancel();
5779 if(Player *modOwner = pCaster->GetSpellModOwner())
5780 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
5782 uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
5784 int32 gain = pCaster->ModifyHealth(heal);
5785 pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
5787 pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
5788 break;
5790 case SPELL_AURA_PERIODIC_HEAL:
5791 case SPELL_AURA_OBS_MOD_HEALTH:
5793 Unit *pCaster = GetCaster();
5794 if(!pCaster)
5795 return;
5797 // heal for caster damage (must be alive)
5798 if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive())
5799 return;
5801 // ignore non positive values (can be result apply spellmods to aura damage
5802 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5804 uint32 pdamage;
5806 if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
5807 pdamage = uint32(m_target->GetMaxHealth() * amount/100);
5808 else
5809 pdamage = amount;
5811 pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
5813 sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
5814 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5816 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5817 data.append(m_target->GetPackGUID());
5818 data.appendPackGUID(GetCasterGUID());
5819 data << uint32(GetId());
5820 data << uint32(1);
5821 data << uint32(m_modifier.m_auraname);
5822 data << (uint32)pdamage;
5823 data << uint32(0); // wotlk
5824 m_target->SendMessageToSet(&data,true);
5826 int32 gain = m_target->ModifyHealth(pdamage);
5828 // add HoTs to amount healed in bgs
5829 if( pCaster->GetTypeId() == TYPEID_PLAYER )
5830 if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
5831 bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
5833 //Do check before because m_modifier.auraName can be invalidate by DealDamage.
5834 bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
5836 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5838 Unit* target = m_target; // aura can be deleted in DealDamage
5839 SpellEntry const* spellProto = GetSpellProto();
5840 bool haveCastItem = GetCastItemGUID()!=0;
5842 // heal for caster damage
5843 if(m_target!=pCaster && spellProto->SpellVisual[0]==163)
5845 uint32 dmg = spellProto->manaPerSecond;
5846 if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
5848 pCaster->RemoveAurasDueToSpell(GetId());
5850 // finish current generic/channeling spells, don't affect autorepeat
5851 if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
5853 pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
5855 if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
5857 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
5858 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
5861 else
5863 pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
5865 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5866 pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5870 // ignore item heals
5871 if(procSpell && !haveCastItem)
5872 pCaster->ProcDamageAndSpell(target,PROC_FLAG_NONE, PROC_FLAG_HEALED, pdamage, SPELL_SCHOOL_MASK_NONE, spellProto);
5873 break;
5875 case SPELL_AURA_PERIODIC_MANA_LEECH:
5877 Unit *pCaster = GetCaster();
5878 if(!pCaster)
5879 return;
5881 if(!pCaster->isAlive())
5882 return;
5884 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5885 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5886 return;
5888 // Check for immune (not use charges)
5889 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5890 return;
5892 // ignore non positive values (can be result apply spellmods to aura damage
5893 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5895 sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
5896 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5898 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5899 break;
5901 Powers power = Powers(m_modifier.m_miscvalue);
5903 // power type might have changed between aura applying and tick (druid's shapeshift)
5904 if(m_target->getPowerType() != power)
5905 break;
5907 int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
5909 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
5910 if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
5911 drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
5913 m_target->ModifyPower(power, -drain_amount);
5915 float gain_multiplier = 0;
5917 if(pCaster->GetMaxPower(power) > 0)
5919 gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
5921 if(Player *modOwner = pCaster->GetSpellModOwner())
5922 modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
5925 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5926 data.append(m_target->GetPackGUID());
5927 data.appendPackGUID(GetCasterGUID());
5928 data << uint32(GetId());
5929 data << uint32(1);
5930 data << uint32(m_modifier.m_auraname);
5931 data << (uint32)power; // power type
5932 data << (uint32)drain_amount;
5933 data << (float)gain_multiplier;
5934 m_target->SendMessageToSet(&data,true);
5936 int32 gain_amount = int32(drain_amount*gain_multiplier);
5938 if(gain_amount)
5940 int32 gain = pCaster->ModifyPower(power,gain_amount);
5941 m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
5943 break;
5945 case SPELL_AURA_PERIODIC_ENERGIZE:
5947 // ignore non positive values (can be result apply spellmods to aura damage
5948 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5950 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
5951 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5953 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5954 break;
5956 Powers power = Powers(m_modifier.m_miscvalue);
5958 if(m_target->GetMaxPower(power) == 0)
5959 break;
5961 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5962 data.append(m_target->GetPackGUID());
5963 data.appendPackGUID(GetCasterGUID());
5964 data << uint32(GetId());
5965 data << uint32(1);
5966 data << uint32(m_modifier.m_auraname);
5967 data << (uint32)power; // power type
5968 data << (uint32)pdamage;
5969 m_target->SendMessageToSet(&data,true);
5971 int32 gain = m_target->ModifyPower(power,pdamage);
5973 if(Unit* pCaster = GetCaster())
5974 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5975 break;
5977 case SPELL_AURA_OBS_MOD_MANA:
5979 // ignore non positive values (can be result apply spellmods to aura damage
5980 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5982 uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
5984 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
5985 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5987 if(m_target->GetMaxPower(POWER_MANA) == 0)
5988 break;
5990 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5991 data.append(m_target->GetPackGUID());
5992 data.appendPackGUID(GetCasterGUID());
5993 data << uint32(GetId());
5994 data << uint32(1);
5995 data << uint32(m_modifier.m_auraname);
5996 data << (uint32)0; // ?
5997 data << (uint32)pdamage;
5998 m_target->SendMessageToSet(&data,true);
6000 int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
6002 if(Unit* pCaster = GetCaster())
6003 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
6004 break;
6006 case SPELL_AURA_POWER_BURN_MANA:
6008 Unit *pCaster = GetCaster();
6009 if(!pCaster)
6010 return;
6012 // Check for immune (not use charges)
6013 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
6014 return;
6016 int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6018 Powers powerType = Powers(m_modifier.m_miscvalue);
6020 if(!m_target->isAlive() || m_target->getPowerType() != powerType)
6021 return;
6023 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
6024 if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
6025 pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
6027 uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
6029 gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
6031 //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
6032 pCaster->SpellNonMeleeDamageLog(m_target, GetId(), gain);
6033 break;
6035 // Here tick dummy auras
6036 case SPELL_AURA_PERIODIC_DUMMY:
6038 PeriodicDummyTick();
6039 break;
6041 default:
6042 break;
6046 void Aura::PeriodicDummyTick()
6048 SpellEntry const* spell = GetSpellProto();
6049 switch (spell->Id)
6051 // Drink
6052 case 430:
6053 case 431:
6054 case 432:
6055 case 1133:
6056 case 1135:
6057 case 1137:
6058 case 10250:
6059 case 22734:
6060 case 27089:
6061 case 34291:
6062 case 43706:
6063 case 46755:
6065 if (m_target->GetTypeId() != TYPEID_PLAYER)
6066 return;
6067 // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
6068 Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
6069 for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
6071 if ((*i)->GetId() == GetId())
6073 // Get tick number
6074 int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
6075 // Default case (not on arenas)
6076 if (tick == 0)
6078 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6079 ((Player*)m_target)->UpdateManaRegen();
6080 // Disable continue
6081 m_isPeriodic = false;
6083 return;
6084 //**********************************************
6085 // Code commended since arena patch not added
6086 // This feature uses only in arenas
6087 //**********************************************
6088 // Here need increase mana regen per tick (6 second rule)
6089 // on 0 tick - 0 (handled in 2 second)
6090 // on 1 tick - 166% (handled in 4 second)
6091 // on 2 tick - 133% (handled in 6 second)
6092 // Not need update after 3 tick
6094 if (tick > 3)
6095 return;
6096 // Apply bonus for 0 - 3 tick
6097 switch (tick)
6099 case 0: // 0%
6100 (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
6101 break;
6102 case 1: // 166%
6103 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
6104 break;
6105 case 2: // 133%
6106 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
6107 break;
6108 default: // 100% - normal regen
6109 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6110 break;
6112 ((Player*)m_target)->UpdateManaRegen();
6113 return;*/
6116 return;
6118 // // Panda
6119 // case 19230: break;
6120 // // Master of Subtlety
6121 // case 31666: break;
6122 // // Gossip NPC Periodic - Talk
6123 // case 33208: break;
6124 // // Gossip NPC Periodic - Despawn
6125 // case 33209: break;
6126 // // Force of Nature
6127 // case 33831: break;
6128 // Aspect of the Viper
6129 case 34074:
6131 if (m_target->GetTypeId() != TYPEID_PLAYER)
6132 return;
6133 // Should be manauser
6134 if (m_target->getPowerType()!=POWER_MANA)
6135 return;
6136 Unit *caster = GetCaster();
6137 if (!caster)
6138 return;
6139 // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
6140 int mana = m_target->GetPower(POWER_MANA);
6141 int max_mana = m_target->GetMaxPower(POWER_MANA);
6142 int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
6143 float regen_pct = 1.20f - 1.1f * mana / max_mana;
6144 if (regen_pct > 1.0f) regen_pct = 1.0f;
6145 else if (regen_pct < 0.2f) regen_pct = 0.2f;
6146 m_modifier.m_amount = int32 (base_regen * regen_pct);
6147 ((Player*)m_target)->UpdateManaRegen();
6148 return;
6150 // // Steal Weapon
6151 // case 36207: break;
6152 // // Simon Game START timer, (DND)
6153 // case 39993: break;
6154 // // Harpooner's Mark
6155 // case 40084: break;
6156 // // Knockdown Fel Cannon: break; The Aggro Burst
6157 // case 40119: break;
6158 // // Old Mount Spell
6159 // case 40154: break;
6160 // // Magnetic Pull
6161 // case 40581: break;
6162 // // Ethereal Ring: break; The Bolt Burst
6163 // case 40801: break;
6164 // // Crystal Prison
6165 // case 40846: break;
6166 // // Copy Weapon
6167 // case 41054: break;
6168 // // Ethereal Ring Visual, Lightning Aura
6169 // case 41477: break;
6170 // // Ethereal Ring Visual, Lightning Aura (Fork)
6171 // case 41525: break;
6172 // // Ethereal Ring Visual, Lightning Jumper Aura
6173 // case 41567: break;
6174 // // No Man's Land
6175 // case 41955: break;
6176 // // Headless Horseman - Fire
6177 // case 42074: break;
6178 // // Headless Horseman - Visual - Large Fire
6179 // case 42075: break;
6180 // // Headless Horseman - Start Fire, Periodic Aura
6181 // case 42140: break;
6182 // // Ram Speed Boost
6183 // case 42152: break;
6184 // // Headless Horseman - Fires Out Victory Aura
6185 // case 42235: break;
6186 // // Pumpkin Life Cycle
6187 // case 42280: break;
6188 // // Brewfest Request Chick Chuck Mug Aura
6189 // case 42537: break;
6190 // // Squashling
6191 // case 42596: break;
6192 // // Headless Horseman Climax, Head: Periodic
6193 // case 42603: break;
6194 // // Fire Bomb
6195 // case 42621: break;
6196 // // Headless Horseman - Conflagrate, Periodic Aura
6197 // case 42637: break;
6198 // // Headless Horseman - Create Pumpkin Treats Aura
6199 // case 42774: break;
6200 // // Headless Horseman Climax - Summoning Rhyme Aura
6201 // case 42879: break;
6202 // // Tricky Treat
6203 // case 42919: break;
6204 // // Giddyup!
6205 // case 42924: break;
6206 // // Ram - Trot
6207 // case 42992: break;
6208 // // Ram - Canter
6209 // case 42993: break;
6210 // // Ram - Gallop
6211 // case 42994: break;
6212 // // Ram Level - Neutral
6213 // case 43310: break;
6214 // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
6215 // case 43884: break;
6216 // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
6217 // case 44000: break;
6218 // // Energy Feedback
6219 // case 44328: break;
6220 // // Romantic Picnic
6221 // case 45102: break;
6222 // // Romantic Picnic
6223 // case 45123: break;
6224 // // Looking for Love
6225 // case 45124: break;
6226 // // Kite - Lightning Strike Kite Aura
6227 // case 45197: break;
6228 // // Rocket Chicken
6229 // case 45202: break;
6230 // // Copy Offhand Weapon
6231 // case 45205: break;
6232 // // Upper Deck - Kite - Lightning Periodic Aura
6233 // case 45207: break;
6234 // // Kite -Sky Lightning Strike Kite Aura
6235 // case 45251: break;
6236 // // Ribbon Pole Dancer Check Aura
6237 // case 45390: break;
6238 // // Holiday - Midsummer, Ribbon Pole Periodic Visual
6239 // case 45406: break;
6240 // // Parachute
6241 // case 45472: break;
6242 // // Alliance Flag, Extra Damage Debuff
6243 // case 45898: break;
6244 // // Horde Flag, Extra Damage Debuff
6245 // case 45899: break;
6246 // // Ahune - Summoning Rhyme Aura
6247 // case 45926: break;
6248 // // Ahune - Slippery Floor
6249 // case 45945: break;
6250 // // Ahune's Shield
6251 // case 45954: break;
6252 // // Nether Vapor Lightning
6253 // case 45960: break;
6254 // // Darkness
6255 // case 45996: break;
6256 // // Summon Blood Elves Periodic
6257 // case 46041: break;
6258 // // Transform Visual Missile Periodic
6259 // case 46205: break;
6260 // // Find Opening Beam End
6261 // case 46333: break;
6262 // // Ice Spear Control Aura
6263 // case 46371: break;
6264 // // Hailstone Chill
6265 // case 46458: break;
6266 // // Hailstone Chill, Internal
6267 // case 46465: break;
6268 // // Chill, Internal Shifter
6269 // case 46549: break;
6270 // // Summon Ice Spear Knockback Delayer
6271 // case 46878: break;
6272 // // Burninate Effect
6273 // case 47214: break;
6274 // // Fizzcrank Practice Parachute
6275 // case 47228: break;
6276 // // Send Mug Control Aura
6277 // case 47369: break;
6278 // // Direbrew's Disarm (precast)
6279 // case 47407: break;
6280 // // Mole Machine Port Schedule
6281 // case 47489: break;
6282 // // Mole Machine Portal Schedule
6283 // case 49466: break;
6284 // // Drink Coffee
6285 // case 49472: break;
6286 // // Listening to Music
6287 // case 50493: break;
6288 // // Love Rocket Barrage
6289 // case 50530: break;
6290 default:
6291 break;
6295 void Aura::HandlePreventFleeing(bool apply, bool Real)
6297 if(!Real)
6298 return;
6300 Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
6301 if( !fearAuras.empty() )
6303 if (apply)
6304 m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
6305 else
6306 m_target->SetFeared(true);
6310 void Aura::HandleManaShield(bool apply, bool Real)
6312 if(!Real)
6313 return;
6315 // prevent double apply bonuses
6316 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
6318 if(Unit* caster = GetCaster())
6320 float DoneActualBenefit = 0.0f;
6321 switch(m_spellProto->SpellFamilyName)
6323 case SPELLFAMILY_MAGE:
6324 if(m_spellProto->SpellFamilyFlags & 0x8000)
6326 // Mana Shield
6327 // +50% from +spd bonus
6328 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
6329 break;
6331 break;
6332 default:
6333 break;
6336 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
6338 m_modifier.m_amount += (int32)DoneActualBenefit;
6343 void Aura::HandleArenaPreparation(bool apply, bool Real)
6345 if(!Real)
6346 return;
6348 if(apply)
6349 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6350 else
6351 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6354 void Aura::HandleAuraControlVehicle(bool apply, bool Real)
6356 if(!Real)
6357 return;
6359 if(m_target->GetTypeId() != TYPEID_PLAYER)
6360 return;
6362 if(Pet *pet = m_target->GetPet())
6363 pet->Remove(PET_SAVE_AS_CURRENT);
6365 WorldPacket data(SMSG_SHOW_VEHICLE_UI, 0);
6366 ((Player*)m_target)->GetSession()->SendPacket(&data);
6369 void Aura::HandleAuraConvertRune(bool apply, bool Real)
6371 if(!Real)
6372 return;
6374 if(m_target->GetTypeId() != TYPEID_PLAYER)
6375 return;
6377 Player *plr = (Player*)m_target;
6379 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6380 return;
6382 // how to determine what rune need to be converted?
6383 for(uint32 i = 0; i < MAX_RUNES; ++i)
6385 if(apply)
6387 if(!plr->GetRuneCooldown(i))
6389 plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]);
6390 break;
6393 else
6395 if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex])
6397 plr->ConvertRune(i, plr->GetBaseRune(i));
6398 break;