* [sql/updates/2008_10_22_01_mangos_quest_template.sql] Implemented honor rewards...
[auctionmangos.git] / src / game / SpellAuras.cpp
blob2f29cfc46acd81dbe46b54e95eff5478f2cc26f0
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::HandleAuraHealing, //115 SPELL_AURA_MOD_HEALING
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::HandleAuraHealingPct, //118 SPELL_AURA_MOD_HEALING_PCT
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::HandleAuraHealingPct, //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 implemended 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::HandleAuraAttackPowerAttacker, //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 defeult intelect, 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 implemended in Unit::GetUnitCriticalChance
241 &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
242 &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING
243 &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
244 &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
245 &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
246 &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
247 &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT)
248 &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT)
249 &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
250 &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
251 &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
252 &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
253 &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP
254 &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
255 &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
256 &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::DoAttackDamage
257 &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::DoAttackDamage
258 &Aura::HandleNULL, //205 vulnerable to school dmg?
259 &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED
260 &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
261 &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive)
262 &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS
263 &Aura::HandleNULL, //210 Commentator's Command
264 &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
265 &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
266 &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
267 &Aura::HandleNULL, //214 Tamed Pet Passive
268 &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
269 &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
270 &Aura::HandleUnused, //217 unused
271 &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
272 &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
273 &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT
274 &Aura::HandleNULL, //221 ignored
275 &Aura::HandleUnused, //222 unused
276 &Aura::HandleNULL, //223 Cold Stare
277 &Aura::HandleUnused, //224 unused
278 &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING
279 &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY
280 &Aura::HandleNULL, //227 periodic trigger spell
281 &Aura::HandleNoImmediateEffect, //228 stealth detection
282 &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
283 &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
284 &Aura::HandleNULL, //231
285 &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
286 &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
287 &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
288 &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
289 &Aura::HandleUnused, //236 unused
290 &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus
291 &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
292 &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
293 &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE
294 &Aura::HandleForceMoveForward, //241 Forces the player to move forward
295 &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING
296 &Aura::HandleUnused, //243 used by two test spells
297 &Aura::HandleComprehendLanguage, //244 Comprehend language
298 &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS
299 &Aura::HandleUnused, //246 unused
300 &Aura::HandleUnused, //247 unused
301 &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
302 &Aura::HandleNULL, //249
303 &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
304 &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE
305 &Aura::HandleUnused, //252 unused
306 &Aura::HandleUnused, //253 unused
307 &Aura::HandleUnused, //254 unused
308 &Aura::HandleUnused, //255 unused
309 &Aura::HandleUnused, //256 unused
310 &Aura::HandleUnused, //257 unused
311 &Aura::HandleUnused, //258 unused
312 &Aura::HandleUnused, //259 unused
313 &Aura::HandleUnused, //260 unused
314 &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell)
317 Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
318 m_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target),
319 m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS),
320 m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false),
321 m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false),
322 m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
324 assert(target);
326 assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
328 m_spellProto = spellproto;
330 m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff];
332 m_isPassive = IsPassiveSpell(GetId());
333 m_positive = IsPositiveEffect(GetId(), m_effIndex);
335 m_applyTime = time(NULL);
337 int32 damage;
338 if(!caster)
340 m_caster_guid = target->GetGUID();
341 damage = m_currentBasePoints+1; // stored value-1
342 m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target);
344 else
346 m_caster_guid = caster->GetGUID();
348 damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target);
349 m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target);
351 if (!damage && castItem && castItem->GetItemSuffixFactor())
353 ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
354 if(item_rand_suffix)
356 for (int k=0; k<3; k++)
358 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
359 if(pEnchant)
361 for (int t=0; t<3; t++)
362 if(pEnchant->spellid[t] == m_spellProto->Id)
364 damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 );
365 break;
369 if(damage)
370 break;
376 if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0)
377 m_permanent = true;
379 Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
381 if(!m_permanent && modOwner)
382 modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration);
384 m_duration = m_maxduration;
386 if(modOwner)
387 modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
389 sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage);
391 m_effIndex = eff;
392 SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
394 m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
396 if(m_spellProto->procCharges)
398 m_procCharges = m_spellProto->procCharges;
400 if(modOwner)
401 modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
403 else
404 m_procCharges = -1;
406 m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances &&
407 !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000));
410 Aura::~Aura()
414 AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
415 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
417 m_isAreaAura = true;
419 // caster==NULL in constructor args if target==caster in fact
420 Unit* caster_ptr = caster ? caster : target;
422 m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex]));
423 if(Player* modOwner = caster_ptr->GetSpellModOwner())
424 modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius);
426 switch(spellproto->Effect[eff])
428 case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
429 m_areaAuraType = AREA_AURA_PARTY;
430 if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
431 m_modifier.m_auraname = SPELL_AURA_NONE;
432 break;
433 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
434 m_areaAuraType = AREA_AURA_FRIEND;
435 break;
436 case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
437 m_areaAuraType = AREA_AURA_ENEMY;
438 if(target == caster_ptr)
439 m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self
440 break;
441 case SPELL_EFFECT_APPLY_AREA_AURA_PET:
442 m_areaAuraType = AREA_AURA_PET;
443 break;
444 case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
445 m_areaAuraType = AREA_AURA_OWNER;
446 if(target == caster_ptr)
447 m_modifier.m_auraname = SPELL_AURA_NONE;
448 break;
449 default:
450 sLog.outError("Wrong spell effect in AreaAura constructor");
451 ASSERT(false);
452 break;
456 AreaAura::~AreaAura()
460 PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
461 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
463 m_isPersistent = true;
466 PersistentAreaAura::~PersistentAreaAura()
470 SingleEnemyTargetAura::SingleEnemyTargetAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
471 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
473 if (caster)
474 m_casters_target_guid = caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)caster)->GetSelection() : caster->GetUInt64Value(UNIT_FIELD_TARGET);
475 else
476 m_casters_target_guid = 0;
479 SingleEnemyTargetAura::~SingleEnemyTargetAura()
483 Unit* SingleEnemyTargetAura::GetTriggerTarget() const
485 return ObjectAccessor::GetUnit(*m_target, m_casters_target_guid);
488 Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem)
490 if (IsAreaAuraEffect(spellproto->Effect[eff]))
491 return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem);
493 uint32 triggeredSpellId = spellproto->EffectTriggerSpell[eff];
495 SpellEntry const* triggredSpellInfo = sSpellStore.LookupEntry(triggeredSpellId);
496 if (triggredSpellInfo)
497 for (int i = 0; i < 3; ++i)
498 if (triggredSpellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_ENEMY)
499 return new SingleEnemyTargetAura(spellproto, eff, currentBasePoints, target, caster, castItem);
501 return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem);
504 Unit* Aura::GetCaster() const
506 if(m_caster_guid==m_target->GetGUID())
507 return m_target;
509 //return ObjectAccessor::GetUnit(*m_target,m_caster_guid);
510 //must return caster even if it's in another grid/map
511 Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL);
512 return unit && unit->IsInWorld() ? unit : NULL;
515 void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
517 m_modifier.m_auraname = t;
518 m_modifier.m_amount = a;
519 m_modifier.m_miscvalue = miscValue;
520 m_modifier.periodictime = pt;
523 void Aura::Update(uint32 diff)
525 if (m_duration > 0)
527 m_duration -= diff;
528 if (m_duration < 0)
529 m_duration = 0;
530 m_timeCla -= diff;
532 // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras
533 // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0
534 if(GetEffIndex()==0 && m_timeCla <= 0)
536 if(Unit* caster = GetCaster())
538 Powers powertype = Powers(m_spellProto->powerType);
539 int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel();
540 m_timeCla = 1000;
541 if (manaPerSecond)
543 if(powertype==POWER_HEALTH)
544 caster->ModifyHealth(-manaPerSecond);
545 else
546 caster->ModifyPower(powertype,-manaPerSecond);
552 // Channeled aura required check distance from caster
553 if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID())
555 Unit* caster = GetCaster();
556 if(!caster)
558 m_target->RemoveAura(GetId(),GetEffIndex());
559 return;
562 // Get spell range
563 float radius;
564 SpellModOp mod;
565 if (m_spellProto->EffectRadiusIndex[GetEffIndex()])
567 radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()]));
568 mod = SPELLMOD_RADIUS;
570 else
572 radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
573 mod = SPELLMOD_RANGE;
576 if(Player* modOwner = caster->GetSpellModOwner())
577 modOwner->ApplySpellMod(GetId(), mod, radius,NULL);
579 if(!caster->IsWithinDistInMap(m_target,radius))
581 m_target->RemoveAura(GetId(),GetEffIndex());
582 return;
586 if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
588 m_periodicTimer -= diff;
589 if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
591 if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN ||
592 m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN ||
593 // Cannibalize, eating items and other spells
594 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH ||
595 // Eating items and other spells
596 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA )
598 ApplyModifier(true);
599 return;
601 // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
602 m_periodicTimer += m_modifier.periodictime;
604 if(m_isTrigger)
605 TriggerSpell();
606 else
607 PeriodicTick();
612 void AreaAura::Update(uint32 diff)
614 // update for the caster of the aura
615 if(m_caster_guid == m_target->GetGUID())
617 Unit* caster = m_target;
619 if( !caster->hasUnitState(UNIT_STAT_ISOLATED) )
621 Unit* owner = caster->GetCharmerOrOwner();
622 if (!owner)
623 owner = caster;
624 std::list<Unit *> targets;
626 switch(m_areaAuraType)
628 case AREA_AURA_PARTY:
630 Group *pGroup = NULL;
632 if (owner->GetTypeId() == TYPEID_PLAYER)
633 pGroup = ((Player*)owner)->GetGroup();
635 if( pGroup)
637 uint8 subgroup = ((Player*)owner)->GetSubGroup();
638 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
640 Player* Target = itr->getSource();
641 if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target))
643 if(caster->IsWithinDistInMap(Target, m_radius))
644 targets.push_back(Target);
645 Pet *pet = Target->GetPet();
646 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
647 targets.push_back(pet);
651 else
653 // add owner
654 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
655 targets.push_back(owner);
656 // add caster's pet
657 Unit* pet = caster->GetPet();
658 if( pet && caster->IsWithinDistInMap(pet, m_radius))
659 targets.push_back(pet);
661 break;
663 case AREA_AURA_FRIEND:
665 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
666 Cell cell(p);
667 cell.data.Part.reserved = ALL_DISTRICT;
668 cell.SetNoCreate();
670 MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius);
671 MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
672 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
673 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
674 CellLock<GridReadGuard> cell_lock(cell, p);
675 cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
676 cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
677 break;
679 case AREA_AURA_ENEMY:
681 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
682 Cell cell(p);
683 cell.data.Part.reserved = ALL_DISTRICT;
684 cell.SetNoCreate();
686 MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
687 MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);
688 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
689 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
690 CellLock<GridReadGuard> cell_lock(cell, p);
691 cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
692 cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
693 break;
695 case AREA_AURA_OWNER:
696 case AREA_AURA_PET:
698 if(owner != caster)
699 targets.push_back(owner);
700 break;
704 for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
706 if((*tIter)->HasAura(GetId(), m_effIndex))
707 continue;
709 if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
711 int32 actualBasePoints = m_currentBasePoints;
712 // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
713 if(actualSpellInfo != GetSpellProto())
714 actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
715 AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL);
716 (*tIter)->AddAura(aur);
720 Aura::Update(diff);
722 else // aura at non-caster
724 Unit * tmp_target = m_target;
725 Unit* caster = GetCaster();
726 uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
728 // WARNING: the aura may get deleted during the update
729 // DO NOT access its members after update!
730 Aura::Update(diff);
732 // remove aura if out-of-range from caster (after teleport for example)
733 // or caster is isolated or caster no longer has the aura
734 // or caster is (no longer) friendly
735 bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
736 if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
737 !caster->IsWithinDistInMap(tmp_target, m_radius) ||
738 !caster->HasAura(tmp_spellId, tmp_effIndex) ||
739 caster->IsFriendlyTo(tmp_target) != needFriendly
742 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
744 else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
746 // not check group if target == owner or target == pet
747 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
749 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
751 Group *pGroup = check ? check->GetGroup() : NULL;
752 if( pGroup )
754 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
755 if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
756 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
758 else
759 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
762 else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
764 if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
765 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
770 void PersistentAreaAura::Update(uint32 diff)
772 bool remove = false;
774 // remove the aura if its caster or the dynamic object causing it was removed
775 // or if the target moves too far from the dynamic object
776 Unit *caster = GetCaster();
777 if (caster)
779 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
780 if (dynObj)
782 if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius()))
783 remove = true;
785 else
786 remove = true;
788 else
789 remove = true;
791 Unit *tmp_target = m_target;
792 uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
794 // WARNING: the aura may get deleted during the update
795 // DO NOT access its members after update!
796 Aura::Update(diff);
798 if(remove)
799 tmp_target->RemoveAura(tmp_id, tmp_index);
802 void Aura::ApplyModifier(bool apply, bool Real)
804 AuraType aura = m_modifier.m_auraname;
806 m_in_use = true;
807 if(aura<TOTAL_AURAS)
808 (*this.*AuraHandler [aura])(apply,Real);
809 m_in_use = false;
812 void Aura::UpdateAuraDuration()
814 if(m_auraSlot >= MAX_AURAS || m_isPassive)
815 return;
817 if( m_target->GetTypeId() == TYPEID_PLAYER)
819 WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5);
820 data << (uint8)m_auraSlot << (uint32)m_duration;
821 ((Player*)m_target)->SendDirectMessage(&data);
823 data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4));
824 data.append(m_target->GetPackGUID());
825 data << uint8(m_auraSlot);
826 data << uint32(GetId());
827 data << uint32(GetAuraMaxDuration());
828 data << uint32(GetAuraDuration());
829 ((Player*)m_target)->SendDirectMessage(&data);
832 // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code
833 if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading())
834 return;
836 Unit* caster = GetCaster();
838 if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target)
839 SendAuraDurationForCaster((Player*)caster);
842 void Aura::SendAuraDurationForCaster(Player* caster)
844 WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4));
845 data.append(m_target->GetPackGUID());
846 data << uint8(m_auraSlot);
847 data << uint32(GetId());
848 data << uint32(GetAuraMaxDuration()); // full
849 data << uint32(GetAuraDuration()); // remain
850 caster->GetSession()->SendPacket(&data);
853 void Aura::_AddAura()
855 if (!GetId())
856 return;
857 if(!m_target)
858 return;
860 // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT
861 bool samespell = false;
862 bool secondaura = false;
863 uint8 slot = NULL_AURA_SLOT;
865 for(uint8 i = 0; i < 3; i++)
867 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
868 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
870 // allow use single slot only by auras from same caster
871 if(itr->second->GetCasterGUID()==GetCasterGUID())
873 samespell = true;
874 if (m_effIndex > itr->second->GetEffIndex())
875 secondaura = true;
876 slot = itr->second->GetAuraSlot();
877 break;
881 if(samespell)
882 break;
885 // not call total regen auras at adding
886 switch (m_modifier.m_auraname)
888 case SPELL_AURA_OBS_MOD_HEALTH:
889 case SPELL_AURA_OBS_MOD_MANA:
890 m_periodicTimer = m_modifier.periodictime;
891 break;
892 case SPELL_AURA_MOD_REGEN:
893 case SPELL_AURA_MOD_POWER_REGEN:
894 case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
895 m_periodicTimer = 5000;
896 break;
899 // register aura
900 if (getDiminishGroup() != DIMINISHING_NONE )
901 m_target->ApplyDiminishingAura(getDiminishGroup(),true);
903 Unit* caster = GetCaster();
905 // passive auras (except totem auras) do not get placed in the slots
906 // area auras with SPELL_AURA_NONE are not shown on target
907 if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
908 (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
910 if(!samespell) // new slot need
912 if (IsPositive()) // empty positive slot
914 for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++)
916 if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
918 slot = i;
919 break;
923 else // empty negative slot
925 for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++)
927 if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
929 slot = i;
930 break;
935 SetAuraSlot( slot );
937 // Not update fields for not first spell's aura, all data already in fields
938 if(!secondaura)
940 if(slot < MAX_AURAS) // slot found
942 SetAura(slot, false);
943 SetAuraFlag(slot, true);
944 SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
945 UpdateAuraCharges();
947 // update for out of range group members
948 m_target->UpdateAuraForGroup(slot);
951 UpdateAuraDuration();
954 else // use found slot
956 SetAuraSlot( slot );
957 // Not recalculate stack count for second aura of the same spell
958 if (!secondaura)
959 UpdateSlotCounterAndDuration(true);
962 // Update Seals information
963 if( IsSealSpell(GetSpellProto()) )
964 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
966 // Conflagrate aura state
967 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
968 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
970 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
971 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
973 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
978 void Aura::_RemoveAura()
980 // Remove all triggered by aura spells vs unlimited duration
981 // except same aura replace case
982 if(m_removeMode!=AURA_REMOVE_BY_STACK)
983 CleanupTriggeredSpells();
985 Unit* caster = GetCaster();
987 if(caster && IsPersistent())
989 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
990 if (dynObj)
991 dynObj->RemoveAffected(m_target);
994 // unregister aura
995 if (getDiminishGroup() != DIMINISHING_NONE )
996 m_target->ApplyDiminishingAura(getDiminishGroup(),false);
998 //passive auras do not get put in slots
999 // Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
1000 //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
1001 // return;
1003 uint8 slot = GetAuraSlot();
1005 if(slot >= MAX_AURAS) // slot not set
1006 return;
1008 if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0)
1009 return;
1011 bool samespell = false;
1012 bool sameaura = false;
1014 // find other aura in same slot (current already removed from list)
1015 for(uint8 i = 0; i < 3; i++)
1017 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
1018 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
1020 if(itr->second->GetAuraSlot()==slot)
1022 samespell = true;
1024 if(GetEffIndex()==i)
1025 sameaura = true;
1027 break;
1030 if(samespell)
1031 break;
1034 // only remove icon when the last aura of the spell is removed (current aura already removed from list)
1035 if (!samespell)
1037 SetAura(slot, true);
1038 SetAuraFlag(slot, false);
1039 SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
1041 SetAuraApplication(slot, 0);
1042 // update for out of range group members
1043 m_target->UpdateAuraForGroup(slot);
1045 if( IsSealSpell(GetSpellProto()) )
1046 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
1048 // Conflagrate aura state
1049 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
1050 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false);
1052 // Swiftmend aura state
1053 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1054 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
1056 bool found = false;
1057 Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
1058 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
1060 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1061 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
1063 found = true;
1064 break;
1067 if(!found)
1068 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false);
1071 // reset cooldown state for spells
1072 if(caster && caster->GetTypeId() == TYPEID_PLAYER)
1074 if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
1075 ((Player*)caster)->SendCooldownEvent(GetSpellProto());
1078 else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove proccess.
1079 UpdateSlotCounterAndDuration(false);
1082 void Aura::SetAuraFlag(uint32 slot, bool add)
1084 uint32 index = slot / 4;
1085 uint32 byte = (slot % 4) * 8;
1086 uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index);
1087 val &= ~((uint32)AFLAG_MASK << byte);
1088 if(add)
1090 if (IsPositive())
1091 val |= ((uint32)AFLAG_POSITIVE << byte);
1092 else
1093 val |= ((uint32)AFLAG_NEGATIVE << byte);
1095 m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val);
1098 void Aura::SetAuraLevel(uint32 slot,uint32 level)
1100 uint32 index = slot / 4;
1101 uint32 byte = (slot % 4) * 8;
1102 uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index);
1103 val &= ~(0xFF << byte);
1104 val |= (level << byte);
1105 m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val);
1108 void Aura::SetAuraApplication(uint32 slot, int8 count)
1110 uint32 index = slot / 4;
1111 uint32 byte = (slot % 4) * 8;
1112 uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index);
1113 val &= ~(0xFF << byte);
1114 val |= ((uint8(count)) << byte);
1115 m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val);
1118 void Aura::UpdateSlotCounterAndDuration(bool add)
1120 uint8 slot = GetAuraSlot();
1121 if(slot >= MAX_AURAS)
1122 return;
1124 // calculate amount of similar auras by same effect index (similar different spells)
1125 int8 count = 0;
1127 // calculate auras and update durations in case aura adding
1128 Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname);
1129 for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i)
1131 if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex &&
1132 (*i)->GetCasterGUID()==GetCasterGUID() )
1134 ++count;
1136 if(add)
1137 (*i)->SetAuraDuration(GetAuraDuration());
1141 // at aura add aura not added yet, at aura remove aura already removed
1142 // in field stored (count-1)
1143 if(!add)
1144 --count;
1146 SetAuraApplication(slot, count);
1148 UpdateAuraDuration();
1151 /*********************************************************/
1152 /*** BASIC AURA FUNCTION ***/
1153 /*********************************************************/
1154 void Aura::HandleAddModifier(bool apply, bool Real)
1156 if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
1157 return;
1159 SpellEntry const *spellInfo = GetSpellProto();
1160 if(!spellInfo)
1161 return;
1163 if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
1164 return;
1166 if (apply)
1168 // Add custom charges for some mod aura
1169 switch (m_spellProto->Id)
1171 case 17941: // Shadow Trance
1172 case 22008: // Netherwind Focus
1173 case 34936: // Backlash
1174 m_procCharges = 1;
1175 break;
1178 SpellModifier *mod = new SpellModifier;
1179 mod->op = SpellModOp(m_modifier.m_miscvalue);
1180 mod->value = m_modifier.m_amount;
1181 mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
1182 mod->spellId = GetId();
1183 mod->effectId = m_effIndex;
1184 mod->lastAffected = NULL;
1186 uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex);
1188 if (spellAffectMask)
1189 mod->mask = spellAffectMask;
1190 else
1191 mod->mask = spellInfo->EffectItemType[m_effIndex];
1193 if (m_procCharges > 0)
1194 mod->charges = m_procCharges;
1195 else
1196 mod->charges = 0;
1198 m_spellmod = mod;
1201 uint64 spellFamilyMask = m_spellmod->mask;
1203 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
1205 // reapply some passive spells after add/remove related spellmods
1206 if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
1208 m_target->RemoveAurasDueToSpell(45471);
1210 if(apply)
1211 m_target->CastSpell(m_target,45471,true);
1215 void Aura::TriggerSpell()
1217 Unit* caster = GetCaster();
1218 Unit* target = GetTriggerTarget();
1220 if(!caster || !target)
1221 return;
1223 // generic casting code with custom spells and target/caster customs
1224 uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
1226 uint64 originalCasterGUID = GetCasterGUID();
1228 SpellEntry const *triggredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1229 SpellEntry const *auraSpellInfo = GetSpellProto();
1230 uint32 auraId = auraSpellInfo->Id;
1232 // specific code for cases with no trigger spell provided in field
1233 if (triggredSpellInfo == NULL)
1235 switch(auraSpellInfo->SpellFamilyName)
1237 case SPELLFAMILY_GENERIC:
1239 switch(auraId)
1241 // Firestone Passive (1-5 rangs)
1242 case 758:
1243 case 17945:
1244 case 17947:
1245 case 17949:
1246 case 27252:
1248 if (caster->GetTypeId()!=TYPEID_PLAYER)
1249 return;
1250 Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
1251 if (!item)
1252 return;
1253 uint32 enchant_id = 0;
1254 switch (GetId())
1256 case 758: enchant_id = 1803; break; // Rank 1
1257 case 17945: enchant_id = 1823; break; // Rank 2
1258 case 17947: enchant_id = 1824; break; // Rank 3
1259 case 17949: enchant_id = 1825; break; // Rank 4
1260 case 27252: enchant_id = 2645; break; // Rank 5
1261 default:
1262 return;
1264 // remove old enchanting before applying new
1265 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1266 item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
1267 // add new enchanting
1268 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
1269 return;
1271 // // Periodic Mana Burn
1272 // case 812: break;
1273 // // Polymorphic Ray
1274 // case 6965: break;
1275 // // Fire Nova (1-7 Rangs)
1276 // case 8350:
1277 // case 8508:
1278 // case 8509:
1279 // case 11312:
1280 // case 11313:
1281 // case 25540:
1282 // case 25544:
1283 // break;
1284 // Thaumaturgy Channel
1285 case 9712: trigger_spell_id = 21029; break;
1286 // // Egan's Blaster
1287 // case 17368: break;
1288 // // Haunted
1289 // case 18347: break;
1290 // // Ranshalla Waiting
1291 // case 18953: break;
1292 // // Inferno
1293 // case 19695: break;
1294 // // Frostwolf Muzzle DND
1295 // case 21794: break;
1296 // // Alterac Ram Collar DND
1297 // case 21866: break;
1298 // // Celebras Waiting
1299 // case 21916: break;
1300 // Brood Affliction: Bronze
1301 case 23170:
1303 m_target->CastSpell(m_target, 23171, true, 0, this);
1304 return;
1306 // // Mark of Frost
1307 // case 23184: break;
1308 // Restoration
1309 case 23493:
1311 int32 heal = caster->GetMaxHealth() / 10;
1312 caster->ModifyHealth( heal );
1313 caster->SendHealSpellLog(caster, 23493, heal);
1315 int32 mana = caster->GetMaxPower(POWER_MANA);
1316 if (mana)
1318 mana /= 10;
1319 caster->ModifyPower( POWER_MANA, mana );
1320 caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
1322 break;
1324 // // Stoneclaw Totem Passive TEST
1325 // case 23792: break;
1326 // // Axe Flurry
1327 // case 24018: break;
1328 // // Mark of Arlokk
1329 // case 24210: break;
1330 // // Restoration
1331 // case 24379: break;
1332 // // Happy Pet
1333 // case 24716: break;
1334 // // Dream Fog
1335 // case 24780: break;
1336 // // Cannon Prep
1337 // case 24832: break;
1338 // // Shadow Bolt Whirl
1339 // case 24834: break;
1340 // // Stink Trap
1341 // case 24918: break;
1342 // // Mark of Nature
1343 // case 25041: break;
1344 // // Agro Drones
1345 // case 25152: break;
1346 // // Consume
1347 // case 25371: break;
1348 // // Pain Spike
1349 // case 25572: break;
1350 // // Rotate 360
1351 // case 26009: break;
1352 // // Rotate -360
1353 // case 26136: break;
1354 // // Consume
1355 // case 26196: break;
1356 // // Berserk
1357 // case 26615: break;
1358 // // Defile
1359 // case 27177: break;
1360 // // Teleport: IF/UC
1361 // case 27601: break;
1362 // // Five Fat Finger Exploding Heart Technique
1363 // case 27673: break;
1364 // // Nitrous Boost
1365 // case 27746: break;
1366 // // Steam Tank Passive
1367 // case 27747: break;
1368 // // Frost Blast
1369 // case 27808: break;
1370 // // Detonate Mana
1371 // case 27819: break;
1372 // // Controller Timer
1373 // case 28095: break;
1374 // // Stalagg Chain
1375 // case 28096: break;
1376 // // Stalagg Tesla Passive
1377 // case 28097: break;
1378 // // Feugen Tesla Passive
1379 // case 28109: break;
1380 // // Feugen Chain
1381 // case 28111: break;
1382 // // Mark of Didier
1383 // case 28114: break;
1384 // // Communique Timer, camp
1385 // case 28346: break;
1386 // // Icebolt
1387 // case 28522: break;
1388 // // Silithyst
1389 // case 29519: break;
1390 // // Inoculate Nestlewood Owlkin
1391 case 29528: trigger_spell_id = 28713; break;
1392 // // Overload
1393 // case 29768: break;
1394 // // Return Fire
1395 // case 29788: break;
1396 // // Return Fire
1397 // case 29793: break;
1398 // // Return Fire
1399 // case 29794: break;
1400 // // Guardian of Icecrown Passive
1401 // case 29897: break;
1402 // Feed Captured Animal
1403 case 29917: trigger_spell_id = 29916; break;
1404 // // Flame Wreath
1405 // case 29946: break;
1406 // // Flame Wreath
1407 // case 29947: break;
1408 // // Mind Exhaustion Passive
1409 // case 30025: break;
1410 // // Nether Beam - Serenity
1411 // case 30401: break;
1412 // Extract Gas
1413 case 30427:
1415 // move loot to player inventory and despawn target
1416 if(caster->GetTypeId() ==TYPEID_PLAYER &&
1417 target->GetTypeId() == TYPEID_UNIT &&
1418 ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
1420 Player* player = (Player*)caster;
1421 Creature* creature = (Creature*)target;
1422 // missing lootid has been reported on startup - just return
1423 if (!creature->GetCreatureInfo()->SkinLootId)
1425 return;
1427 Loot *loot = &creature->loot;
1428 loot->clear();
1429 loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL);
1430 for(uint8 i=0;i<loot->items.size();i++)
1432 LootItem *item = loot->LootItemInSlot(i,player);
1433 ItemPosCountVec dest;
1434 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count );
1435 if ( msg == EQUIP_ERR_OK )
1437 Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId);
1439 player->SendNewItem(newitem, uint32(item->count), false, false, true);
1441 else
1442 player->SendEquipError( msg, NULL, NULL );
1444 creature->setDeathState(JUST_DIED);
1445 creature->RemoveCorpse();
1446 creature->SetHealth(0); // just for nice GM-mode view
1448 return;
1449 break;
1451 // Quake
1452 case 30576: trigger_spell_id = 30571; break;
1453 // // Burning Maul
1454 // case 30598: break;
1455 // // Regeneration
1456 // case 30799:
1457 // case 30800:
1458 // case 30801:
1459 // break;
1460 // // Despawn Self - Smoke cloud
1461 // case 31269: break;
1462 // // Time Rift Periodic
1463 // case 31320: break;
1464 // // Corrupt Medivh
1465 // case 31326: break;
1466 // Doom
1467 case 31347:
1469 m_target->CastSpell(m_target,31350,true);
1470 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
1471 return;
1473 // Spellcloth
1474 case 31373:
1476 // Summon Elemental after create item
1477 caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
1478 return;
1480 // // Bloodmyst Tesla
1481 // case 31611: break;
1482 // // Doomfire
1483 // case 31944: break;
1484 // // Teleport Test
1485 // case 32236: break;
1486 // // Earthquake
1487 // case 32686: break;
1488 // // Possess
1489 // case 33401: break;
1490 // // Draw Shadows
1491 // case 33563: break;
1492 // // Murmur's Touch
1493 // case 33711: break;
1494 // Flame Quills
1495 case 34229:
1497 // cast 24 spells 34269-34289, 34314-34316
1498 for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
1499 caster->CastSpell(m_target,spell_id,true);
1500 for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
1501 caster->CastSpell(m_target,spell_id,true);
1502 return;
1504 // // Gravity Lapse
1505 // case 34480: break;
1506 // // Tornado
1507 // case 34683: break;
1508 // // Frostbite Rotate
1509 // case 34748: break;
1510 // // Arcane Flurry
1511 // case 34821: break;
1512 // // Interrupt Shutdown
1513 // case 35016: break;
1514 // // Interrupt Shutdown
1515 // case 35176: break;
1516 // // Inferno
1517 // case 35268: break;
1518 // // Salaadin's Tesla
1519 // case 35515: break;
1520 // // Ethereal Channel (Red)
1521 // case 35518: break;
1522 // // Nether Vapor
1523 // case 35879: break;
1524 // // Dark Portal Storm
1525 // case 36018: break;
1526 // // Burning Maul
1527 // case 36056: break;
1528 // // Living Grove Defender Lifespan
1529 // case 36061: break;
1530 // // Professor Dabiri Talks
1531 // case 36064: break;
1532 // // Kael Gaining Power
1533 // case 36091: break;
1534 // // They Must Burn Bomb Aura
1535 // case 36344: break;
1536 // // They Must Burn Bomb Aura (self)
1537 // case 36350: break;
1538 // // Stolen Ravenous Ravager Egg
1539 // case 36401: break;
1540 // // Activated Cannon
1541 // case 36410: break;
1542 // // Stolen Ravenous Ravager Egg
1543 // case 36418: break;
1544 // // Enchanted Weapons
1545 // case 36510: break;
1546 // // Cursed Scarab Periodic
1547 // case 36556: break;
1548 // // Cursed Scarab Despawn Periodic
1549 // case 36561: break;
1550 // // Vision Guide
1551 // case 36573: break;
1552 // // Cannon Charging (platform)
1553 // case 36785: break;
1554 // // Cannon Charging (self)
1555 // case 36860: break;
1556 // Remote Toy
1557 case 37027: trigger_spell_id = 37029; break;
1558 // // Mark of Death
1559 // case 37125: break;
1560 // // Arcane Flurry
1561 // case 37268: break;
1562 // // Spout
1563 // case 37429: break;
1564 // // Spout
1565 // case 37430: break;
1566 // // Karazhan - Chess NPC AI, Snapshot timer
1567 // case 37440: break;
1568 // // Karazhan - Chess NPC AI, action timer
1569 // case 37504: break;
1570 // // Karazhan - Chess: Is Square OCCUPIED aura (DND)
1571 // case 39400: break;
1572 // // Banish
1573 // case 37546: break;
1574 // // Shriveling Gaze
1575 // case 37589: break;
1576 // // Fake Aggro Radius (2 yd)
1577 // case 37815: break;
1578 // // Corrupt Medivh
1579 // case 37853: break;
1580 // Eye of Grillok
1581 case 38495:
1583 m_target->CastSpell(m_target, 38530, true);
1584 return;
1586 // Absorb Eye of Grillok (Zezzak's Shard)
1587 case 38554:
1589 if(m_target->GetTypeId() != TYPEID_UNIT)
1590 return;
1592 caster->CastSpell(caster, 38495, true);
1594 Creature* creatureTarget = (Creature*)m_target;
1596 creatureTarget->setDeathState(JUST_DIED);
1597 creatureTarget->RemoveCorpse();
1598 creatureTarget->SetHealth(0); // just for nice GM-mode view
1599 return;
1601 // // Magic Sucker Device timer
1602 // case 38672: break;
1603 // // Tomb Guarding Charging
1604 // case 38751: break;
1605 // // Murmur's Touch
1606 // case 38794: break;
1607 // // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item)
1608 // case 39105: break;
1609 // // Drain World Tree Visual
1610 // case 39140: break;
1611 // // Quest - Dustin's Undead Dragon Visual aura
1612 // case 39259: break;
1613 // // Hellfire - The Exorcism, Jules releases darkness, aura
1614 // case 39306: break;
1615 // // Inferno
1616 // case 39346: break;
1617 // // Enchanted Weapons
1618 // case 39489: break;
1619 // // Shadow Bolt Whirl
1620 // case 39630: break;
1621 // // Shadow Bolt Whirl
1622 // case 39634: break;
1623 // // Shadow Inferno
1624 // case 39645: break;
1625 // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
1626 case 39857: trigger_spell_id = 39856; break;
1627 // // Soulgrinder Ritual Visual (Smashed)
1628 // case 39974: break;
1629 // // Simon Game Pre-game timer
1630 // case 40041: break;
1631 // // Knockdown Fel Cannon: The Aggro Check Aura
1632 // case 40113: break;
1633 // // Spirit Lance
1634 // case 40157: break;
1635 // // Demon Transform 2
1636 // case 40398: break;
1637 // // Demon Transform 1
1638 // case 40511: break;
1639 // // Ancient Flames
1640 // case 40657: break;
1641 // // Ethereal Ring Cannon: Cannon Aura
1642 // case 40734: break;
1643 // // Cage Trap
1644 // case 40760: break;
1645 // // Random Periodic
1646 // case 40867: break;
1647 // // Prismatic Shield
1648 // case 40879: break;
1649 // // Aura of Desire
1650 // case 41350: break;
1651 // // Dementia
1652 // case 41404: break;
1653 // // Chaos Form
1654 // case 41629: break;
1655 // // Alert Drums
1656 // case 42177: break;
1657 // // Spout
1658 // case 42581: break;
1659 // // Spout
1660 // case 42582: break;
1661 // // Return to the Spirit Realm
1662 // case 44035: break;
1663 // // Curse of Boundless Agony
1664 // case 45050: break;
1665 // // Earthquake
1666 // case 46240: break;
1667 // Personalized Weather
1668 case 46736: trigger_spell_id = 46737; break;
1669 // // Stay Submerged
1670 // case 46981: break;
1671 // // Dragonblight Ram
1672 // case 47015: break;
1673 // // Party G.R.E.N.A.D.E.
1674 // case 51510: break;
1675 default:
1676 break;
1678 break;
1680 case SPELLFAMILY_MAGE:
1682 switch(auraId)
1684 // Invisibility
1685 case 66:
1687 if(!m_duration)
1688 m_target->CastSpell(m_target, 32612, true, NULL, this);
1689 return;
1691 default:
1692 break;
1694 break;
1696 // case SPELLFAMILY_WARRIOR:
1697 // {
1698 // switch(auraId)
1699 // {
1700 // // Wild Magic
1701 // case 23410: break;
1702 // // Corrupted Totems
1703 // case 23425: break;
1704 // default:
1705 // break;
1706 // }
1707 // break;
1708 // }
1709 // case SPELLFAMILY_PRIEST:
1710 // {
1711 // switch(auraId)
1712 // {
1713 // // Blue Beam
1714 // case 32930: break;
1715 // // Fury of the Dreghood Elders
1716 // case 35460: break;
1717 // default:
1718 // break;
1719 // }
1720 // break;
1721 // }
1722 case SPELLFAMILY_DRUID:
1724 switch(auraId)
1726 // Cat Form
1727 // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while
1728 case 768:
1729 return;
1730 // Frenzied Regeneration
1731 case 22842:
1732 case 22895:
1733 case 22896:
1734 case 26999:
1736 int32 LifePerRage = GetModifier()->m_amount;
1738 int32 lRage = m_target->GetPower(POWER_RAGE);
1739 if(lRage > 100) // rage stored as rage*10
1740 lRage = 100;
1741 m_target->ModifyPower(POWER_RAGE, -lRage);
1742 int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10);
1743 m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this);
1744 return;
1746 default:
1747 break;
1749 break;
1752 // case SPELLFAMILY_HUNTER:
1753 // {
1754 // switch(auraId)
1755 // {
1756 // //Frost Trap Aura
1757 // case 13810:
1758 // return;
1759 // //Rizzle's Frost Trap
1760 // case 39900:
1761 // return;
1762 // // Tame spells
1763 // case 19597: // Tame Ice Claw Bear
1764 // case 19676: // Tame Snow Leopard
1765 // case 19677: // Tame Large Crag Boar
1766 // case 19678: // Tame Adult Plainstrider
1767 // case 19679: // Tame Prairie Stalker
1768 // case 19680: // Tame Swoop
1769 // case 19681: // Tame Dire Mottled Boar
1770 // case 19682: // Tame Surf Crawler
1771 // case 19683: // Tame Armored Scorpid
1772 // case 19684: // Tame Webwood Lurker
1773 // case 19685: // Tame Nightsaber Stalker
1774 // case 19686: // Tame Strigid Screecher
1775 // case 30100: // Tame Crazed Dragonhawk
1776 // case 30103: // Tame Elder Springpaw
1777 // case 30104: // Tame Mistbat
1778 // case 30647: // Tame Barbed Crawler
1779 // case 30648: // Tame Greater Timberstrider
1780 // case 30652: // Tame Nightstalker
1781 // return;
1782 // default:
1783 // break;
1784 // }
1785 // break;
1786 // }
1787 case SPELLFAMILY_SHAMAN:
1789 switch(auraId)
1791 // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
1792 case 28820:
1794 // Need remove self if Lightning Shield not active
1795 Unit::AuraMap const& auras = target->GetAuras();
1796 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1798 SpellEntry const* spell = itr->second->GetSpellProto();
1799 if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
1800 spell->SpellFamilyFlags & 0x0000000000000400L)
1801 return;
1803 target->RemoveAurasDueToSpell(28820);
1804 return;
1806 // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
1807 case 38443:
1809 bool all = true;
1810 for(int i = 0; i < MAX_TOTEM; ++i)
1812 if(!caster->m_TotemSlot[i])
1814 all = false;
1815 break;
1819 if(all)
1820 caster->CastSpell(caster,38437,true);
1821 else
1822 caster->RemoveAurasDueToSpell(38437);
1823 return;
1825 default:
1826 break;
1828 break;
1830 default:
1831 break;
1833 // Reget trigger spell proto
1834 triggredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1835 if(triggredSpellInfo == NULL)
1837 sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
1838 return;
1841 else
1843 // Spell exist but require costum code
1844 switch(auraId)
1846 // Curse of Idiocy
1847 case 1010:
1849 // TODO: spell casted by result in correct way mostly
1850 // BUT:
1851 // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell
1852 // but must show affect apply like item casting
1853 // 2) maybe aura must be replace by new with accumulative stat mods insteed stacking
1855 // prevent cast by triggered auras
1856 if(m_caster_guid == m_target->GetGUID())
1857 return;
1859 // stop triggering after each affected stats lost > 90
1860 int32 intelectLoss = 0;
1861 int32 spiritLoss = 0;
1863 Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT);
1864 for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
1866 if ((*i)->GetId() == 1010)
1868 switch((*i)->GetModifier()->m_miscvalue)
1870 case STAT_INTELLECT: intelectLoss += (*i)->GetModifier()->m_amount; break;
1871 case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
1872 default: break;
1877 if(intelectLoss <= -90 && spiritLoss <= -90)
1878 return;
1880 caster = target;
1881 originalCasterGUID = 0;
1882 break;
1884 // Mana Tide
1885 case 16191:
1887 caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID);
1888 return;
1892 // All ok cast by default case
1893 Spell *spell = new Spell(caster, triggredSpellInfo, true, originalCasterGUID );
1895 SpellCastTargets targets;
1896 targets.setUnitTarget( target );
1898 // if spell create dynamic object extract area from it
1899 if(DynamicObject* dynObj = caster->GetDynObject(GetId()))
1900 targets.setDestination(dynObj->GetPositionX(),dynObj->GetPositionY(),dynObj->GetPositionZ());
1902 spell->prepare(&targets, this);
1905 /*********************************************************/
1906 /*** AURA EFFECTS ***/
1907 /*********************************************************/
1909 void Aura::HandleAuraDummy(bool apply, bool Real)
1911 // spells required only Real aura add/remove
1912 if(!Real)
1913 return;
1915 Unit* caster = GetCaster();
1917 // AT APPLY
1918 if(apply)
1920 switch(GetId())
1922 case 1515: // Tame beast
1923 // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
1924 if( caster && m_target->CanHaveThreatList())
1925 m_target->AddThreat(caster, 10.0f);
1926 return;
1927 case 13139: // net-o-matic
1928 // root to self part of (root_target->charge->root_self sequence
1929 if(caster)
1930 caster->CastSpell(caster,13138,true,NULL,this);
1931 return;
1932 case 39850: // Rocket Blast
1933 if(roll_chance_i(20)) // backfire stun
1934 m_target->CastSpell(m_target, 51581, true, NULL, this);
1935 return;
1936 case 43873: // Headless Horseman Laugh
1937 if(caster->GetTypeId() == TYPEID_PLAYER)
1938 ((Player*)caster)->PlaySound(11965, false);
1939 return;
1940 case 46354: // Blood Elf Illusion
1941 if(caster)
1943 switch(caster->getGender())
1945 case GENDER_FEMALE:
1946 caster->CastSpell(m_target,46356,true,NULL,this);
1947 break;
1948 case GENDER_MALE:
1949 caster->CastSpell(m_target,46355,true,NULL,this);
1950 break;
1951 default:
1952 break;
1955 return;
1956 case 46699: // Requires No Ammo
1957 if(m_target->GetTypeId()==TYPEID_PLAYER)
1958 ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
1959 return;
1962 // Earth Shield
1963 if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
1965 // prevent double apply bonuses
1966 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
1967 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
1968 return;
1971 // AT REMOVE
1972 else
1974 if( m_target->GetTypeId() == TYPEID_PLAYER &&
1975 ( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
1976 ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
1978 // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
1979 m_target->SetUInt64Value(PLAYER_FARSIGHT, 0);
1980 WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
1981 ((Player*)m_target)->GetSession()->SendPacket(&data);
1982 return;
1985 if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive())
1987 uint32 finalSpelId = 0;
1988 switch(GetId())
1990 case 19548: finalSpelId = 19597; break;
1991 case 19674: finalSpelId = 19677; break;
1992 case 19687: finalSpelId = 19676; break;
1993 case 19688: finalSpelId = 19678; break;
1994 case 19689: finalSpelId = 19679; break;
1995 case 19692: finalSpelId = 19680; break;
1996 case 19693: finalSpelId = 19684; break;
1997 case 19694: finalSpelId = 19681; break;
1998 case 19696: finalSpelId = 19682; break;
1999 case 19697: finalSpelId = 19683; break;
2000 case 19699: finalSpelId = 19685; break;
2001 case 19700: finalSpelId = 19686; break;
2002 case 30646: finalSpelId = 30647; break;
2003 case 30653: finalSpelId = 30648; break;
2004 case 30654: finalSpelId = 30652; break;
2005 case 30099: finalSpelId = 30100; break;
2006 case 30102: finalSpelId = 30103; break;
2007 case 30105: finalSpelId = 30104; break;
2010 if(finalSpelId)
2011 caster->CastSpell(m_target,finalSpelId,true,NULL,this);
2012 return;
2014 // Dark Fiend
2015 if(GetId()==45934)
2017 // Kill target if dispeled
2018 if (m_removeMode==AURA_REMOVE_BY_DISPEL)
2019 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2020 return;
2023 // Burning Winds
2024 if(GetId()==46308) // casted only at creatures at spawn
2026 m_target->CastSpell(m_target,47287,true,NULL,this);
2027 return;
2031 // AT APPLY & REMOVE
2033 switch(m_spellProto->SpellFamilyName)
2035 case SPELLFAMILY_GENERIC:
2037 // Unstable Power
2038 if( GetId()==24658 )
2040 uint32 spellId = 24659;
2041 if (apply)
2043 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2044 if (!spell)
2045 return;
2046 for (int i=0; i < spell->StackAmount; ++i)
2047 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2048 return;
2050 m_target->RemoveAurasDueToSpell(spellId);
2051 return;
2053 // Restless Strength
2054 if( GetId()==24661 )
2056 uint32 spellId = 24662;
2057 if (apply)
2059 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2060 if (!spell)
2061 return;
2062 for (int i=0; i < spell->StackAmount; ++i)
2063 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2064 return;
2066 m_target->RemoveAurasDueToSpell(spellId);
2067 return;
2069 // Victorious
2070 if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
2072 m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
2073 return;
2075 //Summon Fire Elemental
2076 if (GetId() == 40133 && caster)
2078 Unit *owner = caster->GetOwner();
2079 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2081 if(apply)
2082 owner->CastSpell(owner,8985,true);
2083 else
2084 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2086 return;
2089 //Summon Earth Elemental
2090 if (GetId() == 40132 && caster)
2092 Unit *owner = caster->GetOwner();
2093 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2095 if(apply)
2096 owner->CastSpell(owner,19704,true);
2097 else
2098 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2100 return;
2102 break;
2104 case SPELLFAMILY_MAGE:
2106 // Hypothermia
2107 if( GetId()==41425 )
2109 m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply);
2110 return;
2112 break;
2114 case SPELLFAMILY_DRUID:
2116 // Lifebloom
2117 if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
2119 if ( apply )
2121 if ( caster )
2122 // prevent double apply bonuses
2123 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2124 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2126 else
2128 // Final heal only on dispelled or duration end
2129 if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
2130 return;
2132 // have a look if there is still some other Lifebloom dummy aura
2133 Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2134 for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); itr++)
2135 if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2136 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
2137 return;
2139 // final heal
2140 m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
2142 return;
2145 // Predatory Strikes
2146 if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
2148 ((Player*)m_target)->UpdateAttackPowerAndDamage();
2149 return;
2151 // Idol of the Emerald Queen
2152 if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
2154 if(apply)
2156 SpellModifier *mod = new SpellModifier;
2157 mod->op = SPELLMOD_DOT;
2158 mod->value = m_modifier.m_amount/7;
2159 mod->type = SPELLMOD_FLAT;
2160 mod->spellId = GetId();
2161 mod->effectId = m_effIndex;
2162 mod->lastAffected = NULL;
2163 mod->mask = 0x001000000000LL;
2164 mod->charges = 0;
2166 m_spellmod = mod;
2169 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2170 return;
2172 break;
2174 case SPELLFAMILY_HUNTER:
2176 // Improved Aspect of the Viper
2177 if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
2179 if(apply)
2181 // + effect value for Aspect of the Viper
2182 SpellModifier *mod = new SpellModifier;
2183 mod->op = SPELLMOD_EFFECT1;
2184 mod->value = m_modifier.m_amount;
2185 mod->type = SPELLMOD_FLAT;
2186 mod->spellId = GetId();
2187 mod->effectId = m_effIndex;
2188 mod->lastAffected = NULL;
2189 mod->mask = 0x4000000000000LL;
2190 mod->charges = 0;
2192 m_spellmod = mod;
2195 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2196 return;
2198 break;
2200 case SPELLFAMILY_SHAMAN:
2202 // Improved Weapon Totems
2203 if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
2205 if(apply)
2207 SpellModifier *mod = new SpellModifier;
2208 mod->op = SPELLMOD_EFFECT1;
2209 mod->value = m_modifier.m_amount;
2210 mod->type = SPELLMOD_PCT;
2211 mod->spellId = GetId();
2212 mod->effectId = m_effIndex;
2213 mod->lastAffected = NULL;
2214 switch (m_effIndex)
2216 case 0:
2217 mod->mask = 0x00200000000LL; // Windfury Totem
2218 break;
2219 case 1:
2220 mod->mask = 0x00400000000LL; // Flametongue Totem
2221 break;
2223 mod->charges = 0;
2225 m_spellmod = mod;
2228 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2229 return;
2231 break;
2235 // pet auras
2236 if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
2238 if(apply)
2239 m_target->AddPetAura(petSpell);
2240 else
2241 m_target->RemovePetAura(petSpell);
2242 return;
2246 void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
2248 // spells required only Real aura add/remove
2249 if(!Real)
2250 return;
2252 SpellEntry const*spell = GetSpellProto();
2253 switch( spell->SpellFamilyName)
2255 case SPELLFAMILY_ROGUE:
2257 // Master of Subtlety
2258 if (spell->Id==31666 && !apply && Real)
2260 m_target->RemoveAurasDueToSpell(31665);
2261 break;
2263 break;
2265 case SPELLFAMILY_HUNTER:
2267 // Aspect of the Viper
2268 if (spell->SpellFamilyFlags&0x0004000000000000LL)
2270 // Update regen on remove
2271 if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
2272 ((Player*)m_target)->UpdateManaRegen();
2273 break;
2275 break;
2279 m_isPeriodic = apply;
2282 void Aura::HandleAuraMounted(bool apply, bool Real)
2284 if(apply)
2286 CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2287 if(!ci)
2289 sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
2290 return;
2293 uint32 team = 0;
2294 if (m_target->GetTypeId()==TYPEID_PLAYER)
2295 team = ((Player*)m_target)->GetTeam();
2297 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2298 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2299 if (minfo)
2300 display_id = minfo->modelid;
2302 m_target->Mount(display_id);
2304 else
2306 m_target->Unmount();
2310 void Aura::HandleAuraWaterWalk(bool apply, bool Real)
2312 // only at real add/remove aura
2313 if(!Real)
2314 return;
2316 WorldPacket data;
2317 if(apply)
2318 data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
2319 else
2320 data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
2321 data.append(m_target->GetPackGUID());
2322 data << uint32(0);
2323 m_target->SendMessageToSet(&data,true);
2326 void Aura::HandleAuraFeatherFall(bool apply, bool Real)
2328 // only at real add/remove aura
2329 if(!Real)
2330 return;
2332 WorldPacket data;
2333 if(apply)
2334 data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
2335 else
2336 data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
2337 data.append(m_target->GetPackGUID());
2338 data << (uint32)0;
2339 m_target->SendMessageToSet(&data,true);
2342 void Aura::HandleAuraHover(bool apply, bool Real)
2344 // only at real add/remove aura
2345 if(!Real)
2346 return;
2348 WorldPacket data;
2349 if(apply)
2350 data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
2351 else
2352 data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
2353 data.append(m_target->GetPackGUID());
2354 data << uint32(0);
2355 m_target->SendMessageToSet(&data,true);
2358 void Aura::HandleWaterBreathing(bool apply, bool Real)
2360 if(apply)
2361 m_target->waterbreath = true;
2362 else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
2364 m_target->waterbreath = false;
2366 // update for enable timer in case not moving target
2367 if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
2369 ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
2370 ((Player*)m_target)->HandleDrowning();
2375 void Aura::HandleAuraModShapeshift(bool apply, bool Real)
2377 if(!Real)
2378 return;
2380 uint32 modelid = 0;
2381 Powers PowerType = POWER_MANA;
2382 ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
2383 switch(form)
2385 case FORM_CAT:
2386 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2387 modelid = 892;
2388 else
2389 modelid = 8571;
2390 PowerType = POWER_ENERGY;
2391 break;
2392 case FORM_TRAVEL:
2393 modelid = 632;
2394 break;
2395 case FORM_AQUA:
2396 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2397 modelid = 2428;
2398 else
2399 modelid = 2428;
2400 break;
2401 case FORM_BEAR:
2402 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2403 modelid = 2281;
2404 else
2405 modelid = 2289;
2406 PowerType = POWER_RAGE;
2407 break;
2408 case FORM_GHOUL:
2409 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2410 modelid = 10045;
2411 break;
2412 case FORM_DIREBEAR:
2413 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2414 modelid = 2281;
2415 else
2416 modelid = 2289;
2417 PowerType = POWER_RAGE;
2418 break;
2419 case FORM_CREATUREBEAR:
2420 modelid = 902;
2421 break;
2422 case FORM_GHOSTWOLF:
2423 modelid = 4613;
2424 break;
2425 case FORM_FLIGHT:
2426 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2427 modelid = 20857;
2428 else
2429 modelid = 20872;
2430 break;
2431 case FORM_MOONKIN:
2432 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2433 modelid = 15374;
2434 else
2435 modelid = 15375;
2436 break;
2437 case FORM_FLIGHT_EPIC:
2438 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2439 modelid = 21243;
2440 else
2441 modelid = 21244;
2442 break;
2443 case FORM_AMBIENT:
2444 case FORM_SHADOW:
2445 case FORM_STEALTH:
2446 break;
2447 case FORM_TREE:
2448 modelid = 864;
2449 break;
2450 case FORM_BATTLESTANCE:
2451 case FORM_BERSERKERSTANCE:
2452 case FORM_DEFENSIVESTANCE:
2453 PowerType = POWER_RAGE;
2454 break;
2455 case FORM_SPIRITOFREDEMPTION:
2456 modelid = 16031;
2457 break;
2458 default:
2459 sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
2462 // remove polymorph before changing display id to keep new display id
2463 switch ( form )
2465 case FORM_CAT:
2466 case FORM_TREE:
2467 case FORM_TRAVEL:
2468 case FORM_AQUA:
2469 case FORM_BEAR:
2470 case FORM_DIREBEAR:
2471 case FORM_FLIGHT_EPIC:
2472 case FORM_FLIGHT:
2473 case FORM_MOONKIN:
2474 // remove movement affects
2475 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2476 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2478 // and polymorphic affects
2479 if(m_target->IsPolymorphed())
2480 m_target->RemoveAurasDueToSpell(m_target->getTransForm());
2481 break;
2482 default:
2483 break;
2486 if(apply)
2488 // remove other shapeshift before applying a new one
2489 if(m_target->m_ShapeShiftFormSpellId)
2490 m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
2492 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
2494 if(modelid > 0)
2495 m_target->SetDisplayId(modelid);
2497 if(PowerType != POWER_MANA)
2499 // reset power to default values only at power change
2500 if(m_target->getPowerType()!=PowerType)
2501 m_target->setPowerType(PowerType);
2503 switch(form)
2505 case FORM_CAT:
2506 case FORM_BEAR:
2507 case FORM_DIREBEAR:
2509 // get furor proc chance
2510 uint32 FurorChance = 0;
2511 Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2512 for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
2514 if ((*i)->GetSpellProto()->SpellIconID == 238)
2516 FurorChance = (*i)->GetModifier()->m_amount;
2517 break;
2521 if (m_modifier.m_miscvalue == FORM_CAT)
2523 m_target->SetPower(POWER_ENERGY,0);
2524 if(urand(1,100) <= FurorChance)
2525 m_target->CastSpell(m_target,17099,true,NULL,this);
2527 else
2529 m_target->SetPower(POWER_RAGE,0);
2530 if(urand(1,100) <= FurorChance)
2531 m_target->CastSpell(m_target,17057,true,NULL,this);
2533 break;
2535 case FORM_BATTLESTANCE:
2536 case FORM_DEFENSIVESTANCE:
2537 case FORM_BERSERKERSTANCE:
2539 uint32 Rage_val = 0;
2540 // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
2541 if(m_target->GetTypeId() == TYPEID_PLAYER)
2543 PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
2544 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2546 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
2547 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2548 if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
2549 Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
2553 if (m_target->GetPower(POWER_RAGE) > Rage_val)
2554 m_target->SetPower(POWER_RAGE,Rage_val);
2555 break;
2557 default:
2558 break;
2562 m_target->m_ShapeShiftFormSpellId = GetId();
2563 m_target->m_form = form;
2565 else
2567 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2568 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
2569 if(m_target->getClass() == CLASS_DRUID)
2570 m_target->setPowerType(POWER_MANA);
2571 m_target->m_ShapeShiftFormSpellId = 0;
2572 m_target->m_form = FORM_NONE;
2574 switch(form)
2576 // Nordrassil Harness - bonus
2577 case FORM_BEAR:
2578 case FORM_DIREBEAR:
2579 case FORM_CAT:
2581 if(Aura* dummy = m_target->GetDummyAura(37315) )
2582 m_target->CastSpell(m_target,37316,true,NULL,dummy);
2583 break;
2585 // Nordrassil Regalia - bonus
2586 case FORM_MOONKIN:
2588 if(Aura* dummy = m_target->GetDummyAura(37324) )
2589 m_target->CastSpell(m_target,37325,true,NULL,dummy);
2590 break;
2595 // adding/removing linked auras
2596 // add/remove the shapeshift aura's boosts
2597 HandleShapeshiftBoosts(apply);
2599 if(m_target->GetTypeId()==TYPEID_PLAYER)
2600 ((Player*)m_target)->InitDataForForm();
2603 void Aura::HandleAuraTransform(bool apply, bool Real)
2605 if (apply)
2607 // special case (spell specific functionality)
2608 if(m_modifier.m_miscvalue==0)
2610 // player applied only
2611 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2612 return;
2614 switch(GetId())
2616 // Orb of Deception
2617 case 16739:
2619 uint32 orb_model = m_target->GetNativeDisplayId();
2620 switch(orb_model)
2622 // Troll Female
2623 case 1479: m_target->SetDisplayId(10134); break;
2624 // Troll Male
2625 case 1478: m_target->SetDisplayId(10135); break;
2626 // Tauren Male
2627 case 59: m_target->SetDisplayId(10136); break;
2628 // Human Male
2629 case 49: m_target->SetDisplayId(10137); break;
2630 // Human Female
2631 case 50: m_target->SetDisplayId(10138); break;
2632 // Orc Male
2633 case 51: m_target->SetDisplayId(10139); break;
2634 // Orc Female
2635 case 52: m_target->SetDisplayId(10140); break;
2636 // Dwarf Male
2637 case 53: m_target->SetDisplayId(10141); break;
2638 // Dwarf Female
2639 case 54: m_target->SetDisplayId(10142); break;
2640 // NightElf Male
2641 case 55: m_target->SetDisplayId(10143); break;
2642 // NightElf Female
2643 case 56: m_target->SetDisplayId(10144); break;
2644 // Undead Female
2645 case 58: m_target->SetDisplayId(10145); break;
2646 // Undead Male
2647 case 57: m_target->SetDisplayId(10146); break;
2648 // Tauren Female
2649 case 60: m_target->SetDisplayId(10147); break;
2650 // Gnome Male
2651 case 1563: m_target->SetDisplayId(10148); break;
2652 // Gnome Female
2653 case 1564: m_target->SetDisplayId(10149); break;
2654 // BloodElf Female
2655 case 15475: m_target->SetDisplayId(17830); break;
2656 // BloodElf Male
2657 case 15476: m_target->SetDisplayId(17829); break;
2658 // Dranei Female
2659 case 16126: m_target->SetDisplayId(17828); break;
2660 // Dranei Male
2661 case 16125: m_target->SetDisplayId(17827); break;
2662 default: break;
2664 break;
2666 // Murloc costume
2667 case 42365: m_target->SetDisplayId(21723); break;
2668 default: break;
2671 else
2673 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2674 if(!ci)
2676 //pig pink ^_^
2677 m_target->SetDisplayId(16358);
2678 sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
2680 else
2682 // Will use the default model here
2683 m_target->SetDisplayId(ci->DisplayID_A);
2685 // Dragonmaw Illusion (set mount model also)
2686 if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
2687 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
2689 m_target->setTransForm(GetId());
2692 // polymorph case
2693 if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
2695 // for players, start regeneration after 1s (in polymorph fast regeneration case)
2696 // only if caster is Player (after patch 2.4.2)
2697 if(IS_PLAYER_GUID(GetCasterGUID()) )
2698 ((Player*)m_target)->setRegenTimer(1000);
2700 //dismount polymorphed target (after patch 2.4.2)
2701 if (m_target->IsMounted())
2702 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2705 else
2707 Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
2708 if(otherTransforms.empty())
2710 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2711 m_target->setTransForm(0);
2713 else
2715 // look for other transform auras
2716 Aura* handledAura = *otherTransforms.begin();
2717 for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
2719 // negative auras are prefered
2720 if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
2722 handledAura = *i;
2723 break;
2726 handledAura->ApplyModifier(true);
2729 // Dragonmaw Illusion (restore mount model)
2730 if(GetId()==42016 && m_target->GetMountID()==16314)
2732 if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
2734 uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
2735 if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
2737 uint32 team = 0;
2738 if (m_target->GetTypeId()==TYPEID_PLAYER)
2739 team = ((Player*)m_target)->GetTeam();
2741 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2742 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2743 if (minfo)
2744 display_id = minfo->modelid;
2746 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
2753 void Aura::HandleForceReaction(bool apply, bool Real)
2755 if(m_target->GetTypeId() != TYPEID_PLAYER)
2756 return;
2758 if(!Real)
2759 return;
2761 Player* player = (Player*)m_target;
2763 uint32 faction_id = m_modifier.m_miscvalue;
2764 uint32 faction_rank = m_modifier.m_amount;
2766 if(apply)
2767 player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
2768 else
2769 player->m_forcedReactions.erase(faction_id);
2771 WorldPacket data;
2772 data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
2773 data << uint32(player->m_forcedReactions.size());
2774 for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
2776 data << uint32(itr->first); // faction_id (Faction.dbc)
2777 data << uint32(itr->second); // reputation rank
2779 player->SendDirectMessage(&data);
2782 void Aura::HandleAuraModSkill(bool apply, bool Real)
2784 if(m_target->GetTypeId() != TYPEID_PLAYER)
2785 return;
2787 uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
2788 int32 points = GetModifier()->m_amount;
2790 ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
2791 if(prot == SKILL_DEFENSE)
2792 ((Player*)m_target)->UpdateDefenseBonusesMod();
2795 void Aura::HandleChannelDeathItem(bool apply, bool Real)
2797 if(Real && !apply)
2799 Unit* caster = GetCaster();
2800 Unit* victim = GetTarget();
2801 if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
2802 return;
2804 SpellEntry const *spellInfo = GetSpellProto();
2805 if(spellInfo->EffectItemType[m_effIndex] == 0)
2806 return;
2808 // Soul Shard only from non-grey units
2809 if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
2810 (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
2811 victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
2812 return;
2813 ItemPosCountVec dest;
2814 uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
2815 if( msg != EQUIP_ERR_OK )
2817 ((Player*)caster)->SendEquipError( msg, NULL, NULL );
2818 return;
2821 Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
2822 ((Player*)caster)->SendNewItem(newitem, 1, true, false);
2826 void Aura::HandleBindSight(bool apply, bool Real)
2828 Unit* caster = GetCaster();
2829 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2830 return;
2832 caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0);
2835 void Aura::HandleFarSight(bool apply, bool Real)
2837 Unit* caster = GetCaster();
2838 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2839 return;
2841 caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_modifier.m_miscvalue : 0);
2844 void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
2846 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2847 return;
2849 if(apply)
2850 m_target->RemoveNoStackAurasDueToAura(this);
2851 m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
2854 void Aura::HandleAuraTrackResources(bool apply, bool Real)
2856 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2857 return;
2859 if(apply)
2860 m_target->RemoveNoStackAurasDueToAura(this);
2861 m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
2864 void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
2866 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2867 return;
2869 if(apply)
2870 m_target->RemoveNoStackAurasDueToAura(this);
2872 m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
2875 void Aura::HandleAuraModScale(bool apply, bool Real)
2877 m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
2880 void Aura::HandleModPossess(bool apply, bool Real)
2882 if(!Real)
2883 return;
2885 if(m_target->getLevel() > m_modifier.m_amount)
2886 return;
2888 // not possess yourself
2889 if(GetCasterGUID() == m_target->GetGUID())
2890 return;
2892 Unit* caster = GetCaster();
2893 if(!caster)
2894 return;
2896 if( apply )
2898 m_target->SetCharmerGUID(GetCasterGUID());
2899 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
2900 caster->SetCharm(m_target);
2902 m_target->CombatStop();
2903 m_target->DeleteThreatList();
2904 if(m_target->GetTypeId() == TYPEID_UNIT)
2906 m_target->StopMoving();
2907 m_target->GetMotionMaster()->Clear();
2908 m_target->GetMotionMaster()->MoveIdle();
2909 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
2910 charmInfo->InitPossessCreateSpells();
2913 if(caster->GetTypeId() == TYPEID_PLAYER)
2915 ((Player*)caster)->PossessSpellInitialize();
2918 else
2920 m_target->SetCharmerGUID(0);
2922 if(m_target->GetTypeId() == TYPEID_PLAYER)
2923 ((Player*)m_target)->setFactionForRace(m_target->getRace());
2924 else if(m_target->GetTypeId() == TYPEID_UNIT)
2926 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
2927 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
2930 caster->SetCharm(0);
2932 if(caster->GetTypeId() == TYPEID_PLAYER)
2934 WorldPacket data(SMSG_PET_SPELLS, 8);
2935 data << uint64(0);
2936 ((Player*)caster)->GetSession()->SendPacket(&data);
2938 if(m_target->GetTypeId() == TYPEID_UNIT)
2940 ((Creature*)m_target)->AIM_Initialize();
2942 if (((Creature*)m_target)->AI())
2943 ((Creature*)m_target)->AI()->AttackStart(caster);
2946 if(caster->GetTypeId() == TYPEID_PLAYER)
2947 caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0);
2950 void Aura::HandleModPossessPet(bool apply, bool Real)
2952 if(!Real)
2953 return;
2955 Unit* caster = GetCaster();
2956 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2957 return;
2958 if(caster->GetPet() != m_target)
2959 return;
2961 if(apply)
2963 caster->SetUInt64Value(PLAYER_FARSIGHT, m_target->GetGUID());
2964 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2966 else
2968 caster->SetUInt64Value(PLAYER_FARSIGHT, 0);
2969 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
2973 void Aura::HandleModCharm(bool apply, bool Real)
2975 if(!Real)
2976 return;
2978 // not charm yourself
2979 if(GetCasterGUID() == m_target->GetGUID())
2980 return;
2982 Unit* caster = GetCaster();
2983 if(!caster)
2984 return;
2986 if(int32(m_target->getLevel()) <= m_modifier.m_amount)
2988 if( apply )
2990 m_target->SetCharmerGUID(GetCasterGUID());
2991 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
2992 m_target->CastStop(m_target==caster ? GetId() : 0);
2993 caster->SetCharm(m_target);
2995 m_target->CombatStop();
2996 m_target->DeleteThreatList();
2998 if(m_target->GetTypeId() == TYPEID_UNIT)
3000 ((Creature*)m_target)->AIM_Initialize();
3001 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3002 charmInfo->InitCharmCreateSpells();
3003 charmInfo->SetReactState( REACT_DEFENSIVE );
3005 if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
3007 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3008 if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
3010 //to prevent client crash
3011 m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
3012 //just to enable stat window
3013 charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
3014 //if charmed two demons the same session, the 2nd gets the 1st one's name
3015 m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
3020 if(caster->GetTypeId() == TYPEID_PLAYER)
3022 ((Player*)caster)->CharmSpellInitialize();
3025 else
3027 m_target->SetCharmerGUID(0);
3029 if(m_target->GetTypeId() == TYPEID_PLAYER)
3030 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3031 else
3033 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3035 // restore faction
3036 if(((Creature*)m_target)->isPet())
3038 if(Unit* owner = m_target->GetOwner())
3039 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
3040 else if(cinfo)
3041 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3043 else if(cinfo) // normal creature
3044 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3046 // restore UNIT_FIELD_BYTES_0
3047 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
3049 CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
3050 if(cainfo && cainfo->bytes0 != 0)
3051 m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
3052 else
3053 m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
3055 if(m_target->GetCharmInfo())
3056 m_target->GetCharmInfo()->SetPetNumber(0, true);
3057 else
3058 sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
3062 caster->SetCharm(0);
3064 if(caster->GetTypeId() == TYPEID_PLAYER)
3066 WorldPacket data(SMSG_PET_SPELLS, 8);
3067 data << uint64(0);
3068 ((Player*)caster)->GetSession()->SendPacket(&data);
3070 if(m_target->GetTypeId() == TYPEID_UNIT)
3072 ((Creature*)m_target)->AIM_Initialize();
3073 if (((Creature*)m_target)->AI())
3074 ((Creature*)m_target)->AI()->AttackStart(caster);
3080 void Aura::HandleModConfuse(bool apply, bool Real)
3082 if(!Real)
3083 return;
3085 m_target->SetConfused(apply, GetCasterGUID(), GetId());
3088 void Aura::HandleModFear(bool apply, bool Real)
3090 if (!Real)
3091 return;
3093 m_target->SetFeared(apply, GetCasterGUID(), GetId());
3096 void Aura::HandleFeignDeath(bool apply, bool Real)
3098 if(!Real)
3099 return;
3101 if(m_target->GetTypeId() != TYPEID_PLAYER)
3102 return;
3104 if( apply )
3107 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3108 data<<m_target->GetGUID();
3109 data<<uint8(0);
3110 m_target->SendMessageToSet(&data,true);
3112 // blizz like 2.0.x
3113 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3114 // blizz like 2.0.x
3115 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3116 // blizz like 2.0.x
3117 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3119 m_target->addUnitState(UNIT_STAT_DIED);
3120 m_target->CombatStop();
3122 // prevent interrupt message
3123 if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
3124 m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
3125 m_target->InterruptNonMeleeSpells(true);
3126 m_target->getHostilRefManager().deleteReferences();
3128 else
3131 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3132 data<<m_target->GetGUID();
3133 data<<uint8(1);
3134 m_target->SendMessageToSet(&data,true);
3136 // blizz like 2.0.x
3137 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3138 // blizz like 2.0.x
3139 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3140 // blizz like 2.0.x
3141 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3143 m_target->clearUnitState(UNIT_STAT_DIED);
3147 void Aura::HandleAuraModDisarm(bool apply, bool Real)
3149 if(!Real)
3150 return;
3152 if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
3153 return;
3155 // not sure for it's correctness
3156 if(apply)
3157 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3158 else
3159 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3161 // only at real add/remove aura
3162 if (m_target->GetTypeId() != TYPEID_PLAYER)
3163 return;
3165 // main-hand attack speed already set to special value for feral form already and don't must chnage and reset at remove.
3166 if (((Player *)m_target)->IsInFeralForm())
3167 return;
3169 if (apply)
3170 m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
3171 else
3172 ((Player *)m_target)->SetRegularAttackTime();
3174 m_target->UpdateDamagePhysical(BASE_ATTACK);
3177 void Aura::HandleAuraModStun(bool apply, bool Real)
3179 if(!Real)
3180 return;
3182 if (apply)
3184 m_target->addUnitState(UNIT_STAT_STUNNED);
3185 m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
3187 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
3188 m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
3190 // Creature specific
3191 if(m_target->GetTypeId() != TYPEID_PLAYER)
3192 ((Creature*)m_target)->StopMoving();
3193 else
3194 m_target->SetUnitMovementFlags(0); //Clear movement flags
3196 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
3198 data.append(m_target->GetPackGUID());
3199 data << uint32(0);
3200 m_target->SendMessageToSet(&data,true);
3202 else
3204 // Real remove called after current aura remove from lists, check if other similar auras active
3205 if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
3206 return;
3208 m_target->clearUnitState(UNIT_STAT_STUNNED);
3209 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
3211 if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
3213 if(m_target->getVictim() && m_target->isAlive())
3214 m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3216 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
3217 data.append(m_target->GetPackGUID());
3218 data << uint32(0);
3219 m_target->SendMessageToSet(&data,true);
3222 // Wyvern Sting
3223 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
3225 Unit* caster = GetCaster();
3226 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
3227 return;
3229 uint32 spell_id = 0;
3231 switch(GetId())
3233 case 19386: spell_id = 24131; break;
3234 case 24132: spell_id = 24134; break;
3235 case 24133: spell_id = 24135; break;
3236 case 27068: spell_id = 27069; break;
3237 default:
3238 sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
3239 return;
3242 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
3244 if(!spellInfo)
3245 return;
3247 caster->CastSpell(m_target,spellInfo,true,NULL,this);
3248 return;
3253 void Aura::HandleModStealth(bool apply, bool Real)
3255 if(apply)
3257 // drop flag at stealth in bg
3258 if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
3259 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3260 bg->EventPlayerDroppedFlag((Player*)m_target);
3262 // only at real aura add
3263 if(Real)
3265 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
3266 if(m_target->GetTypeId()==TYPEID_PLAYER)
3267 m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
3269 // apply only if not in GM invisibility (and overwrite invisibility state)
3270 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3272 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3273 m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
3276 // for RACE_NIGHTELF stealth
3277 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3278 m_target->CastSpell(m_target, 21009, true, NULL, this);
3281 else
3283 // only at real aura remove
3284 if(Real)
3286 // for RACE_NIGHTELF stealth
3287 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3288 m_target->RemoveAurasDueToSpell(21009);
3290 // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
3291 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
3293 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
3294 if(m_target->GetTypeId()==TYPEID_PLAYER)
3295 m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
3297 // restore invisibility if any
3298 if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
3300 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3301 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3303 else
3304 m_target->SetVisibility(VISIBILITY_ON);
3309 // Master of Subtlety
3310 Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
3311 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
3313 if ((*i)->GetSpellProto()->SpellIconID == 2114)
3315 if (apply)
3317 int32 bp = (*i)->GetModifier()->m_amount;
3318 m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
3320 else
3321 m_target->CastSpell(m_target,31666,true);
3322 break;
3327 void Aura::HandleInvisibility(bool apply, bool Real)
3329 if(apply)
3331 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3333 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3335 // apply glow vision
3336 m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3338 // drop flag at invisible in bg
3339 if(((Player*)m_target)->InBattleGround())
3340 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3341 bg->EventPlayerDroppedFlag((Player*)m_target);
3344 // apply only if not in GM invisibility and not stealth
3345 if(m_target->GetVisibility()==VISIBILITY_ON)
3347 // Aura not added yet but visibility code expect temporary add aura
3348 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3349 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3352 else
3354 // recalculate value at modifier remove (current aura already removed)
3355 m_target->m_invisibilityMask = 0;
3356 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
3357 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3358 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3360 // only at real aura remove and if not have different invisibility auras.
3361 if(Real && m_target->m_invisibilityMask==0)
3363 // remove glow vision
3364 if(m_target->GetTypeId() == TYPEID_PLAYER)
3365 m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3367 // apply only if not in GM invisibility & not stealthed while invisible
3368 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3370 // if have stealth aura then already have stealth visibility
3371 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
3372 m_target->SetVisibility(VISIBILITY_ON);
3378 void Aura::HandleInvisibilityDetect(bool apply, bool Real)
3380 if(apply)
3382 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3384 else
3386 // recalculate value at modifier remove (current aura already removed)
3387 m_target->m_detectInvisibilityMask = 0;
3388 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
3389 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3390 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3392 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3393 ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
3396 void Aura::HandleAuraModRoot(bool apply, bool Real)
3398 // only at real add/remove aura
3399 if(!Real)
3400 return;
3402 uint32 apply_stat = UNIT_STAT_ROOT;
3403 if (apply)
3405 m_target->addUnitState(UNIT_STAT_ROOT);
3406 m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
3407 // probably wrong
3408 m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3410 //Save last orientation
3411 if( m_target->getVictim() )
3412 m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
3414 if(m_target->GetTypeId() == TYPEID_PLAYER)
3416 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
3417 data.append(m_target->GetPackGUID());
3418 data << (uint32)2;
3419 m_target->SendMessageToSet(&data,true);
3421 //Clear unit movement flags
3422 m_target->SetUnitMovementFlags(0);
3424 else
3425 ((Creature *)m_target)->StopMoving();
3427 else
3429 // Real remove called after current aura remove from lists, check if other similar auras active
3430 if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
3431 return;
3433 m_target->clearUnitState(UNIT_STAT_ROOT);
3434 // probably wrong
3435 m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3437 if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
3439 if(m_target->getVictim() && m_target->isAlive())
3440 m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3442 if(m_target->GetTypeId() == TYPEID_PLAYER)
3444 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
3445 data.append(m_target->GetPackGUID());
3446 data << (uint32)2;
3447 m_target->SendMessageToSet(&data,true);
3453 void Aura::HandleAuraModSilence(bool apply, bool Real)
3455 // only at real add/remove aura
3456 if(!Real)
3457 return;
3459 if(apply)
3461 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3462 // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3463 for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
3465 Spell* currentSpell = m_target->m_currentSpells[i];
3466 if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
3468 uint32 state = currentSpell->getState();
3469 // Stop spells on prepere or casting state
3470 if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
3472 currentSpell->cancel();
3473 currentSpell->SetDeletable(true);
3474 m_target->m_currentSpells[i] = NULL;
3479 switch (GetId())
3481 // Arcane Torrent (Energy)
3482 case 25046:
3484 Unit * caster = GetCaster();
3485 if (!caster)
3486 return;
3488 // Search Mana Tap auras on caster
3489 int32 energy = 0;
3490 Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
3491 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3492 if ((*i)->GetId() == 28734)
3493 ++energy;
3494 if (energy)
3496 energy *= 10;
3497 caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true);
3498 caster->RemoveAurasDueToSpell(28734);
3503 else
3505 // Real remove called after current aura remove from lists, check if other similar auras active
3506 if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
3507 return;
3509 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3513 void Aura::HandleModThreat(bool apply, bool Real)
3515 // only at real add/remove aura
3516 if(!Real)
3517 return;
3519 if(!m_target->isAlive())
3520 return;
3522 Unit* caster = GetCaster();
3524 if(!caster || !caster->isAlive())
3525 return;
3527 int level_diff = 0;
3528 int multiplier = 0;
3529 switch (GetId())
3531 // Arcane Shroud
3532 case 26400:
3533 level_diff = m_target->getLevel() - 60;
3534 multiplier = 2;
3535 break;
3536 // The Eye of Diminution
3537 case 28862:
3538 level_diff = m_target->getLevel() - 60;
3539 multiplier = 1;
3540 break;
3542 if (level_diff > 0)
3543 m_modifier.m_amount += multiplier * level_diff;
3545 for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
3547 if(m_modifier.m_miscvalue & int32(1<<x))
3549 if(m_target->GetTypeId() == TYPEID_PLAYER)
3550 ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
3555 void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
3557 // only at real add/remove aura
3558 if(!Real)
3559 return;
3561 if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
3562 return;
3564 Unit* caster = GetCaster();
3566 if(!caster || !caster->isAlive())
3567 return;
3569 float threatMod = 0.0f;
3570 if(apply)
3571 threatMod = float(m_modifier.m_amount);
3572 else
3573 threatMod = float(-m_modifier.m_amount);
3575 m_target->getHostilRefManager().threatAssist(caster, threatMod);
3578 void Aura::HandleModTaunt(bool apply, bool Real)
3580 // only at real add/remove aura
3581 if(!Real)
3582 return;
3584 if(!m_target->isAlive() || !m_target->CanHaveThreatList())
3585 return;
3587 Unit* caster = GetCaster();
3589 if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
3590 return;
3592 if(apply)
3593 m_target->TauntApply(caster);
3594 else
3596 // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
3597 m_target->TauntFadeOut(caster);
3601 /*********************************************************/
3602 /*** MODIFY SPEED ***/
3603 /*********************************************************/
3604 void Aura::HandleAuraModIncreaseSpeed(bool apply, bool Real)
3606 // all applied/removed only at real aura add/remove
3607 if(!Real)
3608 return;
3610 m_target->UpdateSpeed(MOVE_RUN, true);
3613 void Aura::HandleAuraModIncreaseMountedSpeed(bool apply, bool Real)
3615 // all applied/removed only at real aura add/remove
3616 if(!Real)
3617 return;
3619 m_target->UpdateSpeed(MOVE_RUN, true);
3622 void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
3624 // all applied/removed only at real aura add/remove
3625 if(!Real)
3626 return;
3628 // Enable Fly mode for flying mounts
3629 if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
3631 WorldPacket data;
3632 if(apply)
3633 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
3634 else
3635 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
3636 data.append(m_target->GetPackGUID());
3637 data << uint32(0); // unknown
3638 m_target->SendMessageToSet(&data, true);
3640 //Players on flying mounts must be immune to polymorph
3641 if (m_target->GetTypeId()==TYPEID_PLAYER)
3642 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
3644 // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
3645 if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
3646 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
3649 m_target->UpdateSpeed(MOVE_FLY, true);
3652 void Aura::HandleAuraModIncreaseSwimSpeed(bool apply, bool Real)
3654 // all applied/removed only at real aura add/remove
3655 if(!Real)
3656 return;
3658 m_target->UpdateSpeed(MOVE_SWIM, true);
3661 void Aura::HandleAuraModDecreaseSpeed(bool apply, bool Real)
3663 // all applied/removed only at real aura add/remove
3664 if(!Real)
3665 return;
3667 m_target->UpdateSpeed(MOVE_RUN, true);
3668 m_target->UpdateSpeed(MOVE_SWIM, true);
3669 m_target->UpdateSpeed(MOVE_FLY, true);
3672 void Aura::HandleAuraModUseNormalSpeed(bool apply, bool Real)
3674 // all applied/removed only at real aura add/remove
3675 if(!Real)
3676 return;
3678 m_target->UpdateSpeed(MOVE_RUN, true);
3679 m_target->UpdateSpeed(MOVE_SWIM, true);
3680 m_target->UpdateSpeed(MOVE_FLY, true);
3683 /*********************************************************/
3684 /*** IMMUNITY ***/
3685 /*********************************************************/
3687 void Aura::HandleModMechanicImmunity(bool apply, bool Real)
3689 uint32 mechanic = 1 << m_modifier.m_miscvalue;
3691 //immune movement impairment and loss of control
3692 if(GetId()==42292)
3693 mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
3695 if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3697 Unit::AuraMap& Auras = m_target->GetAuras();
3698 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3700 next = iter;
3701 ++next;
3702 SpellEntry const *spell = iter->second->GetSpellProto();
3703 if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
3704 && !iter->second->IsPositive() // only remove negative spells
3705 && spell->Id != GetId())
3707 //check for mechanic mask
3708 if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
3710 m_target->RemoveAurasDueToSpell(spell->Id);
3711 if(Auras.empty())
3712 break;
3713 else
3714 next = Auras.begin();
3720 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
3722 // special cases
3723 switch(m_modifier.m_miscvalue)
3725 case MECHANIC_INVULNERABILITY:
3726 m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply);
3727 break;
3728 case MECHANIC_SHIELD:
3729 m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply);
3730 break;
3733 // Bestial Wrath
3734 if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
3736 // The Beast Within cast on owner if talent present
3737 if ( Unit* owner = m_target->GetOwner() )
3739 // Search talent
3740 Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
3741 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3743 if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
3745 if (apply)
3746 owner->CastSpell(owner, 34471, true, 0, this);
3747 else
3748 owner->RemoveAurasDueToSpell(34471);
3749 break;
3755 // The Beast Within and Bestial Wrath - immunity
3756 if(GetId() == 19574 || GetId() == 34471)
3758 if(apply)
3760 m_target->CastSpell(m_target,24395,true);
3761 m_target->CastSpell(m_target,24396,true);
3762 m_target->CastSpell(m_target,24397,true);
3763 m_target->CastSpell(m_target,26592,true);
3765 else
3767 m_target->RemoveAurasDueToSpell(24395);
3768 m_target->RemoveAurasDueToSpell(24396);
3769 m_target->RemoveAurasDueToSpell(24397);
3770 m_target->RemoveAurasDueToSpell(26592);
3775 void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
3777 if(!apply)
3779 if(m_target->GetTypeId() == TYPEID_PLAYER)
3781 if(((Player*)m_target)->InBattleGround())
3783 BattleGround *bg = ((Player*)m_target)->GetBattleGround();
3784 if(bg)
3786 switch(bg->GetTypeID())
3788 case BATTLEGROUND_AV:
3790 break;
3792 case BATTLEGROUND_WS:
3794 // Warsong Flag, horde // Silverwing Flag, alliance
3795 if(GetId() == 23333 || GetId() == 23335)
3796 bg->EventPlayerDroppedFlag(((Player*)m_target));
3797 break;
3799 case BATTLEGROUND_AB:
3801 break;
3803 case BATTLEGROUND_EY:
3805 if(GetId() == 34976)
3806 bg->EventPlayerDroppedFlag(((Player*)m_target));
3807 break;
3815 m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
3818 void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
3820 if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3822 Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
3823 for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
3825 if (auraList.front() != this) // skip itself aura (it already added)
3827 m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
3828 itr = auraList.begin();
3830 else
3831 ++itr;
3835 m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
3838 void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
3840 m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
3842 if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3844 if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
3846 uint32 school_mask = m_modifier.m_miscvalue;
3847 Unit::AuraMap& Auras = m_target->GetAuras();
3848 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3850 next = iter;
3851 ++next;
3852 SpellEntry const *spell = iter->second->GetSpellProto();
3853 if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
3854 && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
3855 && !iter->second->IsPositive() //Don't remove positive spells
3856 && spell->Id != GetId() ) //Don't remove self
3858 m_target->RemoveAurasDueToSpell(spell->Id);
3859 if(Auras.empty())
3860 break;
3861 else
3862 next = Auras.begin();
3867 if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
3869 if( apply )
3870 m_target->addUnitState(UNIT_STAT_ISOLATED);
3871 else
3872 m_target->clearUnitState(UNIT_STAT_ISOLATED);
3876 void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
3878 m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
3881 void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
3883 // all applied/removed only at real aura add/remove
3884 if(!Real)
3885 return;
3887 m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
3890 void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
3892 if(!Real)
3893 return;
3895 if(apply)
3897 // some spell have charges by functionality not have its in spell data
3898 switch (GetId())
3900 case 28200: // Ascendance (Talisman of Ascendance trinket)
3901 m_procCharges = 6;
3902 UpdateAuraCharges();
3903 break;
3904 default: break;
3909 void Aura::HandleAuraModStalked(bool apply, bool Real)
3911 // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
3912 if(apply)
3913 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3914 else
3915 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
3918 /*********************************************************/
3919 /*** PERIODIC ***/
3920 /*********************************************************/
3922 void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
3924 if (m_periodicTimer <= 0)
3925 m_periodicTimer += m_modifier.periodictime;
3927 m_isPeriodic = apply;
3928 m_isTrigger = apply;
3930 // Curse of the Plaguebringer
3931 if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL)
3933 // Cast Wrath of the Plaguebringer if not dispelled
3934 m_target->CastSpell(m_target, 29214, true, 0, this);
3938 void Aura::HandlePeriodicEnergize(bool apply, bool Real)
3940 if (m_periodicTimer <= 0)
3941 m_periodicTimer += m_modifier.periodictime;
3943 m_isPeriodic = apply;
3946 void Aura::HandlePeriodicHeal(bool apply, bool Real)
3948 if (m_periodicTimer <= 0)
3949 m_periodicTimer += m_modifier.periodictime;
3951 m_isPeriodic = apply;
3953 // only at real apply
3954 if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE)
3956 // provided m_target as original caster to prevent apply aura caster selection for this negative buff
3957 m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID());
3960 // For prevent double apply bonuses
3961 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
3963 if(!loading && apply)
3965 switch (m_spellProto->SpellFamilyName)
3967 case SPELLFAMILY_DRUID:
3969 // Rejuvenation
3970 if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
3972 if(Unit* caster = GetCaster())
3974 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
3975 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
3977 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
3978 switch((*k)->GetModifier()->m_miscvalue)
3980 case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
3981 case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
3983 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
3984 break;
3995 void Aura::HandlePeriodicDamage(bool apply, bool Real)
3997 // spells required only Real aura add/remove
3998 if(!Real)
3999 return;
4001 if (m_periodicTimer <= 0)
4002 m_periodicTimer += m_modifier.periodictime;
4004 m_isPeriodic = apply;
4006 // For prevent double apply bonuses
4007 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4009 Unit *caster = GetCaster();
4011 switch (m_spellProto->SpellFamilyName)
4013 case SPELLFAMILY_GENERIC:
4015 // Pounce Bleed
4016 if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 )
4018 // $AP*0.18/6 bonus per tick
4019 if (apply && !loading && caster)
4020 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4021 return;
4023 break;
4025 case SPELLFAMILY_WARRIOR:
4027 // Rend
4028 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4030 // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
4031 if (apply && !loading && caster)
4033 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4034 int32 mws = caster->GetAttackTime(BASE_ATTACK);
4035 float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
4036 float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
4037 // WARNING! in 3.0 multipler 0.00743f change to 0.6
4038 m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
4040 return;
4042 break;
4044 case SPELLFAMILY_DRUID:
4046 // Rake
4047 if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
4049 // $AP*0.06/3 bonus per tick
4050 if (apply && !loading && caster)
4051 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
4052 return;
4054 // Lacerate
4055 if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
4057 // $AP*0.05/5 bonus per tick
4058 if (apply && !loading && caster)
4059 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
4060 return;
4062 // Rip
4063 if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
4065 // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, wheather 4 or 5 CPs are being used]
4066 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4068 uint8 cp = ((Player*)caster)->GetComboPoints();
4070 // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
4071 Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
4072 for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
4074 if((*itr)->GetId()==34241)
4076 m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
4077 break;
4081 if (cp > 4) cp = 4;
4082 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4084 return;
4086 break;
4088 case SPELLFAMILY_ROGUE:
4090 // Deadly poison aura state
4091 if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100)
4093 if(apply)
4094 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
4095 else
4097 // current aura already removed, search present of another
4098 bool found = false;
4099 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
4100 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
4102 SpellEntry const* itr_spell = (*itr)->GetSpellProto();
4103 if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100)
4105 found = true;
4106 break;
4109 // this has been last deadly poison aura
4110 if(!found)
4111 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
4113 return;
4115 // Rupture
4116 if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
4118 // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP inrease the contribution from AP]
4119 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4121 uint8 cp = ((Player*)caster)->GetComboPoints();
4122 if (cp > 3) cp = 3;
4123 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4125 return;
4127 // Garrote
4128 if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
4130 // $AP*0.18/6 bonus per tick
4131 if (apply && !loading && caster)
4132 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4133 return;
4135 break;
4137 case SPELLFAMILY_HUNTER:
4139 // Serpent Sting
4140 if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
4142 // $RAP*0.1/5 bonus per tick
4143 if (apply && !loading && caster)
4144 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4145 return;
4147 // Immolation Trap
4148 if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
4150 // $RAP*0.1/5 bonus per tick
4151 if (apply && !loading && caster)
4152 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4153 return;
4155 break;
4157 case SPELLFAMILY_PALADIN:
4159 // Consecration
4160 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4162 if (apply && !loading)
4164 if(Unit* caster = GetCaster())
4166 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4167 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4169 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4170 switch((*k)->GetModifier()->m_miscvalue)
4172 case 5147: // Improved Consecration - Libram of the Eternal Rest
4174 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4175 break;
4181 return;
4183 break;
4185 default:
4186 break;
4190 void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
4192 if (m_periodicTimer <= 0)
4193 m_periodicTimer += m_modifier.periodictime;
4195 m_isPeriodic = apply;
4198 void Aura::HandlePeriodicLeech(bool apply, bool Real)
4200 if (m_periodicTimer <= 0)
4201 m_periodicTimer += m_modifier.periodictime;
4203 m_isPeriodic = apply;
4206 void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
4208 if (m_periodicTimer <= 0)
4209 m_periodicTimer += m_modifier.periodictime;
4211 m_isPeriodic = apply;
4214 /*********************************************************/
4215 /*** MODIFY STATS ***/
4216 /*********************************************************/
4218 /********************************/
4219 /*** RESISTANCE ***/
4220 /********************************/
4222 void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
4224 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4226 if(m_modifier.m_miscvalue & int32(1<<x))
4228 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
4229 if(m_target->GetTypeId() == TYPEID_PLAYER)
4230 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4235 void Aura::HandleAuraModResistance(bool apply, bool Real)
4237 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4239 if(m_modifier.m_miscvalue & int32(1<<x))
4241 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4242 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4243 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4247 // Faerie Fire (druid versions)
4248 if( m_spellProto->SpellIconID == 109 &&
4249 m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
4250 m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
4252 m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
4256 void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
4258 // only players have base stats
4259 if(m_target->GetTypeId() != TYPEID_PLAYER)
4261 //pets only have base armor
4262 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4263 m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
4265 else
4267 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4269 if(m_modifier.m_miscvalue & int32(1<<x))
4270 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
4275 void Aura::HandleModResistancePercent(bool apply, bool Real)
4277 for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4279 if(m_modifier.m_miscvalue & int32(1<<i))
4281 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4282 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4284 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
4285 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
4291 void Aura::HandleModBaseResistance(bool apply, bool Real)
4293 // only players have base stats
4294 if(m_target->GetTypeId() != TYPEID_PLAYER)
4296 //only pets have base stats
4297 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4298 m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4300 else
4302 for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4303 if(m_modifier.m_miscvalue & (1<<i))
4304 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4308 /********************************/
4309 /*** STAT ***/
4310 /********************************/
4312 void Aura::HandleAuraModStat(bool apply, bool Real)
4314 if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
4316 sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
4317 return;
4320 for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4322 // -1 or -2 is all stats ( misc < -2 checked in function beginning )
4323 if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
4325 //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
4326 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4327 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4328 m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
4333 void Aura::HandleModPercentStat(bool apply, bool Real)
4335 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4337 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4338 return;
4341 // only players have base stats
4342 if (m_target->GetTypeId() != TYPEID_PLAYER)
4343 return;
4345 for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
4347 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4348 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
4352 void Aura::HandleModSpellDamagePercentFromStat(bool apply, bool Real)
4354 if(m_target->GetTypeId() != TYPEID_PLAYER)
4355 return;
4357 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4358 // This information for client side use only
4359 // Recalculate bonus
4360 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4363 void Aura::HandleModSpellHealingPercentFromStat(bool apply, bool Real)
4365 if(m_target->GetTypeId() != TYPEID_PLAYER)
4366 return;
4368 // Recalculate bonus
4369 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4372 void Aura::HandleAuraModDispelResist(bool apply, bool Real)
4374 if(!Real || !apply)
4375 return;
4377 if(GetId()==33206)
4378 m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
4381 void Aura::HandleModSpellDamagePercentFromAttackPower(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::HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real)
4394 if(m_target->GetTypeId() != TYPEID_PLAYER)
4395 return;
4397 // Recalculate bonus
4398 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4401 void Aura::HandleModHealingDone(bool apply, bool Real)
4403 if(m_target->GetTypeId() != TYPEID_PLAYER)
4404 return;
4405 // implemented in Unit::SpellHealingBonus
4406 // this information is for client side only
4407 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4410 void Aura::HandleModTotalPercentStat(bool apply, bool Real)
4412 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4414 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4415 return;
4418 //save current and max HP before applying aura
4419 uint32 curHPValue = m_target->GetHealth();
4420 uint32 maxHPValue = m_target->GetMaxHealth();
4422 for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4424 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4426 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4427 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4428 m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
4432 //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
4433 if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
4435 // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
4436 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
4437 m_target->SetHealth(newHPValue);
4441 void Aura::HandleAuraModResistenceOfStatPercent(bool apply, bool Real)
4443 if(m_target->GetTypeId() != TYPEID_PLAYER)
4444 return;
4446 if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
4448 // support required adding replace UpdateArmor by loop by UpdateResistence at intelect update
4449 // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
4450 sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistences!");
4451 return;
4454 // Recalculate Armor
4455 m_target->UpdateArmor();
4458 /********************************/
4459 /*** HEAL & ENERGIZE ***/
4460 /********************************/
4461 void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
4464 Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
4465 so this aura not fully working.
4467 if(apply)
4469 if(!m_target->isAlive())
4470 return;
4472 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4473 m_target->SetStandState(PLAYER_STATE_SIT);
4475 if(m_periodicTimer <= 0)
4477 m_periodicTimer += m_modifier.periodictime;
4479 if(m_target->GetHealth() < m_target->GetMaxHealth())
4481 // PeriodicTick can cast triggered spells with stats changes
4482 PeriodicTick();
4487 m_isPeriodic = apply;
4490 void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
4492 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4493 m_target->SetStandState(PLAYER_STATE_SIT);
4494 if(apply)
4496 if(m_modifier.periodictime == 0)
4497 m_modifier.periodictime = 1000;
4498 if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
4500 m_periodicTimer += m_modifier.periodictime;
4502 if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
4504 // PeriodicTick can cast triggered spells with stats changes
4505 PeriodicTick();
4510 m_isPeriodic = apply;
4513 void Aura::HandleModRegen(bool apply, bool Real) // eating
4515 if(apply)
4517 if(!m_target->isAlive())
4518 return;
4520 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4521 m_target->SetStandState(PLAYER_STATE_SIT);
4523 if(m_periodicTimer <= 0)
4525 m_periodicTimer += 5000;
4526 int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
4527 Unit *caster = GetCaster();
4528 if (caster)
4530 SpellEntry const *spellProto = GetSpellProto();
4531 if (spellProto)
4532 m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
4537 m_isPeriodic = apply;
4540 void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
4542 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4543 m_target->SetStandState(PLAYER_STATE_SIT);
4545 if(apply && m_periodicTimer <= 0)
4547 m_periodicTimer += 2000;
4549 Powers pt = m_target->getPowerType();
4550 if(int32(pt) != m_modifier.m_miscvalue)
4551 return;
4553 if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
4555 // eating anim
4556 m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
4558 else if( GetId() == 20577 )
4560 // cannibalize anim
4561 m_target->HandleEmoteCommand(398);
4564 // Warrior talent, gain 1 rage every 3 seconds while in combat
4565 if(pt == POWER_RAGE && m_target->isInCombat())
4567 m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
4568 m_periodicTimer += 1000;
4571 m_isPeriodic = apply;
4572 if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
4573 ((Player*)m_target)->UpdateManaRegen();
4576 void Aura::HandleModPowerRegenPCT(bool apply, bool Real)
4578 // spells required only Real aura add/remove
4579 if(!Real)
4580 return;
4582 if (m_target->GetTypeId() != TYPEID_PLAYER)
4583 return;
4585 // Update manaregen value
4586 if (m_modifier.m_miscvalue == POWER_MANA)
4587 ((Player*)m_target)->UpdateManaRegen();
4590 void Aura::HandleModManaRegen(bool apply, bool Real)
4592 // spells required only Real aura add/remove
4593 if(!Real)
4594 return;
4596 if (m_target->GetTypeId() != TYPEID_PLAYER)
4597 return;
4599 //Note: an increase in regen does NOT cause threat.
4600 ((Player*)m_target)->UpdateManaRegen();
4603 void Aura::HandleComprehendLanguage(bool apply, bool Real)
4605 if(apply)
4606 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4607 else
4608 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4611 void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
4613 // Special case with temporary increase max/current health
4614 switch(GetId())
4616 case 12976: // Warrior Last Stand triggered spell
4617 case 28726: // Nightmare Seed ( Nightmare Seed )
4618 case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
4619 case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
4621 if(Real)
4623 if(apply)
4625 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4626 m_target->ModifyHealth(m_modifier.m_amount);
4628 else
4630 if (int32(m_target->GetHealth()) > m_modifier.m_amount)
4631 m_target->ModifyHealth(-m_modifier.m_amount);
4632 else
4633 m_target->SetHealth(1);
4634 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4637 return;
4641 // generic case
4642 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4645 void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
4647 uint32 oldhealth = m_target->GetHealth();
4648 double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
4650 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4652 // refresh percentage
4653 if(oldhealth > 0)
4655 uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
4656 if(newhealth==0)
4657 newhealth = 1;
4659 m_target->SetHealth(newhealth);
4663 void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
4665 Powers powerType = m_target->getPowerType();
4666 if(int32(powerType) != m_modifier.m_miscvalue)
4667 return;
4669 m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4672 void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool Real)
4674 Powers powerType = m_target->getPowerType();
4675 if(int32(powerType) != m_modifier.m_miscvalue)
4676 return;
4678 m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_PCT, float(m_modifier.m_amount), apply);
4681 void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real)
4683 //m_target->ApplyMaxHealthPercentMod(m_modifier.m_amount,apply);
4684 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
4687 /********************************/
4688 /*** FIGHT ***/
4689 /********************************/
4691 void Aura::HandleAuraModParryPercent(bool apply, bool Real)
4693 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4694 return;
4696 ((Player*)m_target)->UpdateParryPercentage();
4699 void Aura::HandleAuraModDodgePercent(bool apply, bool Real)
4701 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4702 return;
4704 ((Player*)m_target)->UpdateDodgePercentage();
4705 //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
4708 void Aura::HandleAuraModBlockPercent(bool apply, bool Real)
4710 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4711 return;
4713 ((Player*)m_target)->UpdateBlockPercentage();
4714 //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
4717 void Aura::HandleAuraModRegenInterrupt(bool apply, bool Real)
4719 // spells required only Real aura add/remove
4720 if(!Real)
4721 return;
4723 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4724 return;
4726 ((Player*)m_target)->UpdateManaRegen();
4729 void Aura::HandleAuraModCritPercent(bool apply, bool Real)
4731 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4732 return;
4734 // apply item specific bonuses for already equipped weapon
4735 if(Real)
4737 for(int i = 0; i < MAX_ATTACK; ++i)
4738 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4739 ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
4742 // mods must be applied base at equipped weapon class and subclass comparison
4743 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4744 // m_modifier.m_miscvalue comparison with item generated damage types
4746 if (GetSpellProto()->EquippedItemClass == -1)
4748 ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4749 ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4750 ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4752 else
4754 // done in Player::_ApplyWeaponDependentAuraMods
4758 void Aura::HandleModHitChance(bool apply, bool Real)
4760 m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4761 m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4764 void Aura::HandleModSpellHitChance(bool apply, bool Real)
4766 m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
4769 void Aura::HandleModSpellCritChance(bool apply, bool Real)
4771 // spells required only Real aura add/remove
4772 if(!Real)
4773 return;
4775 if(m_target->GetTypeId() == TYPEID_PLAYER)
4777 ((Player*)m_target)->UpdateAllSpellCritChances();
4779 else
4781 m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
4785 void Aura::HandleModSpellCritChanceShool(bool apply, bool Real)
4787 // spells required only Real aura add/remove
4788 if(!Real)
4789 return;
4791 if(m_target->GetTypeId() != TYPEID_PLAYER)
4792 return;
4794 for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
4795 if (m_modifier.m_miscvalue & (1<<school))
4796 ((Player*)m_target)->UpdateSpellCritChance(school);
4799 /********************************/
4800 /*** ATTACK SPEED ***/
4801 /********************************/
4803 void Aura::HandleModCastingSpeed(bool apply, bool Real)
4805 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4808 void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
4810 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4811 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4812 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4815 void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
4817 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4818 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4819 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4820 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4823 void Aura::HandleModAttackSpeed(bool apply, bool Real)
4825 if(!m_target->isAlive() )
4826 return;
4828 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4831 void Aura::HandleHaste(bool apply, bool Real)
4833 m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
4834 m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
4835 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
4838 void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
4840 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4843 void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
4845 if(m_target->GetTypeId() != TYPEID_PLAYER)
4846 return;
4847 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
4850 /********************************/
4851 /*** ATTACK POWER ***/
4852 /********************************/
4854 void Aura::HandleAuraModAttackPower(bool apply, bool Real)
4856 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4859 void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
4861 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4862 return;
4864 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4867 void Aura::HandleAuraAttackPowerAttacker(bool apply, bool Real)
4869 // spells required only Real aura add/remove
4870 if(!Real)
4871 return;
4872 Unit *caster = GetCaster();
4874 if (!caster)
4875 return;
4877 // Hunter's Mark
4878 if (m_spellProto->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
4880 // Check Improved Hunter's Mark bonus on caster
4881 Unit::AuraList const& mOverrideClassScript = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4882 for(Unit::AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
4884 Modifier* mod = (*i)->GetModifier();
4885 // mproved Hunter's Mark script from 5236 to 5240
4886 if (mod->m_miscvalue >= 5236 && mod->m_miscvalue <= 5240)
4888 // Get amount of ranged bonus for this spell..
4889 int32 ranged_bonus = caster->CalculateSpellDamage(m_spellProto, 1, m_spellProto->EffectBasePoints[1], m_target);
4890 // Set melee attack power bonus % from ranged depends from Improved mask aura
4891 m_modifier.m_amount = mod->m_amount * ranged_bonus / 100;
4892 m_currentBasePoints = m_modifier.m_amount;
4893 break;
4896 return;
4900 void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
4902 //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
4903 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
4906 void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
4908 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4909 return;
4911 //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
4912 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
4915 void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
4917 // spells required only Real aura add/remove
4918 if(!Real)
4919 return;
4921 if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4922 return;
4924 if(m_modifier.m_miscvalue != STAT_INTELLECT)
4926 // support required adding UpdateAttackPowerAndDamage calls at stat update
4927 sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intelect stats!");
4928 return;
4931 // Recalculate bonus
4932 ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
4935 /********************************/
4936 /*** DAMAGE BONUS ***/
4937 /********************************/
4938 void Aura::HandleModDamageDone(bool apply, bool Real)
4940 // apply item specific bonuses for already equipped weapon
4941 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
4943 for(int i = 0; i < MAX_ATTACK; ++i)
4944 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4945 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
4948 // m_modifier.m_miscvalue is bitmask of spell schools
4949 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
4950 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
4951 // 127 - full bitmask any damages
4953 // mods must be applied base at equipped weapon class and subclass comparison
4954 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4955 // m_modifier.m_miscvalue comparison with item generated damage types
4957 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
4959 // apply generic physical damage bonuses including wand case
4960 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
4962 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4963 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4964 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4966 else
4968 // done in Player::_ApplyWeaponDependentAuraMods
4971 if(m_target->GetTypeId() == TYPEID_PLAYER)
4973 if(m_positive)
4974 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
4975 else
4976 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
4980 // Skip non magic case for speedup
4981 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
4982 return;
4984 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
4986 // wand magic case (skip generic to all item spell bonuses)
4987 // done in Player::_ApplyWeaponDependentAuraMods
4989 // Skip item specific requirements for not wand magic damage
4990 return;
4993 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4994 // This information for client side use only
4995 if(m_target->GetTypeId() == TYPEID_PLAYER)
4997 if(m_positive)
4999 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5001 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5002 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
5005 else
5007 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5009 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5010 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
5013 Pet* pet = m_target->GetPet();
5014 if(pet)
5015 pet->UpdateAttackPowerAndDamage();
5019 void Aura::HandleModDamagePercentDone(bool apply, bool Real)
5021 sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
5023 // apply item specific bonuses for already equipped weapon
5024 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5026 for(int i = 0; i < MAX_ATTACK; ++i)
5027 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5028 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5031 // m_modifier.m_miscvalue is bitmask of spell schools
5032 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5033 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
5034 // 127 - full bitmask any damages
5036 // mods must be applied base at equipped weapon class and subclass comparison
5037 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5038 // m_modifier.m_miscvalue comparison with item generated damage types
5040 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5042 // apply generic physical damage bonuses including wand case
5043 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5045 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5046 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5047 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5049 else
5051 // done in Player::_ApplyWeaponDependentAuraMods
5053 // For show in client
5054 if(m_target->GetTypeId() == TYPEID_PLAYER)
5055 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
5058 // Skip non magic case for speedup
5059 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5060 return;
5062 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5064 // wand magic case (skip generic to all item spell bonuses)
5065 // done in Player::_ApplyWeaponDependentAuraMods
5067 // Skip item specific requirements for not wand magic damage
5068 return;
5071 // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
5072 // Send info to client
5073 if(m_target->GetTypeId() == TYPEID_PLAYER)
5074 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
5075 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
5078 void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
5080 // spells required only Real aura add/remove
5081 if(!Real)
5082 return;
5084 sLog.outDebug("AURA MOD OFFHAND DAMAGE");
5086 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5089 /********************************/
5090 /*** POWER COST ***/
5091 /********************************/
5093 void Aura::HandleModPowerCostPCT(bool apply, bool Real)
5095 // spells required only Real aura add/remove
5096 if(!Real)
5097 return;
5099 float amount = m_modifier.m_amount/100.0f;
5100 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5101 if(m_modifier.m_miscvalue & (1<<i))
5102 m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
5105 void Aura::HandleModPowerCost(bool apply, bool Real)
5107 // spells required only Real aura add/remove
5108 if(!Real)
5109 return;
5111 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5112 if(m_modifier.m_miscvalue & (1<<i))
5113 m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
5116 /*********************************************************/
5117 /*** OTHERS ***/
5118 /*********************************************************/
5120 void Aura::HandleShapeshiftBoosts(bool apply)
5122 uint32 spellId = 0;
5123 uint32 spellId2 = 0;
5124 uint32 HotWSpellId = 0;
5126 switch(GetModifier()->m_miscvalue)
5128 case FORM_CAT:
5129 spellId = 3025;
5130 HotWSpellId = 24900;
5131 break;
5132 case FORM_TREE:
5133 spellId = 5420;
5134 break;
5135 case FORM_TRAVEL:
5136 spellId = 5419;
5137 break;
5138 case FORM_AQUA:
5139 spellId = 5421;
5140 break;
5141 case FORM_BEAR:
5142 spellId = 1178;
5143 spellId2 = 21178;
5144 HotWSpellId = 24899;
5145 break;
5146 case FORM_DIREBEAR:
5147 spellId = 9635;
5148 spellId2 = 21178;
5149 HotWSpellId = 24899;
5150 break;
5151 case FORM_BATTLESTANCE:
5152 spellId = 21156;
5153 break;
5154 case FORM_DEFENSIVESTANCE:
5155 spellId = 7376;
5156 break;
5157 case FORM_BERSERKERSTANCE:
5158 spellId = 7381;
5159 break;
5160 case FORM_MOONKIN:
5161 spellId = 24905;
5162 // aura from effect trigger spell
5163 spellId2 = 24907;
5164 break;
5165 case FORM_FLIGHT:
5166 spellId = 33948;
5167 break;
5168 case FORM_FLIGHT_EPIC:
5169 spellId = 40122;
5170 spellId2 = 40121;
5171 break;
5172 case FORM_SPIRITOFREDEMPTION:
5173 spellId = 27792;
5174 spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
5175 break;
5176 case FORM_GHOSTWOLF:
5177 case FORM_AMBIENT:
5178 case FORM_GHOUL:
5179 case FORM_SHADOW:
5180 case FORM_STEALTH:
5181 case FORM_CREATURECAT:
5182 case FORM_CREATUREBEAR:
5183 spellId = 0;
5184 break;
5187 uint32 form = GetModifier()->m_miscvalue-1;
5189 if(apply)
5191 if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
5192 if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
5194 if(m_target->GetTypeId() == TYPEID_PLAYER)
5196 const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
5197 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
5199 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
5200 if(itr->first==spellId || itr->first==spellId2) continue;
5201 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
5202 if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
5203 if (spellInfo->Stances & (1<<form))
5204 m_target->CastSpell(m_target, itr->first, true, NULL, this);
5206 //LotP
5207 if (((Player*)m_target)->HasSpell(17007))
5209 SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
5210 if (spellInfo && spellInfo->Stances & (1<<form))
5211 m_target->CastSpell(m_target, 24932, true, NULL, this);
5213 // HotW
5214 if (HotWSpellId)
5216 Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
5217 for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
5219 if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
5221 int32 HotWMod = (*i)->GetModifier()->m_amount;
5222 if(GetModifier()->m_miscvalue == FORM_CAT)
5223 HotWMod /= 2;
5225 m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
5226 break;
5232 else
5234 m_target->RemoveAurasDueToSpell(spellId);
5235 m_target->RemoveAurasDueToSpell(spellId2);
5237 Unit::AuraMap& tAuras = m_target->GetAuras();
5238 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
5240 if (itr->second->IsRemovedOnShapeLost())
5242 m_target->RemoveAurasDueToSpell(itr->second->GetId());
5243 itr = tAuras.begin();
5245 else
5247 ++itr;
5252 /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
5253 m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
5256 void Aura::HandleAuraEmpathy(bool apply, bool Real)
5258 if(m_target->GetTypeId() != TYPEID_UNIT)
5259 return;
5261 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
5262 if(ci && ci->type == CREATURE_TYPE_BEAST)
5263 m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
5266 void Aura::HandleAuraUntrackable(bool apply, bool Real)
5268 if(apply)
5269 m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5270 else
5271 m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5274 void Aura::HandleAuraModPacify(bool apply, bool Real)
5276 if(m_target->GetTypeId() != TYPEID_PLAYER)
5277 return;
5279 if(apply)
5280 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5281 else
5282 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5285 void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
5287 HandleAuraModPacify(apply,Real);
5288 HandleAuraModSilence(apply,Real);
5291 void Aura::HandleAuraGhost(bool apply, bool Real)
5293 if(m_target->GetTypeId() != TYPEID_PLAYER)
5294 return;
5296 if(apply)
5298 m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5300 else
5302 m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5306 void Aura::HandleAuraAllowFlight(bool apply, bool Real)
5308 // all applied/removed only at real aura add/remove
5309 if(!Real)
5310 return;
5312 // allow fly
5313 WorldPacket data;
5314 if(apply)
5315 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
5316 else
5317 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
5318 data.append(m_target->GetPackGUID());
5319 data << uint32(0); // unk
5320 m_target->SendMessageToSet(&data, true);
5323 void Aura::HandleModRating(bool apply, bool Real)
5325 // spells required only Real aura add/remove
5326 if(!Real)
5327 return;
5329 if(m_target->GetTypeId() != TYPEID_PLAYER)
5330 return;
5332 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5333 if (m_modifier.m_miscvalue & (1 << rating))
5334 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
5337 void Aura::HandleForceMoveForward(bool apply, bool Real)
5339 if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
5340 return;
5341 if(apply)
5342 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5343 else
5344 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5347 void Aura::HandleAuraModExpertise(bool apply, bool Real)
5349 if(m_target->GetTypeId() != TYPEID_PLAYER)
5350 return;
5352 ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
5353 ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
5356 void Aura::HandleModTargetResistance(bool apply, bool Real)
5358 // spells required only Real aura add/remove
5359 if(!Real)
5360 return;
5361 // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
5363 // show armor penetration
5364 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
5365 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
5367 // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
5368 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
5369 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
5372 //HandleNoImmediateEffect auras implementation to support new stat system
5373 void Aura::HandleAuraHealing(bool apply, bool Real)
5375 //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5378 void Aura::HandleAuraHealingPct(bool apply, bool Real)
5380 //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_PCT, float(m_modifier.m_amount), apply);
5383 void Aura::HandleShieldBlockValue(bool apply, bool Real)
5385 BaseModType modType = FLAT_MOD;
5386 if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
5387 modType = PCT_MOD;
5389 if(m_target->GetTypeId() == TYPEID_PLAYER)
5390 ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
5393 void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
5395 // spells required only Real aura add/remove
5396 if(!Real)
5397 return;
5399 if(m_target->GetTypeId() != TYPEID_PLAYER)
5400 return;
5402 Player *target = (Player*)m_target;
5404 // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
5405 // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
5406 if( !apply && m_duration==0 && target->GetComboTarget())
5407 if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
5408 target->AddComboPoints(unit, -m_modifier.m_amount);
5411 void Aura::HandleModUnattackable( bool Apply, bool Real )
5413 if(Real && Apply)
5414 m_target->CombatStop();
5416 m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
5419 void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
5421 // spells required only Real aura add/remove
5422 if(!Real)
5423 return;
5425 // prepare spirit state
5426 if(apply)
5428 if(m_target->GetTypeId()==TYPEID_PLAYER)
5430 // disable breath/etc timers
5431 ((Player*)m_target)->StopMirrorTimers();
5433 // set stand state (expected in this form)
5434 if(!m_target->IsStandState())
5435 m_target->SetStandState(PLAYER_STATE_NONE);
5438 m_target->SetHealth(1);
5440 // die at aura end
5441 else
5442 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
5445 void Aura::CleanupTriggeredSpells()
5447 uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
5448 if(!tSpellId)
5449 return;
5451 SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
5452 if(!tProto)
5453 return;
5455 if(GetSpellDuration(tProto) != -1)
5456 return;
5458 // needed for spell 43680, maybe others
5459 // TODO: is there a spell flag, which can solve this in a more sophisticated way?
5460 if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
5461 GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
5462 return;
5463 m_target->RemoveAurasDueToSpell(tSpellId);
5466 void Aura::HandleAuraPowerBurn(bool apply, bool Real)
5468 if (m_periodicTimer <= 0)
5469 m_periodicTimer += m_modifier.periodictime;
5471 m_isPeriodic = apply;
5474 void Aura::HandleSchoolAbsorb(bool apply, bool Real)
5476 if(!Real)
5477 return;
5479 // prevent double apply bonuses
5480 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
5482 if(Unit* caster = GetCaster())
5484 float DoneActualBenefit = 0.0f;
5485 switch(m_spellProto->SpellFamilyName)
5487 case SPELLFAMILY_PRIEST:
5488 if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
5490 //+30% from +healing bonus
5491 DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
5492 break;
5494 break;
5495 case SPELLFAMILY_MAGE:
5496 if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
5498 //frost ward, fire ward, ice barrier
5499 //+10% from +spd bonus
5500 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5501 break;
5503 break;
5504 case SPELLFAMILY_WARLOCK:
5505 if(m_spellProto->SpellFamilyFlags == 0x00)
5507 //shadow ward
5508 //+10% from +spd bonus
5509 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5510 break;
5512 break;
5513 default:
5514 break;
5517 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
5519 m_modifier.m_amount += (int32)DoneActualBenefit;
5524 void Aura::PeriodicTick()
5526 if(!m_target->isAlive())
5527 return;
5529 switch(m_modifier.m_auraname)
5531 case SPELL_AURA_PERIODIC_DAMAGE:
5532 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
5534 Unit *pCaster = GetCaster();
5535 if(!pCaster)
5536 return;
5538 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5539 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5540 return;
5542 // Check for immune (not use charges)
5543 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5544 return;
5546 // some auras remove at specific health level or more
5547 if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
5549 switch(GetId())
5551 case 43093: case 31956: case 38801:
5552 case 35321: case 38363: case 39215:
5553 if(m_target->GetHealth() == m_target->GetMaxHealth() )
5555 m_target->RemoveAurasDueToSpell(GetId());
5556 return;
5558 break;
5559 case 38772:
5561 uint32 percent =
5562 GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
5563 pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
5564 100;
5565 if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
5567 m_target->RemoveAurasDueToSpell(GetId());
5568 return;
5570 break;
5572 default:
5573 break;
5577 uint32 absorb=0;
5578 uint32 resist=0;
5579 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5581 // ignore non positive values (can be result apply spellmods to aura damage
5582 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5584 uint32 pdamage;
5586 if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
5588 pdamage = amount;
5590 // Calculate armor mitigation if it is a physical spell
5591 // But not for bleed mechanic spells
5592 if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
5593 GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
5595 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5596 cleanDamage.damage += pdamage - pdamageReductedArmor;
5597 pdamage = pdamageReductedArmor;
5600 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5602 // Curse of Agony damage-per-tick calculation
5603 if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
5605 // 1..4 ticks, 1/2 from normal tick damage
5606 if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
5607 pdamage = pdamage/2;
5608 // 9..12 ticks, 3/2 from normal tick damage
5609 else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
5610 pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
5611 // 5..8 ticks have normal tick damage
5614 else
5615 pdamage = uint32(m_target->GetMaxHealth()*amount/100);
5617 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5618 // Reduce dot damage from resilience for players
5619 if (m_target->GetTypeId()==TYPEID_PLAYER)
5620 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5622 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5624 sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5625 GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5627 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5628 data.append(m_target->GetPackGUID());
5629 data.appendPackGUID(GetCasterGUID());
5630 data << uint32(GetId());
5631 data << uint32(1);
5632 data << uint32(m_modifier.m_auraname);
5633 data << (uint32)pdamage;
5634 data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
5635 data << (uint32)absorb;
5636 data << (uint32)resist;
5637 m_target->SendMessageToSet(&data,true);
5639 Unit* target = m_target; // aura can be deleted in DealDamage
5640 SpellEntry const* spellProto = GetSpellProto();
5642 pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5644 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5646 pCaster->ProcDamageAndSpell(target, PROC_FLAG_HIT_SPELL, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), GetSpellSchoolMask(spellProto), spellProto);
5647 break;
5649 case SPELL_AURA_PERIODIC_LEECH:
5651 Unit *pCaster = GetCaster();
5652 if(!pCaster)
5653 return;
5655 if(!pCaster->isAlive())
5656 return;
5658 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5659 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5660 return;
5662 // Check for immune (not use charges)
5663 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5664 return;
5666 uint32 absorb=0;
5667 uint32 resist=0;
5668 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5670 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5672 //Calculate armor mitigation if it is a physical spell
5673 if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
5675 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5676 cleanDamage.damage += pdamage - pdamageReductedArmor;
5677 pdamage = pdamageReductedArmor;
5680 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5682 // talent Soul Siphon add bonus to Drain Life spells
5683 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
5685 // find talent max bonus percentage
5686 Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5687 for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
5689 if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
5691 if((*i)->GetEffIndex()!=1)
5693 sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
5694 break;
5697 // effect 1 m_amount
5698 int32 maxPercent = (*i)->GetModifier()->m_amount;
5699 // effect 0 m_amount
5700 int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
5702 // count affliction effects and calc additional damage in percentage
5703 int32 modPercent = 0;
5704 Unit::AuraMap const& victimAuras = m_target->GetAuras();
5705 for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
5707 Aura* aura = itr->second;
5708 if (aura->IsPositive())continue;
5709 SpellEntry const* m_spell = aura->GetSpellProto();
5710 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
5711 continue;
5713 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
5714 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
5716 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
5718 if(_spell_idx->second->skillId == SKILL_AFFLICTION)
5720 modPercent += stepPercent;
5721 if (modPercent >= maxPercent)
5723 modPercent = maxPercent;
5724 break;
5729 pdamage += (pdamage*modPercent/100);
5730 break;
5735 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5736 // Reduce dot damage from resilience for players
5737 if (m_target->GetTypeId()==TYPEID_PLAYER)
5738 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5740 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5742 if(m_target->GetHealth() < pdamage)
5743 pdamage = uint32(m_target->GetHealth());
5745 sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5746 GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5748 pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
5751 Unit* target = m_target; // aura can be deleted in DealDamage
5752 SpellEntry const* spellProto = GetSpellProto();
5753 float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
5755 uint32 new_damage = pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
5757 // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
5759 pCaster->ProcDamageAndSpell(target, PROC_FLAG_HIT_SPELL, PROC_FLAG_TAKE_DAMAGE, new_damage, GetSpellSchoolMask(spellProto), spellProto);
5760 if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
5762 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
5764 if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
5765 pCaster->m_currentSpells[i]->cancel();
5770 if(Player *modOwner = pCaster->GetSpellModOwner())
5771 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
5773 uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
5775 int32 gain = pCaster->ModifyHealth(heal);
5776 pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
5778 pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
5779 break;
5781 case SPELL_AURA_PERIODIC_HEAL:
5782 case SPELL_AURA_OBS_MOD_HEALTH:
5784 Unit *pCaster = GetCaster();
5785 if(!pCaster)
5786 return;
5788 // heal for caster damage (must be alive)
5789 if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive())
5790 return;
5792 // ignore non positive values (can be result apply spellmods to aura damage
5793 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5795 uint32 pdamage;
5797 if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
5798 pdamage = uint32(m_target->GetMaxHealth() * amount/100);
5799 else
5800 pdamage = amount;
5802 pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
5804 sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
5805 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5807 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5808 data.append(m_target->GetPackGUID());
5809 data.appendPackGUID(GetCasterGUID());
5810 data << uint32(GetId());
5811 data << uint32(1);
5812 data << uint32(m_modifier.m_auraname);
5813 data << (uint32)pdamage;
5814 m_target->SendMessageToSet(&data,true);
5816 int32 gain = m_target->ModifyHealth(pdamage);
5818 // add HoTs to amount healed in bgs
5819 if( pCaster->GetTypeId() == TYPEID_PLAYER )
5820 if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
5821 bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
5823 //Do check before because m_modifier.auraName can be invalidate by DealDamage.
5824 bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
5826 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5828 Unit* target = m_target; // aura can be deleted in DealDamage
5829 SpellEntry const* spellProto = GetSpellProto();
5830 bool haveCastItem = GetCastItemGUID()!=0;
5832 // heal for caster damage
5833 if(m_target!=pCaster && spellProto->SpellVisual==163)
5835 uint32 dmg = spellProto->manaPerSecond;
5836 if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
5838 pCaster->RemoveAurasDueToSpell(GetId());
5840 // finish current generic/channeling spells, don't affect autorepeat
5841 if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
5843 pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
5845 if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
5847 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
5848 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
5851 else
5853 pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
5855 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5856 pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5860 // ignore item heals
5861 if(procSpell && !haveCastItem)
5862 pCaster->ProcDamageAndSpell(target,PROC_FLAG_HEAL, PROC_FLAG_HEALED, pdamage, SPELL_SCHOOL_MASK_NONE, spellProto);
5863 break;
5865 case SPELL_AURA_PERIODIC_MANA_LEECH:
5867 Unit *pCaster = GetCaster();
5868 if(!pCaster)
5869 return;
5871 if(!pCaster->isAlive())
5872 return;
5874 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5875 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5876 return;
5878 // Check for immune (not use charges)
5879 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5880 return;
5882 // ignore non positive values (can be result apply spellmods to aura damage
5883 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5885 sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
5886 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5888 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5889 break;
5891 Powers power = Powers(m_modifier.m_miscvalue);
5893 // power type might have changed between aura applying and tick (druid's shapeshift)
5894 if(m_target->getPowerType() != power)
5895 break;
5897 int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
5899 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
5900 if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
5901 drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
5903 m_target->ModifyPower(power, -drain_amount);
5905 float gain_multiplier = 0;
5907 if(pCaster->GetMaxPower(power) > 0)
5909 gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
5911 if(Player *modOwner = pCaster->GetSpellModOwner())
5912 modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
5915 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5916 data.append(m_target->GetPackGUID());
5917 data.appendPackGUID(GetCasterGUID());
5918 data << uint32(GetId());
5919 data << uint32(1);
5920 data << uint32(m_modifier.m_auraname);
5921 data << (uint32)power; // power type
5922 data << (uint32)drain_amount;
5923 data << (float)gain_multiplier;
5924 m_target->SendMessageToSet(&data,true);
5926 int32 gain_amount = int32(drain_amount*gain_multiplier);
5928 if(gain_amount)
5930 int32 gain = pCaster->ModifyPower(power,gain_amount);
5931 m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
5933 break;
5935 case SPELL_AURA_PERIODIC_ENERGIZE:
5937 // ignore non positive values (can be result apply spellmods to aura damage
5938 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5940 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
5941 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5943 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
5944 break;
5946 Powers power = Powers(m_modifier.m_miscvalue);
5948 if(m_target->GetMaxPower(power) == 0)
5949 break;
5951 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5952 data.append(m_target->GetPackGUID());
5953 data.appendPackGUID(GetCasterGUID());
5954 data << uint32(GetId());
5955 data << uint32(1);
5956 data << uint32(m_modifier.m_auraname);
5957 data << (uint32)power; // power type
5958 data << (uint32)pdamage;
5959 m_target->SendMessageToSet(&data,true);
5961 int32 gain = m_target->ModifyPower(power,pdamage);
5963 if(Unit* pCaster = GetCaster())
5964 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5965 break;
5967 case SPELL_AURA_OBS_MOD_MANA:
5969 // ignore non positive values (can be result apply spellmods to aura damage
5970 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5972 uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
5974 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
5975 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5977 if(m_target->GetMaxPower(POWER_MANA) == 0)
5978 break;
5980 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5981 data.append(m_target->GetPackGUID());
5982 data.appendPackGUID(GetCasterGUID());
5983 data << uint32(GetId());
5984 data << uint32(1);
5985 data << uint32(m_modifier.m_auraname);
5986 data << (uint32)0; // ?
5987 data << (uint32)pdamage;
5988 m_target->SendMessageToSet(&data,true);
5990 int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
5992 if(Unit* pCaster = GetCaster())
5993 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5994 break;
5996 case SPELL_AURA_POWER_BURN_MANA:
5998 Unit *pCaster = GetCaster();
5999 if(!pCaster)
6000 return;
6002 // Check for immune (not use charges)
6003 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
6004 return;
6006 int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6008 Powers powerType = Powers(m_modifier.m_miscvalue);
6010 if(!m_target->isAlive() || m_target->getPowerType() != powerType)
6011 return;
6013 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
6014 if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
6015 pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
6017 uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
6019 gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
6021 //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
6022 pCaster->SpellNonMeleeDamageLog(m_target, GetId(), gain);
6023 break;
6025 // Here tick dummy auras
6026 case SPELL_AURA_PERIODIC_DUMMY:
6028 PeriodicDummyTick();
6029 break;
6031 default:
6032 break;
6036 void Aura::PeriodicDummyTick()
6038 SpellEntry const* spell = GetSpellProto();
6039 switch (spell->Id)
6041 // Drink
6042 case 430:
6043 case 431:
6044 case 432:
6045 case 1133:
6046 case 1135:
6047 case 1137:
6048 case 10250:
6049 case 22734:
6050 case 27089:
6051 case 34291:
6052 case 43706:
6053 case 46755:
6055 if (m_target->GetTypeId() != TYPEID_PLAYER)
6056 return;
6057 // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
6058 Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
6059 for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
6061 if ((*i)->GetId() == GetId())
6063 // Get tick number
6064 int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
6065 // Default case (not on arenas)
6066 if (tick == 0)
6068 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6069 ((Player*)m_target)->UpdateManaRegen();
6070 // Disable continue
6071 m_isPeriodic = false;
6073 return;
6074 //**********************************************
6075 // Code commended since arena patch not added
6076 // This feature uses only in arenas
6077 //**********************************************
6078 // Here need increase mana regen per tick (6 second rule)
6079 // on 0 tick - 0 (handled in 2 second)
6080 // on 1 tick - 166% (handled in 4 second)
6081 // on 2 tick - 133% (handled in 6 second)
6082 // Not need update after 3 tick
6084 if (tick > 3)
6085 return;
6086 // Apply bonus for 0 - 3 tick
6087 switch (tick)
6089 case 0: // 0%
6090 (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
6091 break;
6092 case 1: // 166%
6093 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
6094 break;
6095 case 2: // 133%
6096 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
6097 break;
6098 default: // 100% - normal regen
6099 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6100 break;
6102 ((Player*)m_target)->UpdateManaRegen();
6103 return;*/
6106 return;
6108 // // Panda
6109 // case 19230: break;
6110 // // Master of Subtlety
6111 // case 31666: break;
6112 // // Gossip NPC Periodic - Talk
6113 // case 33208: break;
6114 // // Gossip NPC Periodic - Despawn
6115 // case 33209: break;
6116 // // Force of Nature
6117 // case 33831: break;
6118 // Aspect of the Viper
6119 case 34074:
6121 if (m_target->GetTypeId() != TYPEID_PLAYER)
6122 return;
6123 // Should be manauser
6124 if (m_target->getPowerType()!=POWER_MANA)
6125 return;
6126 Unit *caster = GetCaster();
6127 if (!caster)
6128 return;
6129 // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
6130 int mana = m_target->GetPower(POWER_MANA);
6131 int max_mana = m_target->GetMaxPower(POWER_MANA);
6132 int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
6133 float regen_pct = 1.20f - 1.1f * mana / max_mana;
6134 if (regen_pct > 1.0f) regen_pct = 1.0f;
6135 else if (regen_pct < 0.2f) regen_pct = 0.2f;
6136 m_modifier.m_amount = int32 (base_regen * regen_pct);
6137 ((Player*)m_target)->UpdateManaRegen();
6138 return;
6140 // // Steal Weapon
6141 // case 36207: break;
6142 // // Simon Game START timer, (DND)
6143 // case 39993: break;
6144 // // Harpooner's Mark
6145 // case 40084: break;
6146 // // Knockdown Fel Cannon: break; The Aggro Burst
6147 // case 40119: break;
6148 // // Old Mount Spell
6149 // case 40154: break;
6150 // // Magnetic Pull
6151 // case 40581: break;
6152 // // Ethereal Ring: break; The Bolt Burst
6153 // case 40801: break;
6154 // // Crystal Prison
6155 // case 40846: break;
6156 // // Copy Weapon
6157 // case 41054: break;
6158 // // Ethereal Ring Visual, Lightning Aura
6159 // case 41477: break;
6160 // // Ethereal Ring Visual, Lightning Aura (Fork)
6161 // case 41525: break;
6162 // // Ethereal Ring Visual, Lightning Jumper Aura
6163 // case 41567: break;
6164 // // No Man's Land
6165 // case 41955: break;
6166 // // Headless Horseman - Fire
6167 // case 42074: break;
6168 // // Headless Horseman - Visual - Large Fire
6169 // case 42075: break;
6170 // // Headless Horseman - Start Fire, Periodic Aura
6171 // case 42140: break;
6172 // // Ram Speed Boost
6173 // case 42152: break;
6174 // // Headless Horseman - Fires Out Victory Aura
6175 // case 42235: break;
6176 // // Pumpkin Life Cycle
6177 // case 42280: break;
6178 // // Brewfest Request Chick Chuck Mug Aura
6179 // case 42537: break;
6180 // // Squashling
6181 // case 42596: break;
6182 // // Headless Horseman Climax, Head: Periodic
6183 // case 42603: break;
6184 // // Fire Bomb
6185 // case 42621: break;
6186 // // Headless Horseman - Conflagrate, Periodic Aura
6187 // case 42637: break;
6188 // // Headless Horseman - Create Pumpkin Treats Aura
6189 // case 42774: break;
6190 // // Headless Horseman Climax - Summoning Rhyme Aura
6191 // case 42879: break;
6192 // // Tricky Treat
6193 // case 42919: break;
6194 // // Giddyup!
6195 // case 42924: break;
6196 // // Ram - Trot
6197 // case 42992: break;
6198 // // Ram - Canter
6199 // case 42993: break;
6200 // // Ram - Gallop
6201 // case 42994: break;
6202 // // Ram Level - Neutral
6203 // case 43310: break;
6204 // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
6205 // case 43884: break;
6206 // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
6207 // case 44000: break;
6208 // // Energy Feedback
6209 // case 44328: break;
6210 // // Romantic Picnic
6211 // case 45102: break;
6212 // // Romantic Picnic
6213 // case 45123: break;
6214 // // Looking for Love
6215 // case 45124: break;
6216 // // Kite - Lightning Strike Kite Aura
6217 // case 45197: break;
6218 // // Rocket Chicken
6219 // case 45202: break;
6220 // // Copy Offhand Weapon
6221 // case 45205: break;
6222 // // Upper Deck - Kite - Lightning Periodic Aura
6223 // case 45207: break;
6224 // // Kite -Sky Lightning Strike Kite Aura
6225 // case 45251: break;
6226 // // Ribbon Pole Dancer Check Aura
6227 // case 45390: break;
6228 // // Holiday - Midsummer, Ribbon Pole Periodic Visual
6229 // case 45406: break;
6230 // // Parachute
6231 // case 45472: break;
6232 // // Alliance Flag, Extra Damage Debuff
6233 // case 45898: break;
6234 // // Horde Flag, Extra Damage Debuff
6235 // case 45899: break;
6236 // // Ahune - Summoning Rhyme Aura
6237 // case 45926: break;
6238 // // Ahune - Slippery Floor
6239 // case 45945: break;
6240 // // Ahune's Shield
6241 // case 45954: break;
6242 // // Nether Vapor Lightning
6243 // case 45960: break;
6244 // // Darkness
6245 // case 45996: break;
6246 // // Summon Blood Elves Periodic
6247 // case 46041: break;
6248 // // Transform Visual Missile Periodic
6249 // case 46205: break;
6250 // // Find Opening Beam End
6251 // case 46333: break;
6252 // // Ice Spear Control Aura
6253 // case 46371: break;
6254 // // Hailstone Chill
6255 // case 46458: break;
6256 // // Hailstone Chill, Internal
6257 // case 46465: break;
6258 // // Chill, Internal Shifter
6259 // case 46549: break;
6260 // // Summon Ice Spear Knockback Delayer
6261 // case 46878: break;
6262 // // Burninate Effect
6263 // case 47214: break;
6264 // // Fizzcrank Practice Parachute
6265 // case 47228: break;
6266 // // Send Mug Control Aura
6267 // case 47369: break;
6268 // // Direbrew's Disarm (precast)
6269 // case 47407: break;
6270 // // Mole Machine Port Schedule
6271 // case 47489: break;
6272 // // Mole Machine Portal Schedule
6273 // case 49466: break;
6274 // // Drink Coffee
6275 // case 49472: break;
6276 // // Listening to Music
6277 // case 50493: break;
6278 // // Love Rocket Barrage
6279 // case 50530: break;
6280 default:
6281 break;
6285 void Aura::HandlePreventFleeing(bool apply, bool Real)
6287 if(!Real)
6288 return;
6290 Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
6291 if( !fearAuras.empty() )
6293 if (apply)
6294 m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
6295 else
6296 m_target->SetFeared(true);
6300 void Aura::HandleManaShield(bool apply, bool Real)
6302 if(!Real)
6303 return;
6305 // prevent double apply bonuses
6306 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
6308 if(Unit* caster = GetCaster())
6310 float DoneActualBenefit = 0.0f;
6311 switch(m_spellProto->SpellFamilyName)
6313 case SPELLFAMILY_MAGE:
6314 if(m_spellProto->SpellFamilyFlags & 0x8000)
6316 // Mana Shield
6317 // +50% from +spd bonus
6318 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
6319 break;
6321 break;
6322 default:
6323 break;
6326 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
6328 m_modifier.m_amount += (int32)DoneActualBenefit;
6333 void Aura::HandleArenaPreparation(bool apply, bool Real)
6335 if(!Real)
6336 return;
6338 if(apply)
6339 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6340 else
6341 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);