Removed direct use of some updatefields
[getmangos.git] / src / game / SpellAuras.cpp
blobe775150e1fef1c6a291d8057622ba1d77e8112e1
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::HandleNULL, //249
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 = 0;
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, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
737 cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
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, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
753 cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
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(GetAuraCharges());
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;
2038 // Dark Fiend
2039 if(GetId()==45934)
2041 // Kill target if dispelled
2042 if (m_removeMode==AURA_REMOVE_BY_DISPEL)
2043 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2044 return;
2047 // Burning Winds
2048 if(GetId()==46308) // casted only at creatures at spawn
2050 m_target->CastSpell(m_target,47287,true,NULL,this);
2051 return;
2055 // AT APPLY & REMOVE
2057 switch(m_spellProto->SpellFamilyName)
2059 case SPELLFAMILY_GENERIC:
2061 // Unstable Power
2062 if( GetId()==24658 )
2064 uint32 spellId = 24659;
2065 if (apply)
2067 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2068 if (!spell)
2069 return;
2070 for (int i=0; i < spell->StackAmount; ++i)
2071 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2072 return;
2074 m_target->RemoveAurasDueToSpell(spellId);
2075 return;
2077 // Restless Strength
2078 if( GetId()==24661 )
2080 uint32 spellId = 24662;
2081 if (apply)
2083 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2084 if (!spell)
2085 return;
2086 for (int i=0; i < spell->StackAmount; ++i)
2087 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2088 return;
2090 m_target->RemoveAurasDueToSpell(spellId);
2091 return;
2093 // Victorious
2094 if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
2096 m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
2097 return;
2099 //Summon Fire Elemental
2100 if (GetId() == 40133 && caster)
2102 Unit *owner = caster->GetOwner();
2103 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2105 if(apply)
2106 owner->CastSpell(owner,8985,true);
2107 else
2108 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2110 return;
2113 //Summon Earth Elemental
2114 if (GetId() == 40132 && caster)
2116 Unit *owner = caster->GetOwner();
2117 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2119 if(apply)
2120 owner->CastSpell(owner,19704,true);
2121 else
2122 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2124 return;
2126 break;
2128 case SPELLFAMILY_MAGE:
2130 // Hypothermia
2131 if( GetId()==41425 )
2133 m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply);
2134 return;
2136 break;
2138 case SPELLFAMILY_DRUID:
2140 // Lifebloom
2141 if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
2143 if ( apply )
2145 if ( caster )
2146 // prevent double apply bonuses
2147 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2148 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2150 else
2152 // Final heal only on dispelled or duration end
2153 if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
2154 return;
2156 // have a look if there is still some other Lifebloom dummy aura
2157 Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2158 for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); itr++)
2159 if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2160 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
2161 return;
2163 // final heal
2164 m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
2166 return;
2169 // Predatory Strikes
2170 if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
2172 ((Player*)m_target)->UpdateAttackPowerAndDamage();
2173 return;
2175 // Idol of the Emerald Queen
2176 if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
2178 if(apply)
2180 SpellModifier *mod = new SpellModifier;
2181 mod->op = SPELLMOD_DOT;
2182 mod->value = m_modifier.m_amount/7;
2183 mod->type = SPELLMOD_FLAT;
2184 mod->spellId = GetId();
2185 mod->effectId = m_effIndex;
2186 mod->lastAffected = NULL;
2187 mod->mask = 0x001000000000LL;
2188 mod->charges = 0;
2190 m_spellmod = mod;
2193 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2194 return;
2196 break;
2198 case SPELLFAMILY_HUNTER:
2200 // Improved Aspect of the Viper
2201 if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
2203 if(apply)
2205 // + effect value for Aspect of the Viper
2206 SpellModifier *mod = new SpellModifier;
2207 mod->op = SPELLMOD_EFFECT1;
2208 mod->value = m_modifier.m_amount;
2209 mod->type = SPELLMOD_FLAT;
2210 mod->spellId = GetId();
2211 mod->effectId = m_effIndex;
2212 mod->lastAffected = NULL;
2213 mod->mask = 0x4000000000000LL;
2214 mod->charges = 0;
2216 m_spellmod = mod;
2219 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2220 return;
2222 break;
2224 case SPELLFAMILY_SHAMAN:
2226 // Improved Weapon Totems
2227 if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
2229 if(apply)
2231 SpellModifier *mod = new SpellModifier;
2232 mod->op = SPELLMOD_EFFECT1;
2233 mod->value = m_modifier.m_amount;
2234 mod->type = SPELLMOD_PCT;
2235 mod->spellId = GetId();
2236 mod->effectId = m_effIndex;
2237 mod->lastAffected = NULL;
2238 switch (m_effIndex)
2240 case 0:
2241 mod->mask = 0x00200000000LL; // Windfury Totem
2242 break;
2243 case 1:
2244 mod->mask = 0x00400000000LL; // Flametongue Totem
2245 break;
2247 mod->charges = 0;
2249 m_spellmod = mod;
2252 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2253 return;
2255 break;
2259 // pet auras
2260 if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
2262 if(apply)
2263 m_target->AddPetAura(petSpell);
2264 else
2265 m_target->RemovePetAura(petSpell);
2266 return;
2270 void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
2272 // spells required only Real aura add/remove
2273 if(!Real)
2274 return;
2276 SpellEntry const*spell = GetSpellProto();
2277 switch( spell->SpellFamilyName)
2279 case SPELLFAMILY_ROGUE:
2281 // Master of Subtlety
2282 if (spell->Id==31666 && !apply && Real)
2284 m_target->RemoveAurasDueToSpell(31665);
2285 break;
2287 break;
2289 case SPELLFAMILY_HUNTER:
2291 // Aspect of the Viper
2292 if (spell->SpellFamilyFlags&0x0004000000000000LL)
2294 // Update regen on remove
2295 if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
2296 ((Player*)m_target)->UpdateManaRegen();
2297 break;
2299 break;
2303 m_isPeriodic = apply;
2306 void Aura::HandleAuraMounted(bool apply, bool Real)
2308 // only at real add/remove aura
2309 if(!Real)
2310 return;
2312 if(apply)
2314 CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2315 if(!ci)
2317 sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
2318 return;
2321 uint32 team = 0;
2322 if (m_target->GetTypeId()==TYPEID_PLAYER)
2323 team = ((Player*)m_target)->GetTeam();
2325 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2326 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2327 if (minfo)
2328 display_id = minfo->modelid;
2330 m_target->Mount(display_id);
2332 else
2334 m_target->Unmount();
2338 void Aura::HandleAuraWaterWalk(bool apply, bool Real)
2340 // only at real add/remove aura
2341 if(!Real)
2342 return;
2344 WorldPacket data;
2345 if(apply)
2346 data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
2347 else
2348 data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
2349 data.append(m_target->GetPackGUID());
2350 data << uint32(0);
2351 m_target->SendMessageToSet(&data,true);
2354 void Aura::HandleAuraFeatherFall(bool apply, bool Real)
2356 // only at real add/remove aura
2357 if(!Real)
2358 return;
2360 WorldPacket data;
2361 if(apply)
2362 data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
2363 else
2364 data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
2365 data.append(m_target->GetPackGUID());
2366 data << (uint32)0;
2367 m_target->SendMessageToSet(&data,true);
2370 void Aura::HandleAuraHover(bool apply, bool Real)
2372 // only at real add/remove aura
2373 if(!Real)
2374 return;
2376 WorldPacket data;
2377 if(apply)
2378 data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
2379 else
2380 data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
2381 data.append(m_target->GetPackGUID());
2382 data << uint32(0);
2383 m_target->SendMessageToSet(&data,true);
2386 void Aura::HandleWaterBreathing(bool apply, bool Real)
2388 if(apply)
2389 m_target->waterbreath = true;
2390 else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
2392 m_target->waterbreath = false;
2394 // update for enable timer in case not moving target
2395 if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
2397 ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
2398 ((Player*)m_target)->HandleDrowning();
2403 void Aura::HandleAuraModShapeshift(bool apply, bool Real)
2405 if(!Real)
2406 return;
2408 uint32 modelid = 0;
2409 Powers PowerType = POWER_MANA;
2410 ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
2411 switch(form)
2413 case FORM_CAT:
2414 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2415 modelid = 892;
2416 else
2417 modelid = 8571;
2418 PowerType = POWER_ENERGY;
2419 break;
2420 case FORM_TRAVEL:
2421 modelid = 632;
2422 break;
2423 case FORM_AQUA:
2424 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2425 modelid = 2428;
2426 else
2427 modelid = 2428;
2428 break;
2429 case FORM_BEAR:
2430 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2431 modelid = 2281;
2432 else
2433 modelid = 2289;
2434 PowerType = POWER_RAGE;
2435 break;
2436 case FORM_GHOUL:
2437 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2438 modelid = 10045;
2439 break;
2440 case FORM_DIREBEAR:
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_CREATUREBEAR:
2448 modelid = 902;
2449 break;
2450 case FORM_GHOSTWOLF:
2451 modelid = 4613;
2452 break;
2453 case FORM_FLIGHT:
2454 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2455 modelid = 20857;
2456 else
2457 modelid = 20872;
2458 break;
2459 case FORM_MOONKIN:
2460 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2461 modelid = 15374;
2462 else
2463 modelid = 15375;
2464 break;
2465 case FORM_FLIGHT_EPIC:
2466 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2467 modelid = 21243;
2468 else
2469 modelid = 21244;
2470 break;
2471 case FORM_AMBIENT:
2472 case FORM_SHADOW:
2473 case FORM_STEALTH:
2474 break;
2475 case FORM_TREE:
2476 modelid = 864;
2477 break;
2478 case FORM_BATTLESTANCE:
2479 case FORM_BERSERKERSTANCE:
2480 case FORM_DEFENSIVESTANCE:
2481 PowerType = POWER_RAGE;
2482 break;
2483 case FORM_SPIRITOFREDEMPTION:
2484 modelid = 16031;
2485 break;
2486 default:
2487 sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
2490 // remove polymorph before changing display id to keep new display id
2491 switch ( form )
2493 case FORM_CAT:
2494 case FORM_TREE:
2495 case FORM_TRAVEL:
2496 case FORM_AQUA:
2497 case FORM_BEAR:
2498 case FORM_DIREBEAR:
2499 case FORM_FLIGHT_EPIC:
2500 case FORM_FLIGHT:
2501 case FORM_MOONKIN:
2502 // remove movement affects
2503 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2504 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2506 // and polymorphic affects
2507 if(m_target->IsPolymorphed())
2508 m_target->RemoveAurasDueToSpell(m_target->getTransForm());
2509 break;
2510 default:
2511 break;
2514 if(apply)
2516 // remove other shapeshift before applying a new one
2517 if(m_target->m_ShapeShiftFormSpellId)
2518 m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
2520 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
2522 if(modelid > 0)
2523 m_target->SetDisplayId(modelid);
2525 if(PowerType != POWER_MANA)
2527 // reset power to default values only at power change
2528 if(m_target->getPowerType()!=PowerType)
2529 m_target->setPowerType(PowerType);
2531 switch(form)
2533 case FORM_CAT:
2534 case FORM_BEAR:
2535 case FORM_DIREBEAR:
2537 // get furor proc chance
2538 uint32 FurorChance = 0;
2539 Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2540 for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
2542 if ((*i)->GetSpellProto()->SpellIconID == 238)
2544 FurorChance = (*i)->GetModifier()->m_amount;
2545 break;
2549 if (m_modifier.m_miscvalue == FORM_CAT)
2551 m_target->SetPower(POWER_ENERGY,0);
2552 if(urand(1,100) <= FurorChance)
2553 m_target->CastSpell(m_target,17099,true,NULL,this);
2555 else
2557 m_target->SetPower(POWER_RAGE,0);
2558 if(urand(1,100) <= FurorChance)
2559 m_target->CastSpell(m_target,17057,true,NULL,this);
2561 break;
2563 case FORM_BATTLESTANCE:
2564 case FORM_DEFENSIVESTANCE:
2565 case FORM_BERSERKERSTANCE:
2567 uint32 Rage_val = 0;
2568 // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
2569 if(m_target->GetTypeId() == TYPEID_PLAYER)
2571 PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
2572 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2574 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
2575 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2576 if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
2577 Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
2581 if (m_target->GetPower(POWER_RAGE) > Rage_val)
2582 m_target->SetPower(POWER_RAGE,Rage_val);
2583 break;
2585 default:
2586 break;
2590 m_target->m_ShapeShiftFormSpellId = GetId();
2591 m_target->m_form = form;
2593 else
2595 if(modelid > 0)
2596 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2597 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
2598 if(m_target->getClass() == CLASS_DRUID)
2599 m_target->setPowerType(POWER_MANA);
2600 m_target->m_ShapeShiftFormSpellId = 0;
2601 m_target->m_form = FORM_NONE;
2603 switch(form)
2605 // Nordrassil Harness - bonus
2606 case FORM_BEAR:
2607 case FORM_DIREBEAR:
2608 case FORM_CAT:
2610 if(Aura* dummy = m_target->GetDummyAura(37315) )
2611 m_target->CastSpell(m_target,37316,true,NULL,dummy);
2612 break;
2614 // Nordrassil Regalia - bonus
2615 case FORM_MOONKIN:
2617 if(Aura* dummy = m_target->GetDummyAura(37324) )
2618 m_target->CastSpell(m_target,37325,true,NULL,dummy);
2619 break;
2624 // adding/removing linked auras
2625 // add/remove the shapeshift aura's boosts
2626 HandleShapeshiftBoosts(apply);
2628 if(m_target->GetTypeId()==TYPEID_PLAYER)
2629 ((Player*)m_target)->InitDataForForm();
2632 void Aura::HandleAuraTransform(bool apply, bool Real)
2634 if (apply)
2636 // special case (spell specific functionality)
2637 if(m_modifier.m_miscvalue==0)
2639 // player applied only
2640 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2641 return;
2643 switch(GetId())
2645 // Orb of Deception
2646 case 16739:
2648 uint32 orb_model = m_target->GetNativeDisplayId();
2649 switch(orb_model)
2651 // Troll Female
2652 case 1479: m_target->SetDisplayId(10134); break;
2653 // Troll Male
2654 case 1478: m_target->SetDisplayId(10135); break;
2655 // Tauren Male
2656 case 59: m_target->SetDisplayId(10136); break;
2657 // Human Male
2658 case 49: m_target->SetDisplayId(10137); break;
2659 // Human Female
2660 case 50: m_target->SetDisplayId(10138); break;
2661 // Orc Male
2662 case 51: m_target->SetDisplayId(10139); break;
2663 // Orc Female
2664 case 52: m_target->SetDisplayId(10140); break;
2665 // Dwarf Male
2666 case 53: m_target->SetDisplayId(10141); break;
2667 // Dwarf Female
2668 case 54: m_target->SetDisplayId(10142); break;
2669 // NightElf Male
2670 case 55: m_target->SetDisplayId(10143); break;
2671 // NightElf Female
2672 case 56: m_target->SetDisplayId(10144); break;
2673 // Undead Female
2674 case 58: m_target->SetDisplayId(10145); break;
2675 // Undead Male
2676 case 57: m_target->SetDisplayId(10146); break;
2677 // Tauren Female
2678 case 60: m_target->SetDisplayId(10147); break;
2679 // Gnome Male
2680 case 1563: m_target->SetDisplayId(10148); break;
2681 // Gnome Female
2682 case 1564: m_target->SetDisplayId(10149); break;
2683 // BloodElf Female
2684 case 15475: m_target->SetDisplayId(17830); break;
2685 // BloodElf Male
2686 case 15476: m_target->SetDisplayId(17829); break;
2687 // Dranei Female
2688 case 16126: m_target->SetDisplayId(17828); break;
2689 // Dranei Male
2690 case 16125: m_target->SetDisplayId(17827); break;
2691 default: break;
2693 break;
2695 // Murloc costume
2696 case 42365: m_target->SetDisplayId(21723); break;
2697 default: break;
2700 else
2702 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2703 if(!ci)
2705 //pig pink ^_^
2706 m_target->SetDisplayId(16358);
2707 sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
2709 else
2711 // Will use the default model here
2712 m_target->SetDisplayId(ci->DisplayID_A);
2714 // Dragonmaw Illusion (set mount model also)
2715 if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
2716 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
2718 m_target->setTransForm(GetId());
2721 // polymorph case
2722 if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
2724 // for players, start regeneration after 1s (in polymorph fast regeneration case)
2725 // only if caster is Player (after patch 2.4.2)
2726 if(IS_PLAYER_GUID(GetCasterGUID()) )
2727 ((Player*)m_target)->setRegenTimer(1000);
2729 //dismount polymorphed target (after patch 2.4.2)
2730 if (m_target->IsMounted())
2731 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2734 else
2736 Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
2737 if(otherTransforms.empty())
2739 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2740 m_target->setTransForm(0);
2742 else
2744 // look for other transform auras
2745 Aura* handledAura = *otherTransforms.begin();
2746 for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
2748 // negative auras are preferred
2749 if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
2751 handledAura = *i;
2752 break;
2755 handledAura->ApplyModifier(true);
2758 // Dragonmaw Illusion (restore mount model)
2759 if(GetId()==42016 && m_target->GetMountID()==16314)
2761 if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
2763 uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
2764 if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
2766 uint32 team = 0;
2767 if (m_target->GetTypeId()==TYPEID_PLAYER)
2768 team = ((Player*)m_target)->GetTeam();
2770 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2771 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2772 if (minfo)
2773 display_id = minfo->modelid;
2775 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
2782 void Aura::HandleForceReaction(bool apply, bool Real)
2784 if(m_target->GetTypeId() != TYPEID_PLAYER)
2785 return;
2787 if(!Real)
2788 return;
2790 Player* player = (Player*)m_target;
2792 uint32 faction_id = m_modifier.m_miscvalue;
2793 uint32 faction_rank = m_modifier.m_amount;
2795 if(apply)
2796 player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
2797 else
2798 player->m_forcedReactions.erase(faction_id);
2800 WorldPacket data;
2801 data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
2802 data << uint32(player->m_forcedReactions.size());
2803 for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
2805 data << uint32(itr->first); // faction_id (Faction.dbc)
2806 data << uint32(itr->second); // reputation rank
2808 player->SendDirectMessage(&data);
2811 void Aura::HandleAuraModSkill(bool apply, bool Real)
2813 if(m_target->GetTypeId() != TYPEID_PLAYER)
2814 return;
2816 uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
2817 int32 points = GetModifier()->m_amount;
2819 ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
2820 if(prot == SKILL_DEFENSE)
2821 ((Player*)m_target)->UpdateDefenseBonusesMod();
2824 void Aura::HandleChannelDeathItem(bool apply, bool Real)
2826 if(Real && !apply)
2828 Unit* caster = GetCaster();
2829 Unit* victim = GetTarget();
2830 if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
2831 return;
2833 SpellEntry const *spellInfo = GetSpellProto();
2834 if(spellInfo->EffectItemType[m_effIndex] == 0)
2835 return;
2837 // Soul Shard only from non-grey units
2838 if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
2839 (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
2840 victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
2841 return;
2842 ItemPosCountVec dest;
2843 uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
2844 if( msg != EQUIP_ERR_OK )
2846 ((Player*)caster)->SendEquipError( msg, NULL, NULL );
2847 return;
2850 Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
2851 ((Player*)caster)->SendNewItem(newitem, 1, true, false);
2855 void Aura::HandleBindSight(bool apply, bool Real)
2857 Unit* caster = GetCaster();
2858 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2859 return;
2861 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2864 void Aura::HandleFarSight(bool apply, bool Real)
2866 Unit* caster = GetCaster();
2867 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2868 return;
2870 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2873 void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
2875 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2876 return;
2878 if(apply)
2879 m_target->RemoveNoStackAurasDueToAura(this);
2880 m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
2883 void Aura::HandleAuraTrackResources(bool apply, bool Real)
2885 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2886 return;
2888 if(apply)
2889 m_target->RemoveNoStackAurasDueToAura(this);
2890 m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
2893 void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
2895 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2896 return;
2898 if(apply)
2899 m_target->RemoveNoStackAurasDueToAura(this);
2901 m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
2904 void Aura::HandleAuraModScale(bool apply, bool Real)
2906 m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
2909 void Aura::HandleModPossess(bool apply, bool Real)
2911 if(!Real)
2912 return;
2914 if(m_target->getLevel() > m_modifier.m_amount)
2915 return;
2917 // not possess yourself
2918 if(GetCasterGUID() == m_target->GetGUID())
2919 return;
2921 Unit* caster = GetCaster();
2922 if(!caster)
2923 return;
2925 if( apply )
2927 m_target->SetCharmerGUID(GetCasterGUID());
2928 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
2929 caster->SetCharm(m_target);
2931 m_target->CombatStop();
2932 m_target->DeleteThreatList();
2933 if(m_target->GetTypeId() == TYPEID_UNIT)
2935 m_target->StopMoving();
2936 m_target->GetMotionMaster()->Clear();
2937 m_target->GetMotionMaster()->MoveIdle();
2938 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
2939 charmInfo->InitPossessCreateSpells();
2942 if(caster->GetTypeId() == TYPEID_PLAYER)
2944 ((Player*)caster)->PossessSpellInitialize();
2947 else
2949 m_target->SetCharmerGUID(0);
2951 if(m_target->GetTypeId() == TYPEID_PLAYER)
2952 ((Player*)m_target)->setFactionForRace(m_target->getRace());
2953 else if(m_target->GetTypeId() == TYPEID_UNIT)
2955 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
2956 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
2959 caster->SetCharm(0);
2961 if(caster->GetTypeId() == TYPEID_PLAYER)
2963 WorldPacket data(SMSG_PET_SPELLS, 8);
2964 data << uint64(0);
2965 data << uint32(0);
2966 ((Player*)caster)->GetSession()->SendPacket(&data);
2968 if(m_target->GetTypeId() == TYPEID_UNIT)
2970 ((Creature*)m_target)->AIM_Initialize();
2972 if (((Creature*)m_target)->AI())
2973 ((Creature*)m_target)->AI()->AttackStart(caster);
2976 if(caster->GetTypeId() == TYPEID_PLAYER)
2977 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2980 void Aura::HandleModPossessPet(bool apply, bool Real)
2982 if(!Real)
2983 return;
2985 Unit* caster = GetCaster();
2986 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2987 return;
2988 if(caster->GetPet() != m_target)
2989 return;
2991 if(apply)
2992 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2993 else
2994 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2996 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2997 ((Player*)caster)->SetCharm(apply ? m_target : NULL);
2998 ((Player*)caster)->SetClientControl(m_target, apply ? 1 : 0);
3001 void Aura::HandleModCharm(bool apply, bool Real)
3003 if(!Real)
3004 return;
3006 // not charm yourself
3007 if(GetCasterGUID() == m_target->GetGUID())
3008 return;
3010 Unit* caster = GetCaster();
3011 if(!caster)
3012 return;
3014 if(int32(m_target->getLevel()) <= m_modifier.m_amount)
3016 if( apply )
3018 m_target->SetCharmerGUID(GetCasterGUID());
3019 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
3020 m_target->CastStop(m_target==caster ? GetId() : 0);
3021 caster->SetCharm(m_target);
3023 m_target->CombatStop();
3024 m_target->DeleteThreatList();
3026 if(m_target->GetTypeId() == TYPEID_UNIT)
3028 ((Creature*)m_target)->AIM_Initialize();
3029 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3030 charmInfo->InitCharmCreateSpells();
3031 charmInfo->SetReactState( REACT_DEFENSIVE );
3033 if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
3035 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3036 if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
3038 //to prevent client crash
3039 m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
3040 //just to enable stat window
3041 charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
3042 //if charmed two demons the same session, the 2nd gets the 1st one's name
3043 m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
3048 if(caster->GetTypeId() == TYPEID_PLAYER)
3050 ((Player*)caster)->CharmSpellInitialize();
3053 else
3055 m_target->SetCharmerGUID(0);
3057 if(m_target->GetTypeId() == TYPEID_PLAYER)
3058 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3059 else
3061 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3063 // restore faction
3064 if(((Creature*)m_target)->isPet())
3066 if(Unit* owner = m_target->GetOwner())
3067 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
3068 else if(cinfo)
3069 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3071 else if(cinfo) // normal creature
3072 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3074 // restore UNIT_FIELD_BYTES_0
3075 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
3077 CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
3078 if(cainfo && cainfo->bytes0 != 0)
3079 m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
3080 else
3081 m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
3083 if(m_target->GetCharmInfo())
3084 m_target->GetCharmInfo()->SetPetNumber(0, true);
3085 else
3086 sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
3090 caster->SetCharm(0);
3092 if(caster->GetTypeId() == TYPEID_PLAYER)
3094 WorldPacket data(SMSG_PET_SPELLS, 8);
3095 data << uint64(0);
3096 data << uint32(0);
3097 ((Player*)caster)->GetSession()->SendPacket(&data);
3099 if(m_target->GetTypeId() == TYPEID_UNIT)
3101 ((Creature*)m_target)->AIM_Initialize();
3102 if (((Creature*)m_target)->AI())
3103 ((Creature*)m_target)->AI()->AttackStart(caster);
3109 void Aura::HandleModConfuse(bool apply, bool Real)
3111 if(!Real)
3112 return;
3114 m_target->SetConfused(apply, GetCasterGUID(), GetId());
3117 void Aura::HandleModFear(bool apply, bool Real)
3119 if (!Real)
3120 return;
3122 m_target->SetFeared(apply, GetCasterGUID(), GetId());
3125 void Aura::HandleFeignDeath(bool apply, bool Real)
3127 if(!Real)
3128 return;
3130 if(m_target->GetTypeId() != TYPEID_PLAYER)
3131 return;
3133 if( apply )
3136 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3137 data<<m_target->GetGUID();
3138 data<<uint8(0);
3139 m_target->SendMessageToSet(&data,true);
3141 // blizz like 2.0.x
3142 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3143 // blizz like 2.0.x
3144 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3145 // blizz like 2.0.x
3146 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3148 m_target->addUnitState(UNIT_STAT_DIED);
3149 m_target->CombatStop();
3151 // prevent interrupt message
3152 if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
3153 m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
3154 m_target->InterruptNonMeleeSpells(true);
3155 m_target->getHostilRefManager().deleteReferences();
3157 else
3160 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3161 data<<m_target->GetGUID();
3162 data<<uint8(1);
3163 m_target->SendMessageToSet(&data,true);
3165 // blizz like 2.0.x
3166 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3167 // blizz like 2.0.x
3168 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3169 // blizz like 2.0.x
3170 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3172 m_target->clearUnitState(UNIT_STAT_DIED);
3176 void Aura::HandleAuraModDisarm(bool apply, bool Real)
3178 if(!Real)
3179 return;
3181 if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
3182 return;
3184 // not sure for it's correctness
3185 if(apply)
3186 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3187 else
3188 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3190 // only at real add/remove aura
3191 if (m_target->GetTypeId() != TYPEID_PLAYER)
3192 return;
3194 // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
3195 if (((Player *)m_target)->IsInFeralForm())
3196 return;
3198 if (apply)
3199 m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
3200 else
3201 ((Player *)m_target)->SetRegularAttackTime();
3203 m_target->UpdateDamagePhysical(BASE_ATTACK);
3206 void Aura::HandleAuraModStun(bool apply, bool Real)
3208 if(!Real)
3209 return;
3211 if (apply)
3213 m_target->addUnitState(UNIT_STAT_STUNNED);
3214 m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
3216 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3217 m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
3219 // Creature specific
3220 if(m_target->GetTypeId() != TYPEID_PLAYER)
3221 ((Creature*)m_target)->StopMoving();
3222 else
3223 m_target->SetUnitMovementFlags(0); //Clear movement flags
3225 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
3227 data.append(m_target->GetPackGUID());
3228 data << uint32(0);
3229 m_target->SendMessageToSet(&data,true);
3231 else
3233 // Real remove called after current aura remove from lists, check if other similar auras active
3234 if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
3235 return;
3237 m_target->clearUnitState(UNIT_STAT_STUNNED);
3238 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3240 if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
3242 if(m_target->getVictim() && m_target->isAlive())
3243 m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3245 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
3246 data.append(m_target->GetPackGUID());
3247 data << uint32(0);
3248 m_target->SendMessageToSet(&data,true);
3251 // Wyvern Sting
3252 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
3254 Unit* caster = GetCaster();
3255 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
3256 return;
3258 uint32 spell_id = 0;
3260 switch(GetId())
3262 case 19386: spell_id = 24131; break;
3263 case 24132: spell_id = 24134; break;
3264 case 24133: spell_id = 24135; break;
3265 case 27068: spell_id = 27069; break;
3266 default:
3267 sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
3268 return;
3271 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
3273 if(!spellInfo)
3274 return;
3276 caster->CastSpell(m_target,spellInfo,true,NULL,this);
3277 return;
3282 void Aura::HandleModStealth(bool apply, bool Real)
3284 if(apply)
3286 // drop flag at stealth in bg
3287 if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
3288 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3289 bg->EventPlayerDroppedFlag((Player*)m_target);
3291 // only at real aura add
3292 if(Real)
3294 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
3295 if(m_target->GetTypeId()==TYPEID_PLAYER)
3296 m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
3298 // apply only if not in GM invisibility (and overwrite invisibility state)
3299 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3301 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3302 m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
3305 // for RACE_NIGHTELF stealth
3306 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3307 m_target->CastSpell(m_target, 21009, true, NULL, this);
3310 else
3312 // only at real aura remove
3313 if(Real)
3315 // for RACE_NIGHTELF stealth
3316 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3317 m_target->RemoveAurasDueToSpell(21009);
3319 // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
3320 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
3322 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
3323 if(m_target->GetTypeId()==TYPEID_PLAYER)
3324 m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
3326 // restore invisibility if any
3327 if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
3329 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3330 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3332 else
3333 m_target->SetVisibility(VISIBILITY_ON);
3338 // Master of Subtlety
3339 Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
3340 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
3342 if ((*i)->GetSpellProto()->SpellIconID == 2114)
3344 if (apply)
3346 int32 bp = (*i)->GetModifier()->m_amount;
3347 m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
3349 else
3350 m_target->CastSpell(m_target,31666,true);
3351 break;
3356 void Aura::HandleInvisibility(bool apply, bool Real)
3358 if(apply)
3360 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3362 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3364 // apply glow vision
3365 m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3367 // drop flag at invisible in bg
3368 if(((Player*)m_target)->InBattleGround())
3369 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3370 bg->EventPlayerDroppedFlag((Player*)m_target);
3373 // apply only if not in GM invisibility and not stealth
3374 if(m_target->GetVisibility()==VISIBILITY_ON)
3376 // Aura not added yet but visibility code expect temporary add aura
3377 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3378 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3381 else
3383 // recalculate value at modifier remove (current aura already removed)
3384 m_target->m_invisibilityMask = 0;
3385 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
3386 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3387 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3389 // only at real aura remove and if not have different invisibility auras.
3390 if(Real && m_target->m_invisibilityMask==0)
3392 // remove glow vision
3393 if(m_target->GetTypeId() == TYPEID_PLAYER)
3394 m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3396 // apply only if not in GM invisibility & not stealthed while invisible
3397 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3399 // if have stealth aura then already have stealth visibility
3400 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
3401 m_target->SetVisibility(VISIBILITY_ON);
3407 void Aura::HandleInvisibilityDetect(bool apply, bool Real)
3409 if(apply)
3411 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3413 else
3415 // recalculate value at modifier remove (current aura already removed)
3416 m_target->m_detectInvisibilityMask = 0;
3417 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
3418 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3419 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3421 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3422 ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
3425 void Aura::HandleAuraModRoot(bool apply, bool Real)
3427 // only at real add/remove aura
3428 if(!Real)
3429 return;
3431 uint32 apply_stat = UNIT_STAT_ROOT;
3432 if (apply)
3434 m_target->addUnitState(UNIT_STAT_ROOT);
3435 m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
3436 // probably wrong
3437 m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3439 //Save last orientation
3440 if( m_target->getVictim() )
3441 m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
3443 if(m_target->GetTypeId() == TYPEID_PLAYER)
3445 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
3446 data.append(m_target->GetPackGUID());
3447 data << (uint32)2;
3448 m_target->SendMessageToSet(&data,true);
3450 //Clear unit movement flags
3451 m_target->SetUnitMovementFlags(0);
3453 else
3454 ((Creature *)m_target)->StopMoving();
3456 else
3458 // Real remove called after current aura remove from lists, check if other similar auras active
3459 if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
3460 return;
3462 m_target->clearUnitState(UNIT_STAT_ROOT);
3463 // probably wrong
3464 m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3466 if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
3468 if(m_target->getVictim() && m_target->isAlive())
3469 m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3471 if(m_target->GetTypeId() == TYPEID_PLAYER)
3473 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
3474 data.append(m_target->GetPackGUID());
3475 data << (uint32)2;
3476 m_target->SendMessageToSet(&data,true);
3482 void Aura::HandleAuraModSilence(bool apply, bool Real)
3484 // only at real add/remove aura
3485 if(!Real)
3486 return;
3488 if(apply)
3490 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3491 // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3492 for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
3494 Spell* currentSpell = m_target->m_currentSpells[i];
3495 if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
3497 uint32 state = currentSpell->getState();
3498 // Stop spells on prepare or casting state
3499 if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
3501 currentSpell->cancel();
3502 currentSpell->SetReferencedFromCurrent(false);
3503 m_target->m_currentSpells[i] = NULL;
3508 switch (GetId())
3510 // Arcane Torrent (Energy)
3511 case 25046:
3513 Unit * caster = GetCaster();
3514 if (!caster)
3515 return;
3517 // Search Mana Tap auras on caster
3518 int32 energy = 0;
3519 Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
3520 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3521 if ((*i)->GetId() == 28734)
3522 ++energy;
3523 if (energy)
3525 energy *= 10;
3526 caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true);
3527 caster->RemoveAurasDueToSpell(28734);
3532 else
3534 // Real remove called after current aura remove from lists, check if other similar auras active
3535 if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
3536 return;
3538 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3542 void Aura::HandleModThreat(bool apply, bool Real)
3544 // only at real add/remove aura
3545 if(!Real)
3546 return;
3548 if(!m_target->isAlive())
3549 return;
3551 Unit* caster = GetCaster();
3553 if(!caster || !caster->isAlive())
3554 return;
3556 int level_diff = 0;
3557 int multiplier = 0;
3558 switch (GetId())
3560 // Arcane Shroud
3561 case 26400:
3562 level_diff = m_target->getLevel() - 60;
3563 multiplier = 2;
3564 break;
3565 // The Eye of Diminution
3566 case 28862:
3567 level_diff = m_target->getLevel() - 60;
3568 multiplier = 1;
3569 break;
3571 if (level_diff > 0)
3572 m_modifier.m_amount += multiplier * level_diff;
3574 for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
3576 if(m_modifier.m_miscvalue & int32(1<<x))
3578 if(m_target->GetTypeId() == TYPEID_PLAYER)
3579 ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
3584 void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
3586 // only at real add/remove aura
3587 if(!Real)
3588 return;
3590 if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
3591 return;
3593 Unit* caster = GetCaster();
3595 if(!caster || !caster->isAlive())
3596 return;
3598 float threatMod = 0.0f;
3599 if(apply)
3600 threatMod = float(m_modifier.m_amount);
3601 else
3602 threatMod = float(-m_modifier.m_amount);
3604 m_target->getHostilRefManager().threatAssist(caster, threatMod);
3607 void Aura::HandleModTaunt(bool apply, bool Real)
3609 // only at real add/remove aura
3610 if(!Real)
3611 return;
3613 if(!m_target->isAlive() || !m_target->CanHaveThreatList())
3614 return;
3616 Unit* caster = GetCaster();
3618 if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
3619 return;
3621 if(apply)
3622 m_target->TauntApply(caster);
3623 else
3625 // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
3626 m_target->TauntFadeOut(caster);
3630 /*********************************************************/
3631 /*** MODIFY SPEED ***/
3632 /*********************************************************/
3633 void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real)
3635 // all applied/removed only at real aura add/remove
3636 if(!Real)
3637 return;
3639 m_target->UpdateSpeed(MOVE_RUN, true);
3642 void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real)
3644 // all applied/removed only at real aura add/remove
3645 if(!Real)
3646 return;
3648 m_target->UpdateSpeed(MOVE_RUN, true);
3651 void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
3653 // all applied/removed only at real aura add/remove
3654 if(!Real)
3655 return;
3657 // Enable Fly mode for flying mounts
3658 if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
3660 WorldPacket data;
3661 if(apply)
3662 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
3663 else
3664 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
3665 data.append(m_target->GetPackGUID());
3666 data << uint32(0); // unknown
3667 m_target->SendMessageToSet(&data, true);
3669 //Players on flying mounts must be immune to polymorph
3670 if (m_target->GetTypeId()==TYPEID_PLAYER)
3671 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
3673 // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
3674 if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
3675 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
3678 m_target->UpdateSpeed(MOVE_FLY, true);
3681 void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
3683 // all applied/removed only at real aura add/remove
3684 if(!Real)
3685 return;
3687 m_target->UpdateSpeed(MOVE_SWIM, true);
3690 void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
3692 // all applied/removed only at real aura add/remove
3693 if(!Real)
3694 return;
3696 m_target->UpdateSpeed(MOVE_RUN, true);
3697 m_target->UpdateSpeed(MOVE_SWIM, true);
3698 m_target->UpdateSpeed(MOVE_FLY, true);
3701 void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
3703 // all applied/removed only at real aura add/remove
3704 if(!Real)
3705 return;
3707 m_target->UpdateSpeed(MOVE_RUN, true);
3708 m_target->UpdateSpeed(MOVE_SWIM, true);
3709 m_target->UpdateSpeed(MOVE_FLY, true);
3712 /*********************************************************/
3713 /*** IMMUNITY ***/
3714 /*********************************************************/
3716 void Aura::HandleModMechanicImmunity(bool apply, bool Real)
3718 uint32 mechanic = 1 << m_modifier.m_miscvalue;
3720 //immune movement impairment and loss of control
3721 if(GetId()==42292)
3722 mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
3724 if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3726 Unit::AuraMap& Auras = m_target->GetAuras();
3727 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3729 next = iter;
3730 ++next;
3731 SpellEntry const *spell = iter->second->GetSpellProto();
3732 if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
3733 && !iter->second->IsPositive() // only remove negative spells
3734 && spell->Id != GetId())
3736 //check for mechanic mask
3737 if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
3739 m_target->RemoveAurasDueToSpell(spell->Id);
3740 if(Auras.empty())
3741 break;
3742 else
3743 next = Auras.begin();
3749 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
3751 // special cases
3752 switch(m_modifier.m_miscvalue)
3754 case MECHANIC_INVULNERABILITY:
3755 m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply);
3756 break;
3757 case MECHANIC_SHIELD:
3758 m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply);
3759 break;
3762 // Bestial Wrath
3763 if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
3765 // The Beast Within cast on owner if talent present
3766 if ( Unit* owner = m_target->GetOwner() )
3768 // Search talent
3769 Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
3770 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3772 if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
3774 if (apply)
3775 owner->CastSpell(owner, 34471, true, 0, this);
3776 else
3777 owner->RemoveAurasDueToSpell(34471);
3778 break;
3784 // The Beast Within and Bestial Wrath - immunity
3785 if(GetId() == 19574 || GetId() == 34471)
3787 if(apply)
3789 m_target->CastSpell(m_target,24395,true);
3790 m_target->CastSpell(m_target,24396,true);
3791 m_target->CastSpell(m_target,24397,true);
3792 m_target->CastSpell(m_target,26592,true);
3794 else
3796 m_target->RemoveAurasDueToSpell(24395);
3797 m_target->RemoveAurasDueToSpell(24396);
3798 m_target->RemoveAurasDueToSpell(24397);
3799 m_target->RemoveAurasDueToSpell(26592);
3804 void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
3806 if(!apply)
3808 if(m_target->GetTypeId() == TYPEID_PLAYER)
3810 if(((Player*)m_target)->InBattleGround())
3812 BattleGround *bg = ((Player*)m_target)->GetBattleGround();
3813 if(bg)
3815 switch(bg->GetTypeID())
3817 case BATTLEGROUND_AV:
3819 break;
3821 case BATTLEGROUND_WS:
3823 // Warsong Flag, horde // Silverwing Flag, alliance
3824 if(GetId() == 23333 || GetId() == 23335)
3825 bg->EventPlayerDroppedFlag(((Player*)m_target));
3826 break;
3828 case BATTLEGROUND_AB:
3830 break;
3832 case BATTLEGROUND_EY:
3834 if(GetId() == 34976)
3835 bg->EventPlayerDroppedFlag(((Player*)m_target));
3836 break;
3844 m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
3847 void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
3849 if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3851 Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
3852 for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
3854 if (auraList.front() != this) // skip itself aura (it already added)
3856 m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
3857 itr = auraList.begin();
3859 else
3860 ++itr;
3864 m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
3867 void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
3869 m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
3871 if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3873 if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
3875 uint32 school_mask = m_modifier.m_miscvalue;
3876 Unit::AuraMap& Auras = m_target->GetAuras();
3877 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3879 next = iter;
3880 ++next;
3881 SpellEntry const *spell = iter->second->GetSpellProto();
3882 if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
3883 && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
3884 && !iter->second->IsPositive() //Don't remove positive spells
3885 && spell->Id != GetId() ) //Don't remove self
3887 m_target->RemoveAurasDueToSpell(spell->Id);
3888 if(Auras.empty())
3889 break;
3890 else
3891 next = Auras.begin();
3896 if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
3898 if( apply )
3899 m_target->addUnitState(UNIT_STAT_ISOLATED);
3900 else
3901 m_target->clearUnitState(UNIT_STAT_ISOLATED);
3905 void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
3907 m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
3910 void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
3912 // all applied/removed only at real aura add/remove
3913 if(!Real)
3914 return;
3916 m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
3919 void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
3921 if(!Real)
3922 return;
3924 if(apply)
3926 // some spell have charges by functionality not have its in spell data
3927 switch (GetId())
3929 case 28200: // Ascendance (Talisman of Ascendance trinket)
3930 m_procCharges = 6;
3931 UpdateAuraCharges();
3932 break;
3933 default: break;
3938 void Aura::HandleAuraModStalked(bool apply, bool Real)
3940 // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
3941 if(apply)
3942 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3943 else
3944 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3947 /*********************************************************/
3948 /*** PERIODIC ***/
3949 /*********************************************************/
3951 void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
3953 if (m_periodicTimer <= 0)
3954 m_periodicTimer += m_modifier.periodictime;
3956 m_isPeriodic = apply;
3957 m_isTrigger = apply;
3959 // Curse of the Plaguebringer
3960 if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL)
3962 // Cast Wrath of the Plaguebringer if not dispelled
3963 m_target->CastSpell(m_target, 29214, true, 0, this);
3967 void Aura::HandlePeriodicEnergize(bool apply, bool Real)
3969 if (m_periodicTimer <= 0)
3970 m_periodicTimer += m_modifier.periodictime;
3972 m_isPeriodic = apply;
3975 void Aura::HandlePeriodicHeal(bool apply, bool Real)
3977 if (m_periodicTimer <= 0)
3978 m_periodicTimer += m_modifier.periodictime;
3980 m_isPeriodic = apply;
3982 // only at real apply
3983 if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE)
3985 // provided m_target as original caster to prevent apply aura caster selection for this negative buff
3986 m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID());
3989 // For prevent double apply bonuses
3990 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
3992 if(!loading && apply)
3994 switch (m_spellProto->SpellFamilyName)
3996 case SPELLFAMILY_DRUID:
3998 // Rejuvenation
3999 if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
4001 if(Unit* caster = GetCaster())
4003 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4004 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4006 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4007 switch((*k)->GetModifier()->m_miscvalue)
4009 case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
4010 case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
4012 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4013 break;
4024 void Aura::HandlePeriodicDamage(bool apply, bool Real)
4026 // spells required only Real aura add/remove
4027 if(!Real)
4028 return;
4030 if (m_periodicTimer <= 0)
4031 m_periodicTimer += m_modifier.periodictime;
4033 m_isPeriodic = apply;
4035 // For prevent double apply bonuses
4036 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4038 Unit *caster = GetCaster();
4040 switch (m_spellProto->SpellFamilyName)
4042 case SPELLFAMILY_GENERIC:
4044 // Pounce Bleed
4045 if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 )
4047 // $AP*0.18/6 bonus per tick
4048 if (apply && !loading && caster)
4049 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4050 return;
4052 break;
4054 case SPELLFAMILY_WARRIOR:
4056 // Rend
4057 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4059 // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
4060 if (apply && !loading && caster)
4062 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4063 int32 mws = caster->GetAttackTime(BASE_ATTACK);
4064 float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
4065 float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
4066 // WARNING! in 3.0 multiplier 0.00743f change to 0.6
4067 m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
4069 return;
4071 break;
4073 case SPELLFAMILY_DRUID:
4075 // Rake
4076 if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
4078 // $AP*0.06/3 bonus per tick
4079 if (apply && !loading && caster)
4080 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
4081 return;
4083 // Lacerate
4084 if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
4086 // $AP*0.05/5 bonus per tick
4087 if (apply && !loading && caster)
4088 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
4089 return;
4091 // Rip
4092 if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
4094 // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used]
4095 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4097 uint8 cp = ((Player*)caster)->GetComboPoints();
4099 // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
4100 Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
4101 for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
4103 if((*itr)->GetId()==34241)
4105 m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
4106 break;
4110 if (cp > 4) cp = 4;
4111 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4113 return;
4115 break;
4117 case SPELLFAMILY_ROGUE:
4119 // Deadly poison aura state
4120 if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual[0]==5100)
4122 if(apply)
4123 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
4124 else
4126 // current aura already removed, search present of another
4127 bool found = false;
4128 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
4129 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
4131 SpellEntry const* itr_spell = (*itr)->GetSpellProto();
4132 if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual[0]==5100)
4134 found = true;
4135 break;
4138 // this has been last deadly poison aura
4139 if(!found)
4140 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
4142 return;
4144 // Rupture
4145 if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
4147 // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP]
4148 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4150 uint8 cp = ((Player*)caster)->GetComboPoints();
4151 if (cp > 3) cp = 3;
4152 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4154 return;
4156 // Garrote
4157 if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
4159 // $AP*0.18/6 bonus per tick
4160 if (apply && !loading && caster)
4161 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4162 return;
4164 break;
4166 case SPELLFAMILY_HUNTER:
4168 // Serpent Sting
4169 if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
4171 // $RAP*0.1/5 bonus per tick
4172 if (apply && !loading && caster)
4173 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4174 return;
4176 // Immolation Trap
4177 if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
4179 // $RAP*0.1/5 bonus per tick
4180 if (apply && !loading && caster)
4181 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4182 return;
4184 break;
4186 case SPELLFAMILY_PALADIN:
4188 // Consecration
4189 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4191 if (apply && !loading)
4193 if(Unit* caster = GetCaster())
4195 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4196 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4198 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4199 switch((*k)->GetModifier()->m_miscvalue)
4201 case 5147: // Improved Consecration - Libram of the Eternal Rest
4203 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4204 break;
4210 return;
4212 break;
4214 default:
4215 break;
4219 void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
4221 if (m_periodicTimer <= 0)
4222 m_periodicTimer += m_modifier.periodictime;
4224 m_isPeriodic = apply;
4227 void Aura::HandlePeriodicLeech(bool apply, bool Real)
4229 if (m_periodicTimer <= 0)
4230 m_periodicTimer += m_modifier.periodictime;
4232 m_isPeriodic = apply;
4235 void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
4237 if (m_periodicTimer <= 0)
4238 m_periodicTimer += m_modifier.periodictime;
4240 m_isPeriodic = apply;
4243 /*********************************************************/
4244 /*** MODIFY STATS ***/
4245 /*********************************************************/
4247 /********************************/
4248 /*** RESISTANCE ***/
4249 /********************************/
4251 void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
4253 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4255 if(m_modifier.m_miscvalue & int32(1<<x))
4257 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
4258 if(m_target->GetTypeId() == TYPEID_PLAYER)
4259 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4264 void Aura::HandleAuraModResistance(bool apply, bool Real)
4266 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4268 if(m_modifier.m_miscvalue & int32(1<<x))
4270 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4271 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4272 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4276 // Faerie Fire (druid versions)
4277 if( m_spellProto->SpellIconID == 109 &&
4278 m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
4279 m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
4281 m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
4285 void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
4287 // only players have base stats
4288 if(m_target->GetTypeId() != TYPEID_PLAYER)
4290 //pets only have base armor
4291 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4292 m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
4294 else
4296 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4298 if(m_modifier.m_miscvalue & int32(1<<x))
4299 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
4304 void Aura::HandleModResistancePercent(bool apply, bool Real)
4306 for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4308 if(m_modifier.m_miscvalue & int32(1<<i))
4310 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4311 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4313 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
4314 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
4320 void Aura::HandleModBaseResistance(bool apply, bool Real)
4322 // only players have base stats
4323 if(m_target->GetTypeId() != TYPEID_PLAYER)
4325 //only pets have base stats
4326 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4327 m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4329 else
4331 for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4332 if(m_modifier.m_miscvalue & (1<<i))
4333 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4337 /********************************/
4338 /*** STAT ***/
4339 /********************************/
4341 void Aura::HandleAuraModStat(bool apply, bool Real)
4343 if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
4345 sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
4346 return;
4349 for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4351 // -1 or -2 is all stats ( misc < -2 checked in function beginning )
4352 if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
4354 //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
4355 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4356 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4357 m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
4362 void Aura::HandleModPercentStat(bool apply, bool Real)
4364 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4366 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4367 return;
4370 // only players have base stats
4371 if (m_target->GetTypeId() != TYPEID_PLAYER)
4372 return;
4374 for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
4376 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4377 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
4381 void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real)
4383 if(m_target->GetTypeId() != TYPEID_PLAYER)
4384 return;
4386 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4387 // This information for client side use only
4388 // Recalculate bonus
4389 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4392 void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real)
4394 if(m_target->GetTypeId() != TYPEID_PLAYER)
4395 return;
4397 // Recalculate bonus
4398 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4401 void Aura::HandleAuraModDispelResist(bool apply, bool Real)
4403 if(!Real || !apply)
4404 return;
4406 if(GetId()==33206)
4407 m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
4410 void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real)
4412 if(m_target->GetTypeId() != TYPEID_PLAYER)
4413 return;
4415 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4416 // This information for client side use only
4417 // Recalculate bonus
4418 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4421 void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real)
4423 if(m_target->GetTypeId() != TYPEID_PLAYER)
4424 return;
4426 // Recalculate bonus
4427 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4430 void Aura::HandleModHealingDone(bool /*apply*/, bool Real)
4432 if(m_target->GetTypeId() != TYPEID_PLAYER)
4433 return;
4434 // implemented in Unit::SpellHealingBonus
4435 // this information is for client side only
4436 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4439 void Aura::HandleModTotalPercentStat(bool apply, bool Real)
4441 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4443 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4444 return;
4447 //save current and max HP before applying aura
4448 uint32 curHPValue = m_target->GetHealth();
4449 uint32 maxHPValue = m_target->GetMaxHealth();
4451 for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4453 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4455 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4456 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4457 m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
4461 //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
4462 if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
4464 // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
4465 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
4466 m_target->SetHealth(newHPValue);
4470 void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
4472 if(m_target->GetTypeId() != TYPEID_PLAYER)
4473 return;
4475 if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
4477 // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
4478 // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
4479 sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
4480 return;
4483 // Recalculate Armor
4484 m_target->UpdateArmor();
4487 /********************************/
4488 /*** HEAL & ENERGIZE ***/
4489 /********************************/
4490 void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
4493 Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
4494 so this aura not fully working.
4496 if(apply)
4498 if(!m_target->isAlive())
4499 return;
4501 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4502 m_target->SetStandState(PLAYER_STATE_SIT);
4504 if(m_periodicTimer <= 0)
4506 m_periodicTimer += m_modifier.periodictime;
4508 if(m_target->GetHealth() < m_target->GetMaxHealth())
4510 // PeriodicTick can cast triggered spells with stats changes
4511 PeriodicTick();
4516 m_isPeriodic = apply;
4519 void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
4521 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4522 m_target->SetStandState(PLAYER_STATE_SIT);
4523 if(apply)
4525 if(m_modifier.periodictime == 0)
4526 m_modifier.periodictime = 1000;
4527 if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
4529 m_periodicTimer += m_modifier.periodictime;
4531 if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
4533 // PeriodicTick can cast triggered spells with stats changes
4534 PeriodicTick();
4539 m_isPeriodic = apply;
4542 void Aura::HandleModRegen(bool apply, bool Real) // eating
4544 if(apply)
4546 if(!m_target->isAlive())
4547 return;
4549 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4550 m_target->SetStandState(PLAYER_STATE_SIT);
4552 if(m_periodicTimer <= 0)
4554 m_periodicTimer += 5000;
4555 int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
4556 Unit *caster = GetCaster();
4557 if (caster)
4559 SpellEntry const *spellProto = GetSpellProto();
4560 if (spellProto)
4561 m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
4566 m_isPeriodic = apply;
4569 void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
4571 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4572 m_target->SetStandState(PLAYER_STATE_SIT);
4574 if(apply && m_periodicTimer <= 0)
4576 m_periodicTimer += 2000;
4578 Powers pt = m_target->getPowerType();
4579 if(int32(pt) != m_modifier.m_miscvalue)
4580 return;
4582 if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
4584 // eating anim
4585 m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
4587 else if( GetId() == 20577 )
4589 // cannibalize anim
4590 m_target->HandleEmoteCommand(398);
4593 // Warrior talent, gain 1 rage every 3 seconds while in combat
4594 if(pt == POWER_RAGE && m_target->isInCombat())
4596 m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
4597 m_periodicTimer += 1000;
4600 m_isPeriodic = apply;
4601 if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
4602 ((Player*)m_target)->UpdateManaRegen();
4605 void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
4607 // spells required only Real aura add/remove
4608 if(!Real)
4609 return;
4611 if (m_target->GetTypeId() != TYPEID_PLAYER)
4612 return;
4614 // Update manaregen value
4615 if (m_modifier.m_miscvalue == POWER_MANA)
4616 ((Player*)m_target)->UpdateManaRegen();
4619 void Aura::HandleModManaRegen(bool /*apply*/, bool Real)
4621 // spells required only Real aura add/remove
4622 if(!Real)
4623 return;
4625 if (m_target->GetTypeId() != TYPEID_PLAYER)
4626 return;
4628 //Note: an increase in regen does NOT cause threat.
4629 ((Player*)m_target)->UpdateManaRegen();
4632 void Aura::HandleComprehendLanguage(bool apply, bool Real)
4634 if(apply)
4635 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4636 else
4637 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4640 void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
4642 // Special case with temporary increase max/current health
4643 switch(GetId())
4645 case 12976: // Warrior Last Stand triggered spell
4646 case 28726: // Nightmare Seed ( Nightmare Seed )
4647 case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
4648 case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
4650 if(Real)
4652 if(apply)
4654 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4655 m_target->ModifyHealth(m_modifier.m_amount);
4657 else
4659 if (int32(m_target->GetHealth()) > m_modifier.m_amount)
4660 m_target->ModifyHealth(-m_modifier.m_amount);
4661 else
4662 m_target->SetHealth(1);
4663 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4666 return;
4670 // generic case
4671 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4674 void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
4676 uint32 oldhealth = m_target->GetHealth();
4677 double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
4679 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4681 // refresh percentage
4682 if(oldhealth > 0)
4684 uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
4685 if(newhealth==0)
4686 newhealth = 1;
4688 m_target->SetHealth(newhealth);
4692 void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
4694 Powers powerType = m_target->getPowerType();
4695 if(int32(powerType) != m_modifier.m_miscvalue)
4696 return;
4698 m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4701 void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool Real)
4703 Powers powerType = m_target->getPowerType();
4704 if(int32(powerType) != m_modifier.m_miscvalue)
4705 return;
4707 m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_PCT, float(m_modifier.m_amount), apply);
4710 void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real)
4712 //m_target->ApplyMaxHealthPercentMod(m_modifier.m_amount,apply);
4713 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
4716 /********************************/
4717 /*** FIGHT ***/
4718 /********************************/
4720 void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real)
4722 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4723 return;
4725 ((Player*)m_target)->UpdateParryPercentage();
4728 void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real)
4730 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4731 return;
4733 ((Player*)m_target)->UpdateDodgePercentage();
4734 //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
4737 void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real)
4739 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4740 return;
4742 ((Player*)m_target)->UpdateBlockPercentage();
4743 //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
4746 void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real)
4748 // spells required only Real aura add/remove
4749 if(!Real)
4750 return;
4752 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4753 return;
4755 ((Player*)m_target)->UpdateManaRegen();
4758 void Aura::HandleAuraModCritPercent(bool apply, bool Real)
4760 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4761 return;
4763 // apply item specific bonuses for already equipped weapon
4764 if(Real)
4766 for(int i = 0; i < MAX_ATTACK; ++i)
4767 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4768 ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
4771 // mods must be applied base at equipped weapon class and subclass comparison
4772 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4773 // m_modifier.m_miscvalue comparison with item generated damage types
4775 if (GetSpellProto()->EquippedItemClass == -1)
4777 ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4778 ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4779 ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4781 else
4783 // done in Player::_ApplyWeaponDependentAuraMods
4787 void Aura::HandleModHitChance(bool apply, bool Real)
4789 m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4790 m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4793 void Aura::HandleModSpellHitChance(bool apply, bool Real)
4795 m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
4798 void Aura::HandleModSpellCritChance(bool apply, bool Real)
4800 // spells required only Real aura add/remove
4801 if(!Real)
4802 return;
4804 if(m_target->GetTypeId() == TYPEID_PLAYER)
4806 ((Player*)m_target)->UpdateAllSpellCritChances();
4808 else
4810 m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
4814 void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
4816 // spells required only Real aura add/remove
4817 if(!Real)
4818 return;
4820 if(m_target->GetTypeId() != TYPEID_PLAYER)
4821 return;
4823 for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
4824 if (m_modifier.m_miscvalue & (1<<school))
4825 ((Player*)m_target)->UpdateSpellCritChance(school);
4828 /********************************/
4829 /*** ATTACK SPEED ***/
4830 /********************************/
4832 void Aura::HandleModCastingSpeed(bool apply, bool Real)
4834 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4837 void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
4839 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4840 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4841 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4844 void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
4846 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4847 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4848 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4849 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4852 void Aura::HandleModAttackSpeed(bool apply, bool Real)
4854 if(!m_target->isAlive() )
4855 return;
4857 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4860 void Aura::HandleHaste(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::HandleAuraModRangedHaste(bool apply, bool Real)
4869 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4872 void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
4874 if(m_target->GetTypeId() != TYPEID_PLAYER)
4875 return;
4876 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
4879 /********************************/
4880 /*** ATTACK POWER ***/
4881 /********************************/
4883 void Aura::HandleAuraModAttackPower(bool apply, bool Real)
4885 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4888 void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
4890 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4891 return;
4893 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4896 void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
4898 //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
4899 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
4902 void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
4904 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4905 return;
4907 //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
4908 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
4911 void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
4913 // spells required only Real aura add/remove
4914 if(!Real)
4915 return;
4917 if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4918 return;
4920 if(m_modifier.m_miscvalue != STAT_INTELLECT)
4922 // support required adding UpdateAttackPowerAndDamage calls at stat update
4923 sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intelect stats!");
4924 return;
4927 // Recalculate bonus
4928 ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
4931 /********************************/
4932 /*** DAMAGE BONUS ***/
4933 /********************************/
4934 void Aura::HandleModDamageDone(bool apply, bool Real)
4936 // apply item specific bonuses for already equipped weapon
4937 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
4939 for(int i = 0; i < MAX_ATTACK; ++i)
4940 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4941 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
4944 // m_modifier.m_miscvalue is bitmask of spell schools
4945 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
4946 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
4947 // 127 - full bitmask any damages
4949 // mods must be applied base at equipped weapon class and subclass comparison
4950 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4951 // m_modifier.m_miscvalue comparison with item generated damage types
4953 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
4955 // apply generic physical damage bonuses including wand case
4956 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
4958 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4959 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4960 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4962 else
4964 // done in Player::_ApplyWeaponDependentAuraMods
4967 if(m_target->GetTypeId() == TYPEID_PLAYER)
4969 if(m_positive)
4970 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
4971 else
4972 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
4976 // Skip non magic case for speedup
4977 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
4978 return;
4980 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
4982 // wand magic case (skip generic to all item spell bonuses)
4983 // done in Player::_ApplyWeaponDependentAuraMods
4985 // Skip item specific requirements for not wand magic damage
4986 return;
4989 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4990 // This information for client side use only
4991 if(m_target->GetTypeId() == TYPEID_PLAYER)
4993 if(m_positive)
4995 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
4997 if((m_modifier.m_miscvalue & (1<<i)) != 0)
4998 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
5001 else
5003 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5005 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5006 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
5009 Pet* pet = m_target->GetPet();
5010 if(pet)
5011 pet->UpdateAttackPowerAndDamage();
5015 void Aura::HandleModDamagePercentDone(bool apply, bool Real)
5017 sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
5019 // apply item specific bonuses for already equipped weapon
5020 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5022 for(int i = 0; i < MAX_ATTACK; ++i)
5023 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5024 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5027 // m_modifier.m_miscvalue is bitmask of spell schools
5028 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5029 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
5030 // 127 - full bitmask any damages
5032 // mods must be applied base at equipped weapon class and subclass comparison
5033 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5034 // m_modifier.m_miscvalue comparison with item generated damage types
5036 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5038 // apply generic physical damage bonuses including wand case
5039 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5041 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5042 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5043 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5045 else
5047 // done in Player::_ApplyWeaponDependentAuraMods
5049 // For show in client
5050 if(m_target->GetTypeId() == TYPEID_PLAYER)
5051 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
5054 // Skip non magic case for speedup
5055 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5056 return;
5058 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5060 // wand magic case (skip generic to all item spell bonuses)
5061 // done in Player::_ApplyWeaponDependentAuraMods
5063 // Skip item specific requirements for not wand magic damage
5064 return;
5067 // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
5068 // Send info to client
5069 if(m_target->GetTypeId() == TYPEID_PLAYER)
5070 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
5071 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
5074 void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
5076 // spells required only Real aura add/remove
5077 if(!Real)
5078 return;
5080 sLog.outDebug("AURA MOD OFFHAND DAMAGE");
5082 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5085 /********************************/
5086 /*** POWER COST ***/
5087 /********************************/
5089 void Aura::HandleModPowerCostPCT(bool apply, bool Real)
5091 // spells required only Real aura add/remove
5092 if(!Real)
5093 return;
5095 float amount = m_modifier.m_amount/100.0f;
5096 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5097 if(m_modifier.m_miscvalue & (1<<i))
5098 m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
5101 void Aura::HandleModPowerCost(bool apply, bool Real)
5103 // spells required only Real aura add/remove
5104 if(!Real)
5105 return;
5107 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5108 if(m_modifier.m_miscvalue & (1<<i))
5109 m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
5112 /*********************************************************/
5113 /*** OTHERS ***/
5114 /*********************************************************/
5116 void Aura::HandleShapeshiftBoosts(bool apply)
5118 uint32 spellId = 0;
5119 uint32 spellId2 = 0;
5120 uint32 HotWSpellId = 0;
5122 switch(GetModifier()->m_miscvalue)
5124 case FORM_CAT:
5125 spellId = 3025;
5126 HotWSpellId = 24900;
5127 break;
5128 case FORM_TREE:
5129 spellId = 5420;
5130 break;
5131 case FORM_TRAVEL:
5132 spellId = 5419;
5133 break;
5134 case FORM_AQUA:
5135 spellId = 5421;
5136 break;
5137 case FORM_BEAR:
5138 spellId = 1178;
5139 spellId2 = 21178;
5140 HotWSpellId = 24899;
5141 break;
5142 case FORM_DIREBEAR:
5143 spellId = 9635;
5144 spellId2 = 21178;
5145 HotWSpellId = 24899;
5146 break;
5147 case FORM_BATTLESTANCE:
5148 spellId = 21156;
5149 break;
5150 case FORM_DEFENSIVESTANCE:
5151 spellId = 7376;
5152 break;
5153 case FORM_BERSERKERSTANCE:
5154 spellId = 7381;
5155 break;
5156 case FORM_MOONKIN:
5157 spellId = 24905;
5158 // aura from effect trigger spell
5159 spellId2 = 24907;
5160 break;
5161 case FORM_FLIGHT:
5162 spellId = 33948;
5163 break;
5164 case FORM_FLIGHT_EPIC:
5165 spellId = 40122;
5166 spellId2 = 40121;
5167 break;
5168 case FORM_SPIRITOFREDEMPTION:
5169 spellId = 27792;
5170 spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
5171 break;
5172 case FORM_GHOSTWOLF:
5173 case FORM_AMBIENT:
5174 case FORM_GHOUL:
5175 case FORM_SHADOW:
5176 case FORM_STEALTH:
5177 case FORM_CREATURECAT:
5178 case FORM_CREATUREBEAR:
5179 spellId = 0;
5180 break;
5183 uint32 form = GetModifier()->m_miscvalue-1;
5185 if(apply)
5187 if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
5188 if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
5190 if(m_target->GetTypeId() == TYPEID_PLAYER)
5192 const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
5193 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
5195 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
5196 if(itr->first==spellId || itr->first==spellId2) continue;
5197 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
5198 if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
5199 if (spellInfo->Stances & (1<<form))
5200 m_target->CastSpell(m_target, itr->first, true, NULL, this);
5202 //LotP
5203 if (((Player*)m_target)->HasSpell(17007))
5205 SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
5206 if (spellInfo && spellInfo->Stances & (1<<form))
5207 m_target->CastSpell(m_target, 24932, true, NULL, this);
5209 // HotW
5210 if (HotWSpellId)
5212 Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
5213 for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
5215 if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
5217 int32 HotWMod = (*i)->GetModifier()->m_amount;
5218 if(GetModifier()->m_miscvalue == FORM_CAT)
5219 HotWMod /= 2;
5221 m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
5222 break;
5228 else
5230 m_target->RemoveAurasDueToSpell(spellId);
5231 m_target->RemoveAurasDueToSpell(spellId2);
5233 Unit::AuraMap& tAuras = m_target->GetAuras();
5234 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
5236 if (itr->second->IsRemovedOnShapeLost())
5238 m_target->RemoveAurasDueToSpell(itr->second->GetId());
5239 itr = tAuras.begin();
5241 else
5243 ++itr;
5248 /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
5249 m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
5252 void Aura::HandleAuraEmpathy(bool apply, bool Real)
5254 if(m_target->GetTypeId() != TYPEID_UNIT)
5255 return;
5257 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
5258 if(ci && ci->type == CREATURE_TYPE_BEAST)
5259 m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
5262 void Aura::HandleAuraUntrackable(bool apply, bool Real)
5264 if(apply)
5265 m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5266 else
5267 m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5270 void Aura::HandleAuraModPacify(bool apply, bool Real)
5272 if(m_target->GetTypeId() != TYPEID_PLAYER)
5273 return;
5275 if(apply)
5276 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5277 else
5278 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5281 void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
5283 HandleAuraModPacify(apply,Real);
5284 HandleAuraModSilence(apply,Real);
5287 void Aura::HandleAuraGhost(bool apply, bool Real)
5289 if(m_target->GetTypeId() != TYPEID_PLAYER)
5290 return;
5292 if(apply)
5294 m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5296 else
5298 m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5302 void Aura::HandleAuraAllowFlight(bool apply, bool Real)
5304 // all applied/removed only at real aura add/remove
5305 if(!Real)
5306 return;
5308 // allow fly
5309 WorldPacket data;
5310 if(apply)
5311 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
5312 else
5313 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
5314 data.append(m_target->GetPackGUID());
5315 data << uint32(0); // unk
5316 m_target->SendMessageToSet(&data, true);
5319 void Aura::HandleModRating(bool apply, bool Real)
5321 // spells required only Real aura add/remove
5322 if(!Real)
5323 return;
5325 if(m_target->GetTypeId() != TYPEID_PLAYER)
5326 return;
5328 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5329 if (m_modifier.m_miscvalue & (1 << rating))
5330 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
5333 void Aura::HandleForceMoveForward(bool apply, bool Real)
5335 if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
5336 return;
5337 if(apply)
5338 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5339 else
5340 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5343 void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real)
5345 if(m_target->GetTypeId() != TYPEID_PLAYER)
5346 return;
5348 ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
5349 ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
5352 void Aura::HandleModTargetResistance(bool apply, bool Real)
5354 // spells required only Real aura add/remove
5355 if(!Real)
5356 return;
5357 // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
5359 // show armor penetration
5360 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
5361 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
5363 // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
5364 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
5365 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
5368 void Aura::HandleShieldBlockValue(bool apply, bool Real)
5370 BaseModType modType = FLAT_MOD;
5371 if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
5372 modType = PCT_MOD;
5374 if(m_target->GetTypeId() == TYPEID_PLAYER)
5375 ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
5378 void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
5380 // spells required only Real aura add/remove
5381 if(!Real)
5382 return;
5384 if(m_target->GetTypeId() != TYPEID_PLAYER)
5385 return;
5387 Player *target = (Player*)m_target;
5389 // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
5390 // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
5391 if( !apply && m_duration==0 && target->GetComboTarget())
5392 if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
5393 target->AddComboPoints(unit, -m_modifier.m_amount);
5396 void Aura::HandleModUnattackable( bool Apply, bool Real )
5398 if(Real && Apply)
5399 m_target->CombatStop();
5401 m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
5404 void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
5406 // spells required only Real aura add/remove
5407 if(!Real)
5408 return;
5410 // prepare spirit state
5411 if(apply)
5413 if(m_target->GetTypeId()==TYPEID_PLAYER)
5415 // disable breath/etc timers
5416 ((Player*)m_target)->StopMirrorTimers();
5418 // set stand state (expected in this form)
5419 if(!m_target->IsStandState())
5420 m_target->SetStandState(PLAYER_STATE_NONE);
5423 m_target->SetHealth(1);
5425 // die at aura end
5426 else
5427 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
5430 void Aura::CleanupTriggeredSpells()
5432 uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
5433 if(!tSpellId)
5434 return;
5436 SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
5437 if(!tProto)
5438 return;
5440 if(GetSpellDuration(tProto) != -1)
5441 return;
5443 // needed for spell 43680, maybe others
5444 // TODO: is there a spell flag, which can solve this in a more sophisticated way?
5445 if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
5446 GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
5447 return;
5448 m_target->RemoveAurasDueToSpell(tSpellId);
5451 void Aura::HandleAuraPowerBurn(bool apply, bool Real)
5453 if (m_periodicTimer <= 0)
5454 m_periodicTimer += m_modifier.periodictime;
5456 m_isPeriodic = apply;
5459 void Aura::HandleSchoolAbsorb(bool apply, bool Real)
5461 if(!Real)
5462 return;
5464 // prevent double apply bonuses
5465 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
5467 if(Unit* caster = GetCaster())
5469 float DoneActualBenefit = 0.0f;
5470 switch(m_spellProto->SpellFamilyName)
5472 case SPELLFAMILY_PRIEST:
5473 if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
5475 //+30% from +healing bonus
5476 DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
5477 break;
5479 break;
5480 case SPELLFAMILY_MAGE:
5481 if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
5483 //frost ward, fire ward, ice barrier
5484 //+10% from +spd bonus
5485 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5486 break;
5488 break;
5489 case SPELLFAMILY_WARLOCK:
5490 if(m_spellProto->SpellFamilyFlags == 0x00)
5492 //shadow ward
5493 //+10% from +spd bonus
5494 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5495 break;
5497 break;
5498 default:
5499 break;
5502 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
5504 m_modifier.m_amount += (int32)DoneActualBenefit;
5509 void Aura::PeriodicTick()
5511 if(!m_target->isAlive())
5512 return;
5514 switch(m_modifier.m_auraname)
5516 case SPELL_AURA_PERIODIC_DAMAGE:
5517 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
5519 Unit *pCaster = GetCaster();
5520 if(!pCaster)
5521 return;
5523 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5524 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5525 return;
5527 // Check for immune (not use charges)
5528 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5529 return;
5531 // some auras remove at specific health level or more
5532 if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
5534 switch(GetId())
5536 case 43093: case 31956: case 38801:
5537 case 35321: case 38363: case 39215:
5538 if(m_target->GetHealth() == m_target->GetMaxHealth() )
5540 m_target->RemoveAurasDueToSpell(GetId());
5541 return;
5543 break;
5544 case 38772:
5546 uint32 percent =
5547 GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
5548 pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
5549 100;
5550 if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
5552 m_target->RemoveAurasDueToSpell(GetId());
5553 return;
5555 break;
5557 default:
5558 break;
5562 uint32 absorb=0;
5563 uint32 resist=0;
5564 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5566 // ignore non positive values (can be result apply spellmods to aura damage
5567 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5569 uint32 pdamage;
5571 if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
5573 pdamage = amount;
5575 // Calculate armor mitigation if it is a physical spell
5576 // But not for bleed mechanic spells
5577 if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
5578 GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
5580 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5581 cleanDamage.damage += pdamage - pdamageReductedArmor;
5582 pdamage = pdamageReductedArmor;
5585 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5587 // Curse of Agony damage-per-tick calculation
5588 if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
5590 // 1..4 ticks, 1/2 from normal tick damage
5591 if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
5592 pdamage = pdamage/2;
5593 // 9..12 ticks, 3/2 from normal tick damage
5594 else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
5595 pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
5596 // 5..8 ticks have normal tick damage
5599 else
5600 pdamage = uint32(m_target->GetMaxHealth()*amount/100);
5602 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5603 // Reduce dot damage from resilience for players
5604 if (m_target->GetTypeId()==TYPEID_PLAYER)
5605 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5607 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5609 sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5610 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5612 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5613 data.append(m_target->GetPackGUID());
5614 data.appendPackGUID(GetCasterGUID());
5615 data << uint32(GetId());
5616 data << uint32(1);
5617 data << uint32(m_modifier.m_auraname);
5618 data << (uint32)pdamage;
5619 data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
5620 data << (uint32)absorb;
5621 data << (uint32)resist;
5622 data << uint32(0); // wotlk
5623 m_target->SendMessageToSet(&data,true);
5625 Unit* target = m_target; // aura can be deleted in DealDamage
5626 SpellEntry const* spellProto = GetSpellProto();
5628 pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5630 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5632 pCaster->ProcDamageAndSpell(target, PROC_FLAG_NONE, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), GetSpellSchoolMask(spellProto), spellProto);
5633 break;
5635 case SPELL_AURA_PERIODIC_LEECH:
5637 Unit *pCaster = GetCaster();
5638 if(!pCaster)
5639 return;
5641 if(!pCaster->isAlive())
5642 return;
5644 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5645 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5646 return;
5648 // Check for immune (not use charges)
5649 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5650 return;
5652 uint32 absorb=0;
5653 uint32 resist=0;
5654 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5656 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5658 //Calculate armor mitigation if it is a physical spell
5659 if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
5661 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5662 cleanDamage.damage += pdamage - pdamageReductedArmor;
5663 pdamage = pdamageReductedArmor;
5666 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5668 // talent Soul Siphon add bonus to Drain Life spells
5669 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
5671 // find talent max bonus percentage
5672 Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5673 for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
5675 if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
5677 if((*i)->GetEffIndex()!=1)
5679 sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
5680 break;
5683 // effect 1 m_amount
5684 int32 maxPercent = (*i)->GetModifier()->m_amount;
5685 // effect 0 m_amount
5686 int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
5688 // count affliction effects and calc additional damage in percentage
5689 int32 modPercent = 0;
5690 Unit::AuraMap const& victimAuras = m_target->GetAuras();
5691 for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
5693 Aura* aura = itr->second;
5694 if (aura->IsPositive())continue;
5695 SpellEntry const* m_spell = aura->GetSpellProto();
5696 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
5697 continue;
5699 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
5700 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
5702 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
5704 if(_spell_idx->second->skillId == SKILL_AFFLICTION)
5706 modPercent += stepPercent;
5707 if (modPercent >= maxPercent)
5709 modPercent = maxPercent;
5710 break;
5715 pdamage += (pdamage*modPercent/100);
5716 break;
5721 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5722 // Reduce dot damage from resilience for players
5723 if (m_target->GetTypeId()==TYPEID_PLAYER)
5724 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5726 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5728 if(m_target->GetHealth() < pdamage)
5729 pdamage = uint32(m_target->GetHealth());
5731 sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5732 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5734 pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
5737 Unit* target = m_target; // aura can be deleted in DealDamage
5738 SpellEntry const* spellProto = GetSpellProto();
5739 float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
5741 uint32 new_damage = pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
5743 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5745 pCaster->ProcDamageAndSpell(target, PROC_FLAG_HEALED, PROC_FLAG_TAKE_DAMAGE, new_damage, GetSpellSchoolMask(spellProto), spellProto);
5746 if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
5748 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
5750 if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
5751 pCaster->m_currentSpells[i]->cancel();
5756 if(Player *modOwner = pCaster->GetSpellModOwner())
5757 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
5759 uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
5761 int32 gain = pCaster->ModifyHealth(heal);
5762 pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
5764 pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
5765 break;
5767 case SPELL_AURA_PERIODIC_HEAL:
5768 case SPELL_AURA_OBS_MOD_HEALTH:
5770 Unit *pCaster = GetCaster();
5771 if(!pCaster)
5772 return;
5774 // heal for caster damage (must be alive)
5775 if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive())
5776 return;
5778 // ignore non positive values (can be result apply spellmods to aura damage
5779 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5781 uint32 pdamage;
5783 if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
5784 pdamage = uint32(m_target->GetMaxHealth() * amount/100);
5785 else
5786 pdamage = amount;
5788 pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
5790 sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
5791 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5793 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5794 data.append(m_target->GetPackGUID());
5795 data.appendPackGUID(GetCasterGUID());
5796 data << uint32(GetId());
5797 data << uint32(1);
5798 data << uint32(m_modifier.m_auraname);
5799 data << (uint32)pdamage;
5800 data << uint32(0); // wotlk
5801 m_target->SendMessageToSet(&data,true);
5803 int32 gain = m_target->ModifyHealth(pdamage);
5805 // add HoTs to amount healed in bgs
5806 if( pCaster->GetTypeId() == TYPEID_PLAYER )
5807 if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
5808 bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
5810 //Do check before because m_modifier.auraName can be invalidate by DealDamage.
5811 bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
5813 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5815 Unit* target = m_target; // aura can be deleted in DealDamage
5816 SpellEntry const* spellProto = GetSpellProto();
5817 bool haveCastItem = GetCastItemGUID()!=0;
5819 // heal for caster damage
5820 if(m_target!=pCaster && spellProto->SpellVisual[0]==163)
5822 uint32 dmg = spellProto->manaPerSecond;
5823 if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
5825 pCaster->RemoveAurasDueToSpell(GetId());
5827 // finish current generic/channeling spells, don't affect autorepeat
5828 if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
5830 pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
5832 if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
5834 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
5835 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
5838 else
5840 pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
5842 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5843 pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5847 // ignore item heals
5848 if(procSpell && !haveCastItem)
5849 pCaster->ProcDamageAndSpell(target,PROC_FLAG_NONE, PROC_FLAG_HEALED, pdamage, SPELL_SCHOOL_MASK_NONE, spellProto);
5850 break;
5852 case SPELL_AURA_PERIODIC_MANA_LEECH:
5854 Unit *pCaster = GetCaster();
5855 if(!pCaster)
5856 return;
5858 if(!pCaster->isAlive())
5859 return;
5861 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5862 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5863 return;
5865 // Check for immune (not use charges)
5866 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5867 return;
5869 // ignore non positive values (can be result apply spellmods to aura damage
5870 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5872 sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
5873 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5875 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5876 break;
5878 Powers power = Powers(m_modifier.m_miscvalue);
5880 // power type might have changed between aura applying and tick (druid's shapeshift)
5881 if(m_target->getPowerType() != power)
5882 break;
5884 int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
5886 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
5887 if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
5888 drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
5890 m_target->ModifyPower(power, -drain_amount);
5892 float gain_multiplier = 0;
5894 if(pCaster->GetMaxPower(power) > 0)
5896 gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
5898 if(Player *modOwner = pCaster->GetSpellModOwner())
5899 modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
5902 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5903 data.append(m_target->GetPackGUID());
5904 data.appendPackGUID(GetCasterGUID());
5905 data << uint32(GetId());
5906 data << uint32(1);
5907 data << uint32(m_modifier.m_auraname);
5908 data << (uint32)power; // power type
5909 data << (uint32)drain_amount;
5910 data << (float)gain_multiplier;
5911 m_target->SendMessageToSet(&data,true);
5913 int32 gain_amount = int32(drain_amount*gain_multiplier);
5915 if(gain_amount)
5917 int32 gain = pCaster->ModifyPower(power,gain_amount);
5918 m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
5920 break;
5922 case SPELL_AURA_PERIODIC_ENERGIZE:
5924 // ignore non positive values (can be result apply spellmods to aura damage
5925 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5927 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
5928 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5930 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5931 break;
5933 Powers power = Powers(m_modifier.m_miscvalue);
5935 if(m_target->GetMaxPower(power) == 0)
5936 break;
5938 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5939 data.append(m_target->GetPackGUID());
5940 data.appendPackGUID(GetCasterGUID());
5941 data << uint32(GetId());
5942 data << uint32(1);
5943 data << uint32(m_modifier.m_auraname);
5944 data << (uint32)power; // power type
5945 data << (uint32)pdamage;
5946 m_target->SendMessageToSet(&data,true);
5948 int32 gain = m_target->ModifyPower(power,pdamage);
5950 if(Unit* pCaster = GetCaster())
5951 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5952 break;
5954 case SPELL_AURA_OBS_MOD_MANA:
5956 // ignore non positive values (can be result apply spellmods to aura damage
5957 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5959 uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
5961 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
5962 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5964 if(m_target->GetMaxPower(POWER_MANA) == 0)
5965 break;
5967 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5968 data.append(m_target->GetPackGUID());
5969 data.appendPackGUID(GetCasterGUID());
5970 data << uint32(GetId());
5971 data << uint32(1);
5972 data << uint32(m_modifier.m_auraname);
5973 data << (uint32)0; // ?
5974 data << (uint32)pdamage;
5975 m_target->SendMessageToSet(&data,true);
5977 int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
5979 if(Unit* pCaster = GetCaster())
5980 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5981 break;
5983 case SPELL_AURA_POWER_BURN_MANA:
5985 Unit *pCaster = GetCaster();
5986 if(!pCaster)
5987 return;
5989 // Check for immune (not use charges)
5990 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5991 return;
5993 int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5995 Powers powerType = Powers(m_modifier.m_miscvalue);
5997 if(!m_target->isAlive() || m_target->getPowerType() != powerType)
5998 return;
6000 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
6001 if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
6002 pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
6004 uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
6006 gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
6008 //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
6009 pCaster->SpellNonMeleeDamageLog(m_target, GetId(), gain);
6010 break;
6012 // Here tick dummy auras
6013 case SPELL_AURA_PERIODIC_DUMMY:
6015 PeriodicDummyTick();
6016 break;
6018 default:
6019 break;
6023 void Aura::PeriodicDummyTick()
6025 SpellEntry const* spell = GetSpellProto();
6026 switch (spell->Id)
6028 // Drink
6029 case 430:
6030 case 431:
6031 case 432:
6032 case 1133:
6033 case 1135:
6034 case 1137:
6035 case 10250:
6036 case 22734:
6037 case 27089:
6038 case 34291:
6039 case 43706:
6040 case 46755:
6042 if (m_target->GetTypeId() != TYPEID_PLAYER)
6043 return;
6044 // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
6045 Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
6046 for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
6048 if ((*i)->GetId() == GetId())
6050 // Get tick number
6051 int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
6052 // Default case (not on arenas)
6053 if (tick == 0)
6055 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6056 ((Player*)m_target)->UpdateManaRegen();
6057 // Disable continue
6058 m_isPeriodic = false;
6060 return;
6061 //**********************************************
6062 // Code commended since arena patch not added
6063 // This feature uses only in arenas
6064 //**********************************************
6065 // Here need increase mana regen per tick (6 second rule)
6066 // on 0 tick - 0 (handled in 2 second)
6067 // on 1 tick - 166% (handled in 4 second)
6068 // on 2 tick - 133% (handled in 6 second)
6069 // Not need update after 3 tick
6071 if (tick > 3)
6072 return;
6073 // Apply bonus for 0 - 3 tick
6074 switch (tick)
6076 case 0: // 0%
6077 (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
6078 break;
6079 case 1: // 166%
6080 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
6081 break;
6082 case 2: // 133%
6083 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
6084 break;
6085 default: // 100% - normal regen
6086 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6087 break;
6089 ((Player*)m_target)->UpdateManaRegen();
6090 return;*/
6093 return;
6095 // // Panda
6096 // case 19230: break;
6097 // // Master of Subtlety
6098 // case 31666: break;
6099 // // Gossip NPC Periodic - Talk
6100 // case 33208: break;
6101 // // Gossip NPC Periodic - Despawn
6102 // case 33209: break;
6103 // // Force of Nature
6104 // case 33831: break;
6105 // Aspect of the Viper
6106 case 34074:
6108 if (m_target->GetTypeId() != TYPEID_PLAYER)
6109 return;
6110 // Should be manauser
6111 if (m_target->getPowerType()!=POWER_MANA)
6112 return;
6113 Unit *caster = GetCaster();
6114 if (!caster)
6115 return;
6116 // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
6117 int mana = m_target->GetPower(POWER_MANA);
6118 int max_mana = m_target->GetMaxPower(POWER_MANA);
6119 int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
6120 float regen_pct = 1.20f - 1.1f * mana / max_mana;
6121 if (regen_pct > 1.0f) regen_pct = 1.0f;
6122 else if (regen_pct < 0.2f) regen_pct = 0.2f;
6123 m_modifier.m_amount = int32 (base_regen * regen_pct);
6124 ((Player*)m_target)->UpdateManaRegen();
6125 return;
6127 // // Steal Weapon
6128 // case 36207: break;
6129 // // Simon Game START timer, (DND)
6130 // case 39993: break;
6131 // // Harpooner's Mark
6132 // case 40084: break;
6133 // // Knockdown Fel Cannon: break; The Aggro Burst
6134 // case 40119: break;
6135 // // Old Mount Spell
6136 // case 40154: break;
6137 // // Magnetic Pull
6138 // case 40581: break;
6139 // // Ethereal Ring: break; The Bolt Burst
6140 // case 40801: break;
6141 // // Crystal Prison
6142 // case 40846: break;
6143 // // Copy Weapon
6144 // case 41054: break;
6145 // // Ethereal Ring Visual, Lightning Aura
6146 // case 41477: break;
6147 // // Ethereal Ring Visual, Lightning Aura (Fork)
6148 // case 41525: break;
6149 // // Ethereal Ring Visual, Lightning Jumper Aura
6150 // case 41567: break;
6151 // // No Man's Land
6152 // case 41955: break;
6153 // // Headless Horseman - Fire
6154 // case 42074: break;
6155 // // Headless Horseman - Visual - Large Fire
6156 // case 42075: break;
6157 // // Headless Horseman - Start Fire, Periodic Aura
6158 // case 42140: break;
6159 // // Ram Speed Boost
6160 // case 42152: break;
6161 // // Headless Horseman - Fires Out Victory Aura
6162 // case 42235: break;
6163 // // Pumpkin Life Cycle
6164 // case 42280: break;
6165 // // Brewfest Request Chick Chuck Mug Aura
6166 // case 42537: break;
6167 // // Squashling
6168 // case 42596: break;
6169 // // Headless Horseman Climax, Head: Periodic
6170 // case 42603: break;
6171 // // Fire Bomb
6172 // case 42621: break;
6173 // // Headless Horseman - Conflagrate, Periodic Aura
6174 // case 42637: break;
6175 // // Headless Horseman - Create Pumpkin Treats Aura
6176 // case 42774: break;
6177 // // Headless Horseman Climax - Summoning Rhyme Aura
6178 // case 42879: break;
6179 // // Tricky Treat
6180 // case 42919: break;
6181 // // Giddyup!
6182 // case 42924: break;
6183 // // Ram - Trot
6184 // case 42992: break;
6185 // // Ram - Canter
6186 // case 42993: break;
6187 // // Ram - Gallop
6188 // case 42994: break;
6189 // // Ram Level - Neutral
6190 // case 43310: break;
6191 // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
6192 // case 43884: break;
6193 // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
6194 // case 44000: break;
6195 // // Energy Feedback
6196 // case 44328: break;
6197 // // Romantic Picnic
6198 // case 45102: break;
6199 // // Romantic Picnic
6200 // case 45123: break;
6201 // // Looking for Love
6202 // case 45124: break;
6203 // // Kite - Lightning Strike Kite Aura
6204 // case 45197: break;
6205 // // Rocket Chicken
6206 // case 45202: break;
6207 // // Copy Offhand Weapon
6208 // case 45205: break;
6209 // // Upper Deck - Kite - Lightning Periodic Aura
6210 // case 45207: break;
6211 // // Kite -Sky Lightning Strike Kite Aura
6212 // case 45251: break;
6213 // // Ribbon Pole Dancer Check Aura
6214 // case 45390: break;
6215 // // Holiday - Midsummer, Ribbon Pole Periodic Visual
6216 // case 45406: break;
6217 // // Parachute
6218 // case 45472: break;
6219 // // Alliance Flag, Extra Damage Debuff
6220 // case 45898: break;
6221 // // Horde Flag, Extra Damage Debuff
6222 // case 45899: break;
6223 // // Ahune - Summoning Rhyme Aura
6224 // case 45926: break;
6225 // // Ahune - Slippery Floor
6226 // case 45945: break;
6227 // // Ahune's Shield
6228 // case 45954: break;
6229 // // Nether Vapor Lightning
6230 // case 45960: break;
6231 // // Darkness
6232 // case 45996: break;
6233 // // Summon Blood Elves Periodic
6234 // case 46041: break;
6235 // // Transform Visual Missile Periodic
6236 // case 46205: break;
6237 // // Find Opening Beam End
6238 // case 46333: break;
6239 // // Ice Spear Control Aura
6240 // case 46371: break;
6241 // // Hailstone Chill
6242 // case 46458: break;
6243 // // Hailstone Chill, Internal
6244 // case 46465: break;
6245 // // Chill, Internal Shifter
6246 // case 46549: break;
6247 // // Summon Ice Spear Knockback Delayer
6248 // case 46878: break;
6249 // // Burninate Effect
6250 // case 47214: break;
6251 // // Fizzcrank Practice Parachute
6252 // case 47228: break;
6253 // // Send Mug Control Aura
6254 // case 47369: break;
6255 // // Direbrew's Disarm (precast)
6256 // case 47407: break;
6257 // // Mole Machine Port Schedule
6258 // case 47489: break;
6259 // // Mole Machine Portal Schedule
6260 // case 49466: break;
6261 // // Drink Coffee
6262 // case 49472: break;
6263 // // Listening to Music
6264 // case 50493: break;
6265 // // Love Rocket Barrage
6266 // case 50530: break;
6267 default:
6268 break;
6272 void Aura::HandlePreventFleeing(bool apply, bool Real)
6274 if(!Real)
6275 return;
6277 Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
6278 if( !fearAuras.empty() )
6280 if (apply)
6281 m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
6282 else
6283 m_target->SetFeared(true);
6287 void Aura::HandleManaShield(bool apply, bool Real)
6289 if(!Real)
6290 return;
6292 // prevent double apply bonuses
6293 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
6295 if(Unit* caster = GetCaster())
6297 float DoneActualBenefit = 0.0f;
6298 switch(m_spellProto->SpellFamilyName)
6300 case SPELLFAMILY_MAGE:
6301 if(m_spellProto->SpellFamilyFlags & 0x8000)
6303 // Mana Shield
6304 // +50% from +spd bonus
6305 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
6306 break;
6308 break;
6309 default:
6310 break;
6313 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
6315 m_modifier.m_amount += (int32)DoneActualBenefit;
6320 void Aura::HandleArenaPreparation(bool apply, bool Real)
6322 if(!Real)
6323 return;
6325 if(apply)
6326 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6327 else
6328 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6331 void Aura::HandleAuraControlVehicle(bool apply, bool Real)
6333 if(!Real)
6334 return;
6336 if(m_target->GetTypeId() != TYPEID_PLAYER)
6337 return;
6339 if(Pet *pet = m_target->GetPet())
6340 pet->Remove(PET_SAVE_AS_CURRENT);
6342 WorldPacket data(SMSG_UNKNOWN_1181, 0);
6343 ((Player*)m_target)->GetSession()->SendPacket(&data);