[7146] Trailing whitespace code cleanup
[getmangos.git] / src / game / SpellAuras.cpp
blob5ae889278bc9310d0f3416ea0258031ea1db908b
1 /*
2 * Copyright (C) 2005-2009 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::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER
163 &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT
164 &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER
165 &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
166 &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
167 &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
168 &Aura::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim
169 &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
170 &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
171 &Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus
172 &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless
173 &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
174 &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
175 &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
176 &Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE
177 &Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER
178 &Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
179 &Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
180 &Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
181 &Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET
182 &Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS
183 &Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
184 &Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
185 &Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT
186 &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
187 &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
188 &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE
189 &Aura::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus
190 &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
191 &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE
192 &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
193 &Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
194 &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
195 &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
196 &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
197 &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
198 &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
199 &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
200 &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
201 &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
202 &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK
203 &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
204 &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
205 &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
206 &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
207 &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL
208 &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
209 &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
210 &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
211 &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
212 &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
213 &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
214 &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
215 &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA
216 &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE
217 &Aura::HandleUnused, //164 useless, only one test spell
218 &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
219 &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
220 &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
221 &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
222 &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
223 &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell
224 &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
225 &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
226 &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
227 &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus
228 &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
229 &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
230 &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM
231 &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
232 &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
233 &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
234 &Aura::HandleUnused, //181 SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS unused
235 &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
236 &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT
237 &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
238 &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
239 &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult
240 &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
241 &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
242 &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING
243 &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
244 &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
245 &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
246 &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
247 &Aura::HandleUnused, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL
248 &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL implement in Unit::CalculateSpellDamage
249 &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
250 &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
251 &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
252 &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
253 &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP
254 &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
255 &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
256 &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
257 &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
258 &Aura::HandleNULL, //205 vulnerable to school dmg?
259 &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED
260 &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
261 &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive)
262 &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS
263 &Aura::HandleNULL, //210 Commentator's Command
264 &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
265 &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
266 &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
267 &Aura::HandleNULL, //214 Tamed Pet Passive
268 &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
269 &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
270 &Aura::HandleUnused, //217 unused
271 &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
272 &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
273 &Aura::HandleModRatingFromStat, //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::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE
281 &Aura::HandleNoImmediateEffect, //228 stealth detection
282 &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
283 &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
284 &Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
285 &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
286 &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
287 &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
288 &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
289 &Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE
290 &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus
291 &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
292 &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
293 &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE
294 &Aura::HandleForceMoveForward, //241 Forces the player to move forward
295 &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING
296 &Aura::HandleUnused, //243 used by two test spells
297 &Aura::HandleComprehendLanguage, //244 Comprehend language
298 &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS
299 &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL
300 &Aura::HandleUnused, //247 unused
301 &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
302 &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
303 &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
304 &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE
305 &Aura::HandleNULL, //252 haste all?
306 &Aura::HandleNULL, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE
307 &Aura::HandleNULL, //254 SPELL_AURA_MOD_DISARM_SHIELD disarm Shield
308 &Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus
309 &Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
310 &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
311 &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
312 &Aura::HandleNULL, //259 corrupt healing over time spell
313 &Aura::HandleNULL, //260
314 &Aura::HandleNULL, //261 out of phase?
315 &Aura::HandleNULL, //262
316 &Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilites set in SpellClassMask
317 &Aura::HandleNULL, //264 unused
318 &Aura::HandleNULL, //265 unused
319 &Aura::HandleNULL, //266 unused
320 &Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect
321 &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
322 &Aura::HandleNULL, //269 ignore DR effects?
323 &Aura::HandleNULL, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST
324 &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
325 &Aura::HandleNULL, //272 reduce spell cast time?
326 &Aura::HandleNULL, //273
327 &Aura::HandleNULL, //274 proc free shot?
328 &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
329 &Aura::HandleNULL, //276 mod damage % mechanic?
330 &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Use SpellClassMask for spell select
331 &Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
332 &Aura::HandleNULL, //279
333 &Aura::HandleNULL, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
334 &Aura::HandleNULL, //281 SPELL_AURA_MOD_HONOR_GAIN
335 &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
336 &Aura::HandleNULL //283 SPD/heal from AP?
339 Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
340 m_spellmod(NULL), m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target),
341 m_timeCla(1000), m_periodicTimer(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
342 m_effIndex(eff), m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),
343 m_positive(false), m_permanent(false), m_isPeriodic(false), m_isAreaAura(false), m_isPersistent(false),
344 m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
346 assert(target);
348 assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
350 m_spellProto = spellproto;
352 m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff];
354 m_isPassive = IsPassiveSpell(GetId());
355 m_positive = IsPositiveEffect(GetId(), m_effIndex);
357 m_applyTime = time(NULL);
359 int32 damage;
360 if(!caster)
362 m_caster_guid = target->GetGUID();
363 damage = m_currentBasePoints+1; // stored value-1
364 m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target);
366 else
368 m_caster_guid = caster->GetGUID();
370 damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target);
371 m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target);
373 if (!damage && castItem && castItem->GetItemSuffixFactor())
375 ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
376 if(item_rand_suffix)
378 for (int k=0; k<3; k++)
380 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
381 if(pEnchant)
383 for (int t=0; t<3; t++)
384 if(pEnchant->spellid[t] == m_spellProto->Id)
386 damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 );
387 break;
391 if(damage)
392 break;
398 if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0)
399 m_permanent = true;
401 Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
403 if(!m_permanent && modOwner)
404 modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration);
406 m_duration = m_maxduration;
408 if(modOwner)
409 modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
411 sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage);
413 m_effIndex = eff;
414 SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
416 m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
418 m_procCharges = m_spellProto->procCharges;
419 if(modOwner)
420 modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
422 m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances &&
423 !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000));
426 Aura::~Aura()
430 AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
431 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
433 m_isAreaAura = true;
435 // caster==NULL in constructor args if target==caster in fact
436 Unit* caster_ptr = caster ? caster : target;
438 m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex]));
439 if(Player* modOwner = caster_ptr->GetSpellModOwner())
440 modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius);
442 switch(spellproto->Effect[eff])
444 case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
445 m_areaAuraType = AREA_AURA_PARTY;
446 if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
447 m_modifier.m_auraname = SPELL_AURA_NONE;
448 break;
449 case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
450 m_areaAuraType = AREA_AURA_RAID;
451 if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
452 m_modifier.m_auraname = SPELL_AURA_NONE;
453 break;
454 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
455 m_areaAuraType = AREA_AURA_FRIEND;
456 break;
457 case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
458 m_areaAuraType = AREA_AURA_ENEMY;
459 if(target == caster_ptr)
460 m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self
461 break;
462 case SPELL_EFFECT_APPLY_AREA_AURA_PET:
463 m_areaAuraType = AREA_AURA_PET;
464 break;
465 case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
466 m_areaAuraType = AREA_AURA_OWNER;
467 if(target == caster_ptr)
468 m_modifier.m_auraname = SPELL_AURA_NONE;
469 break;
470 default:
471 sLog.outError("Wrong spell effect in AreaAura constructor");
472 ASSERT(false);
473 break;
477 AreaAura::~AreaAura()
481 PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
482 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
484 m_isPersistent = true;
487 PersistentAreaAura::~PersistentAreaAura()
491 SingleEnemyTargetAura::SingleEnemyTargetAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
492 Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
494 if (caster)
495 m_casters_target_guid = caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)caster)->GetSelection() : caster->GetUInt64Value(UNIT_FIELD_TARGET);
496 else
497 m_casters_target_guid = 0;
500 SingleEnemyTargetAura::~SingleEnemyTargetAura()
504 Unit* SingleEnemyTargetAura::GetTriggerTarget() const
506 return ObjectAccessor::GetUnit(*m_target, m_casters_target_guid);
509 Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem)
511 if (IsAreaAuraEffect(spellproto->Effect[eff]))
512 return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem);
514 uint32 triggeredSpellId = spellproto->EffectTriggerSpell[eff];
516 if(SpellEntry const* triggeredSpellInfo = sSpellStore.LookupEntry(triggeredSpellId))
517 for (int i = 0; i < 3; ++i)
518 if (triggeredSpellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_ENEMY)
519 return new SingleEnemyTargetAura(spellproto, eff, currentBasePoints, target, caster, castItem);
521 return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem);
524 Unit* Aura::GetCaster() const
526 if(m_caster_guid==m_target->GetGUID())
527 return m_target;
529 //return ObjectAccessor::GetUnit(*m_target,m_caster_guid);
530 //must return caster even if it's in another grid/map
531 Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL);
532 return unit && unit->IsInWorld() ? unit : NULL;
535 void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
537 m_modifier.m_auraname = t;
538 m_modifier.m_amount = a;
539 m_modifier.m_miscvalue = miscValue;
540 m_modifier.periodictime = pt;
543 void Aura::Update(uint32 diff)
545 if (m_duration > 0)
547 m_duration -= diff;
548 if (m_duration < 0)
549 m_duration = 0;
550 m_timeCla -= diff;
552 // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras
553 // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0
554 if(GetEffIndex()==0 && m_timeCla <= 0)
556 if(Unit* caster = GetCaster())
558 Powers powertype = Powers(m_spellProto->powerType);
559 int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel();
560 m_timeCla = 1000;
561 if (manaPerSecond)
563 if(powertype==POWER_HEALTH)
564 caster->ModifyHealth(-manaPerSecond);
565 else
566 caster->ModifyPower(powertype,-manaPerSecond);
572 // Channeled aura required check distance from caster
573 if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID())
575 Unit* caster = GetCaster();
576 if(!caster)
578 m_target->RemoveAura(GetId(),GetEffIndex());
579 return;
582 // Get spell range
583 float radius;
584 SpellModOp mod;
585 if (m_spellProto->EffectRadiusIndex[GetEffIndex()])
587 radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()]));
588 mod = SPELLMOD_RADIUS;
590 else
592 radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
593 mod = SPELLMOD_RANGE;
596 if(Player* modOwner = caster->GetSpellModOwner())
597 modOwner->ApplySpellMod(GetId(), mod, radius,NULL);
599 if(!caster->IsWithinDistInMap(m_target,radius))
601 m_target->RemoveAura(GetId(),GetEffIndex());
602 return;
606 if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
608 m_periodicTimer -= diff;
609 if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
611 if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN ||
612 m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN ||
613 // Cannibalize, eating items and other spells
614 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH ||
615 // Eating items and other spells
616 m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA )
618 ApplyModifier(true);
619 return;
621 // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
622 m_periodicTimer += m_modifier.periodictime;
623 PeriodicTick();
628 void AreaAura::Update(uint32 diff)
630 // update for the caster of the aura
631 if(m_caster_guid == m_target->GetGUID())
633 Unit* caster = m_target;
635 if( !caster->hasUnitState(UNIT_STAT_ISOLATED) )
637 Unit* owner = caster->GetCharmerOrOwner();
638 if (!owner)
639 owner = caster;
640 std::list<Unit *> targets;
642 switch(m_areaAuraType)
644 case AREA_AURA_PARTY:
646 Group *pGroup = NULL;
648 if (owner->GetTypeId() == TYPEID_PLAYER)
649 pGroup = ((Player*)owner)->GetGroup();
651 if( pGroup)
653 uint8 subgroup = ((Player*)owner)->GetSubGroup();
654 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
656 Player* Target = itr->getSource();
657 if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target))
659 if(caster->IsWithinDistInMap(Target, m_radius))
660 targets.push_back(Target);
661 Pet *pet = Target->GetPet();
662 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
663 targets.push_back(pet);
667 else
669 // add owner
670 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
671 targets.push_back(owner);
672 // add caster's pet
673 Unit* pet = caster->GetPet();
674 if( pet && caster->IsWithinDistInMap(pet, m_radius))
675 targets.push_back(pet);
677 break;
679 case AREA_AURA_RAID:
681 Group *pGroup = NULL;
683 if (owner->GetTypeId() == TYPEID_PLAYER)
684 pGroup = ((Player*)owner)->GetGroup();
686 if( pGroup)
688 uint8 subgroup = ((Player*)owner)->GetSubGroup();
689 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
691 Player* Target = itr->getSource();
692 if(Target && Target->isAlive() && caster->IsFriendlyTo(Target))
694 if(caster->IsWithinDistInMap(Target, m_radius))
695 targets.push_back(Target);
696 Pet *pet = Target->GetPet();
697 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
698 targets.push_back(pet);
702 else
704 // add owner
705 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
706 targets.push_back(owner);
707 // add caster's pet
708 Unit* pet = caster->GetPet();
709 if( pet && caster->IsWithinDistInMap(pet, m_radius))
710 targets.push_back(pet);
712 break;
714 case AREA_AURA_FRIEND:
716 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
717 Cell cell(p);
718 cell.data.Part.reserved = ALL_DISTRICT;
719 cell.SetNoCreate();
721 MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius);
722 MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
723 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
724 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
725 CellLock<GridReadGuard> cell_lock(cell, p);
726 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
727 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
728 break;
730 case AREA_AURA_ENEMY:
732 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
733 Cell cell(p);
734 cell.data.Part.reserved = ALL_DISTRICT;
735 cell.SetNoCreate();
737 MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
738 MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);
739 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
740 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
741 CellLock<GridReadGuard> cell_lock(cell, p);
742 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
743 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
744 break;
746 case AREA_AURA_OWNER:
747 case AREA_AURA_PET:
749 if(owner != caster)
750 targets.push_back(owner);
751 break;
755 for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
757 if((*tIter)->HasAura(GetId(), m_effIndex))
758 continue;
760 if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
762 int32 actualBasePoints = m_currentBasePoints;
763 // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
764 if(actualSpellInfo != GetSpellProto())
765 actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
766 AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL);
767 aur->SetAuraDuration(GetAuraDuration());
768 (*tIter)->AddAura(aur);
772 Aura::Update(diff);
774 else // aura at non-caster
776 Unit * tmp_target = m_target;
777 Unit* caster = GetCaster();
778 uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
780 // WARNING: the aura may get deleted during the update
781 // DO NOT access its members after update!
782 Aura::Update(diff);
784 // remove aura if out-of-range from caster (after teleport for example)
785 // or caster is isolated or caster no longer has the aura
786 // or caster is (no longer) friendly
787 bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
788 if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
789 !caster->IsWithinDistInMap(tmp_target, m_radius) ||
790 !caster->HasAura(tmp_spellId, tmp_effIndex) ||
791 caster->IsFriendlyTo(tmp_target) != needFriendly
794 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
796 else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
798 // not check group if target == owner or target == pet
799 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
801 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
803 Group *pGroup = check ? check->GetGroup() : NULL;
804 if( pGroup )
806 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
807 if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
808 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
810 else
811 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
814 else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
816 // not check group if target == owner or target == pet
817 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
819 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
821 Group *pGroup = check ? check->GetGroup() : NULL;
822 if( pGroup )
824 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
825 if(!checkTarget)
826 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
828 else
829 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
832 else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
834 if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
835 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
840 void PersistentAreaAura::Update(uint32 diff)
842 bool remove = false;
844 // remove the aura if its caster or the dynamic object causing it was removed
845 // or if the target moves too far from the dynamic object
846 Unit *caster = GetCaster();
847 if (caster)
849 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
850 if (dynObj)
852 if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius()))
853 remove = true;
855 else
856 remove = true;
858 else
859 remove = true;
861 Unit *tmp_target = m_target;
862 uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
864 // WARNING: the aura may get deleted during the update
865 // DO NOT access its members after update!
866 Aura::Update(diff);
868 if(remove)
869 tmp_target->RemoveAura(tmp_id, tmp_index);
872 void Aura::ApplyModifier(bool apply, bool Real)
874 AuraType aura = m_modifier.m_auraname;
876 m_in_use = true;
877 if(aura<TOTAL_AURAS)
878 (*this.*AuraHandler [aura])(apply,Real);
879 m_in_use = false;
882 void Aura::_AddAura()
884 if (!GetId())
885 return;
886 if(!m_target)
887 return;
889 // Second aura if some spell
890 bool secondaura = false;
891 // Try find slot for aura
892 uint8 slot = NULL_AURA_SLOT;
893 // Lookup for some spell auras (and get slot from it)
894 for(uint8 i = 0; i < m_effIndex; i++)
896 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
897 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
899 // allow use single slot only by auras from same caster
900 if(itr->second->GetCasterGUID()==GetCasterGUID())
902 slot = itr->second->GetAuraSlot();
903 secondaura = true;
904 break;
907 if (secondaura)
908 break;
910 // Lookup free slot
911 if (!secondaura && m_target->GetVisibleAurasCount() < MAX_AURAS)
913 Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras();
914 for(uint8 i = 0; i < MAX_AURAS; ++i)
916 Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i);
917 if(itr == visibleAuras->end())
919 slot = i;
920 // update for out of range group members (on 1 slot use)
921 m_target->UpdateAuraForGroup(slot);
922 break;
926 // not call total regen auras at adding
927 switch (m_modifier.m_auraname)
929 case SPELL_AURA_OBS_MOD_HEALTH:
930 case SPELL_AURA_OBS_MOD_MANA:
931 m_periodicTimer = m_modifier.periodictime;
932 break;
933 case SPELL_AURA_MOD_REGEN:
934 case SPELL_AURA_MOD_POWER_REGEN:
935 case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
936 m_periodicTimer = 5000;
937 break;
940 Unit* caster = GetCaster();
942 // passive auras (except totem auras) do not get placed in the slots
943 // area auras with SPELL_AURA_NONE are not shown on target
944 if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
945 (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
947 SetAuraSlot( slot );
948 if(slot < MAX_AURAS) // slot found send data to client
950 SetAura(false);
951 SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE));
952 SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
953 SendAuraUpdate(false);
956 //*****************************************************
957 // Update target aura state flag (at 1 aura apply)
958 // TODO: Make it easer
959 //*****************************************************
960 if (!secondaura)
962 // register aura diminishing on apply
963 if (getDiminishGroup() != DIMINISHING_NONE )
964 m_target->ApplyDiminishingAura(getDiminishGroup(),true);
966 // Update Seals information
967 if (IsSealSpell(m_spellProto))
968 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
970 // Conflagrate aura state on Immolate
971 if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags & 4)
972 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
974 // Faerie Fire (druid versions)
975 if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
976 m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true);
978 // Victorious
979 if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
980 m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true);
982 // Swiftmend state on Regrowth & Rejuvenation
983 if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 )
984 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
986 // Deadly poison aura state
987 if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000)
988 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true);
993 void Aura::_RemoveAura()
995 // Remove all triggered by aura spells vs unlimited duration
996 // except same aura replace case
997 if(m_removeMode!=AURA_REMOVE_BY_STACK)
998 CleanupTriggeredSpells();
1000 Unit* caster = GetCaster();
1002 if(caster && IsPersistent())
1004 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
1005 if (dynObj)
1006 dynObj->RemoveAffected(m_target);
1009 //passive auras do not get put in slots
1010 // Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
1011 //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
1012 // return;
1014 uint8 slot = GetAuraSlot();
1016 if(slot >= MAX_AURAS) // slot not set
1017 return;
1019 if(m_target->GetVisibleAura(slot) == 0)
1020 return;
1022 bool lastaura = true;
1024 // find other aura in same slot (current already removed from list)
1025 for(uint8 i = 0; i < 3; i++)
1027 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
1028 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
1030 if(itr->second->GetAuraSlot()==slot)
1032 lastaura = false;
1033 break;
1036 if(!lastaura)
1037 break;
1040 // only remove icon when the last aura of the spell is removed (current aura already removed from list)
1041 if (lastaura)
1043 // unregister aura diminishing (and store last time)
1044 if (getDiminishGroup() != DIMINISHING_NONE )
1045 m_target->ApplyDiminishingAura(getDiminishGroup(),false);
1047 SetAura(true);
1048 SetAuraFlags(AFLAG_NONE);
1049 SetAuraLevel(0);
1050 SendAuraUpdate(true);
1052 // update for out of range group members
1053 m_target->UpdateAuraForGroup(slot);
1055 //*****************************************************
1056 // Update target aura state flag (at last aura remove)
1057 //*****************************************************
1058 uint32 removeState = 0;
1059 switch(m_spellProto->SpellFamilyName)
1061 case SPELLFAMILY_PALADIN:
1062 if (IsSealSpell(m_spellProto))
1063 removeState = AURA_STATE_JUDGEMENT; // Update Seals information
1064 break;
1065 case SPELLFAMILY_WARLOCK:
1066 if(m_spellProto->SpellFamilyFlags & 4)
1067 removeState = AURA_STATE_IMMOLATE; // Conflagrate aura state
1068 break;
1069 case SPELLFAMILY_DRUID:
1070 if(m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
1071 removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
1072 else if(m_spellProto->SpellFamilyFlags & 0x50)
1073 removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
1074 break;
1075 case SPELLFAMILY_WARRIOR:
1076 if(m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
1077 removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
1078 break;
1079 case SPELLFAMILY_ROGUE:
1080 if(m_spellProto->SpellFamilyFlags & 0x10000)
1081 removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
1082 break;
1083 case SPELLFAMILY_HUNTER:
1084 if(m_spellProto->SpellFamilyFlags & 0x1000000000000000LL)
1085 removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
1088 // Remove state (but need check other auras for it)
1089 if (removeState)
1091 bool found = false;
1092 Unit::AuraMap& Auras = m_target->GetAuras();
1093 for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
1095 SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
1096 if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
1097 auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags )
1099 found = true;
1100 break;
1103 // this has been last aura
1104 if(!found)
1105 m_target->ModifyAuraState(AuraState(removeState), false);
1108 // reset cooldown state for spells
1109 if(caster && caster->GetTypeId() == TYPEID_PLAYER)
1111 if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
1112 ((Player*)caster)->SendCooldownEvent(GetSpellProto());
1117 void Aura::SendAuraUpdate(bool remove)
1119 WorldPacket data(SMSG_AURA_UPDATE);
1120 data.append(m_target->GetPackGUID());
1121 data << uint8(GetAuraSlot());
1122 data << uint32(remove ? 0 : GetId());
1124 if(remove)
1126 m_target->SendMessageToSet(&data, true);
1127 return;
1130 uint8 auraFlags = GetAuraFlags();
1131 data << uint8(auraFlags);
1132 data << uint8(GetAuraLevel());
1133 data << uint8(m_procCharges ? m_procCharges : m_stackAmount);
1135 if(!(auraFlags & AFLAG_NOT_CASTER))
1137 data << uint8(0); // pguid
1140 if(auraFlags & AFLAG_DURATION)
1142 data << uint32(GetAuraMaxDuration());
1143 data << uint32(GetAuraDuration());
1146 m_target->SendMessageToSet(&data, true);
1149 void Aura::SetStackAmount(uint8 stackAmount)
1151 if (stackAmount != m_stackAmount)
1153 Unit *target = GetTarget();
1154 Unit *caster = GetCaster();
1155 if (!target || !caster)
1156 return;
1157 m_stackAmount = stackAmount;
1158 int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target);
1159 // Reapply if amount change
1160 if (amount!=m_modifier.m_amount)
1162 ApplyModifier(false, true);
1163 m_modifier.m_amount = amount;
1164 ApplyModifier(true, true);
1167 RefreshAura();
1170 bool Aura::modStackAmount(int32 num)
1172 // Can`t mod
1173 if (!m_spellProto->StackAmount)
1174 return true;
1176 // Modify stack but limit it
1177 int32 stackAmount = m_stackAmount + num;
1178 if (stackAmount > m_spellProto->StackAmount)
1179 stackAmount = m_spellProto->StackAmount;
1180 else if (stackAmount <=0) // Last aura from stack removed
1182 m_stackAmount = 0;
1183 return true; // need remove aura
1186 // Update stack amount
1187 SetStackAmount(stackAmount);
1188 return false;
1191 void Aura::RefreshAura()
1193 m_duration = m_maxduration;
1194 SendAuraUpdate(false);
1197 bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
1199 // Check family name
1200 if (spell->SpellFamilyName != m_spellProto->SpellFamilyName)
1201 return false;
1202 // Check EffectClassMask
1203 uint32 const *ptr = getAuraSpellClassMask();
1204 if (((uint64*)ptr)[0] & spell->SpellFamilyFlags)
1205 return true;
1206 if (ptr[2] & spell->SpellFamilyFlags2)
1207 return true;
1208 return false;
1211 /*********************************************************/
1212 /*** BASIC AURA FUNCTION ***/
1213 /*********************************************************/
1214 void Aura::HandleAddModifier(bool apply, bool Real)
1216 if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
1217 return;
1219 if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
1220 return;
1222 if (apply)
1224 // Add custom charges for some mod aura
1225 switch (m_spellProto->Id)
1227 case 17941: // Shadow Trance
1228 case 22008: // Netherwind Focus
1229 case 31834: // Light's Grace
1230 case 34754: // Clearcasting
1231 case 34936: // Backlash
1232 case 48108: // Hot Streak
1233 case 57761: // Fireball!
1234 SetAuraCharges(1);
1235 break;
1238 SpellModifier *mod = new SpellModifier;
1239 mod->op = SpellModOp(m_modifier.m_miscvalue);
1240 mod->value = m_modifier.m_amount;
1241 mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
1242 mod->spellId = GetId();
1244 uint32 const *ptr;
1245 SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
1246 if (spellAffect)
1247 ptr = &spellAffect->SpellClassMask[0];
1248 else
1250 switch (m_effIndex)
1252 case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break;
1253 case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break;
1254 case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break;
1255 default:
1256 return;
1260 mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
1261 mod->mask2= (uint64)ptr[2];
1262 mod->charges = m_procCharges;
1264 m_spellmod = mod;
1267 uint64 spellFamilyMask = m_spellmod->mask;
1269 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
1271 // reapply some passive spells after add/remove related spellmods
1272 if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
1274 m_target->RemoveAurasDueToSpell(45471);
1276 if(apply)
1277 m_target->CastSpell(m_target,45471,true);
1280 void Aura::HandleAddTargetTrigger(bool apply, bool Real)
1282 // Use SpellModifier structure for check
1283 // used only fields:
1284 // spellId, mask, mask2
1285 if (apply)
1287 SpellModifier *mod = new SpellModifier;
1288 mod->spellId = GetId();
1290 uint32 const *ptr;
1291 SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
1292 if (spellAffect)
1293 ptr = &spellAffect->SpellClassMask[0];
1294 else
1296 switch (m_effIndex)
1298 case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break;
1299 case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break;
1300 case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break;
1301 default:
1302 return;
1306 mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
1307 mod->mask2= (uint64)ptr[2];
1308 m_spellmod = mod;
1310 else
1312 delete m_spellmod;
1313 m_spellmod = NULL;
1317 void Aura::TriggerSpell()
1319 Unit* caster = GetCaster();
1320 Unit* target = GetTriggerTarget();
1322 if(!caster || !target)
1323 return;
1325 // generic casting code with custom spells and target/caster customs
1326 uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
1328 SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1329 SpellEntry const *auraSpellInfo = GetSpellProto();
1330 uint32 auraId = auraSpellInfo->Id;
1332 // specific code for cases with no trigger spell provided in field
1333 if (triggeredSpellInfo == NULL)
1335 switch(auraSpellInfo->SpellFamilyName)
1337 case SPELLFAMILY_GENERIC:
1339 switch(auraId)
1341 // Firestone Passive (1-5 ranks)
1342 case 758:
1343 case 17945:
1344 case 17947:
1345 case 17949:
1346 case 27252:
1348 if (caster->GetTypeId()!=TYPEID_PLAYER)
1349 return;
1350 Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
1351 if (!item)
1352 return;
1353 uint32 enchant_id = 0;
1354 switch (GetId())
1356 case 758: enchant_id = 1803; break; // Rank 1
1357 case 17945: enchant_id = 1823; break; // Rank 2
1358 case 17947: enchant_id = 1824; break; // Rank 3
1359 case 17949: enchant_id = 1825; break; // Rank 4
1360 case 27252: enchant_id = 2645; break; // Rank 5
1361 default:
1362 return;
1364 // remove old enchanting before applying new
1365 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1366 item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
1367 // add new enchanting
1368 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
1369 return;
1371 // // Periodic Mana Burn
1372 // case 812: break;
1373 // // Polymorphic Ray
1374 // case 6965: break;
1375 // // Fire Nova (1-7 ranks)
1376 // case 8350:
1377 // case 8508:
1378 // case 8509:
1379 // case 11312:
1380 // case 11313:
1381 // case 25540:
1382 // case 25544:
1383 // break;
1384 // Thaumaturgy Channel
1385 case 9712: trigger_spell_id = 21029; break;
1386 // // Egan's Blaster
1387 // case 17368: break;
1388 // // Haunted
1389 // case 18347: break;
1390 // // Ranshalla Waiting
1391 // case 18953: break;
1392 // // Inferno
1393 // case 19695: break;
1394 // // Frostwolf Muzzle DND
1395 // case 21794: break;
1396 // // Alterac Ram Collar DND
1397 // case 21866: break;
1398 // // Celebras Waiting
1399 // case 21916: break;
1400 // Brood Affliction: Bronze
1401 case 23170:
1403 m_target->CastSpell(m_target, 23171, true, 0, this);
1404 return;
1406 // // Mark of Frost
1407 // case 23184: break;
1408 // Restoration
1409 case 23493:
1411 int32 heal = caster->GetMaxHealth() / 10;
1412 caster->ModifyHealth( heal );
1413 caster->SendHealSpellLog(caster, 23493, heal);
1415 int32 mana = caster->GetMaxPower(POWER_MANA);
1416 if (mana)
1418 mana /= 10;
1419 caster->ModifyPower( POWER_MANA, mana );
1420 caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
1422 break;
1424 // // Stoneclaw Totem Passive TEST
1425 // case 23792: break;
1426 // // Axe Flurry
1427 // case 24018: break;
1428 // // Mark of Arlokk
1429 // case 24210: break;
1430 // // Restoration
1431 // case 24379: break;
1432 // // Happy Pet
1433 // case 24716: break;
1434 // // Dream Fog
1435 // case 24780: break;
1436 // // Cannon Prep
1437 // case 24832: break;
1438 // // Shadow Bolt Whirl
1439 // case 24834: break;
1440 // // Stink Trap
1441 // case 24918: break;
1442 // // Mark of Nature
1443 // case 25041: break;
1444 // // Agro Drones
1445 // case 25152: break;
1446 // // Consume
1447 // case 25371: break;
1448 // // Pain Spike
1449 // case 25572: break;
1450 // // Rotate 360
1451 // case 26009: break;
1452 // // Rotate -360
1453 // case 26136: break;
1454 // // Consume
1455 // case 26196: break;
1456 // // Berserk
1457 // case 26615: break;
1458 // // Defile
1459 // case 27177: break;
1460 // // Teleport: IF/UC
1461 // case 27601: break;
1462 // // Five Fat Finger Exploding Heart Technique
1463 // case 27673: break;
1464 // // Nitrous Boost
1465 // case 27746: break;
1466 // // Steam Tank Passive
1467 // case 27747: break;
1468 // // Frost Blast
1469 // case 27808: break;
1470 // // Detonate Mana
1471 // case 27819: break;
1472 // // Controller Timer
1473 // case 28095: break;
1474 // // Stalagg Chain
1475 // case 28096: break;
1476 // // Stalagg Tesla Passive
1477 // case 28097: break;
1478 // // Feugen Tesla Passive
1479 // case 28109: break;
1480 // // Feugen Chain
1481 // case 28111: break;
1482 // // Mark of Didier
1483 // case 28114: break;
1484 // // Communique Timer, camp
1485 // case 28346: break;
1486 // // Icebolt
1487 // case 28522: break;
1488 // // Silithyst
1489 // case 29519: break;
1490 // // Inoculate Nestlewood Owlkin
1491 case 29528: trigger_spell_id = 28713; break;
1492 // // Overload
1493 // case 29768: break;
1494 // // Return Fire
1495 // case 29788: break;
1496 // // Return Fire
1497 // case 29793: break;
1498 // // Return Fire
1499 // case 29794: break;
1500 // // Guardian of Icecrown Passive
1501 // case 29897: break;
1502 // Feed Captured Animal
1503 case 29917: trigger_spell_id = 29916; break;
1504 // // Flame Wreath
1505 // case 29946: break;
1506 // // Flame Wreath
1507 // case 29947: break;
1508 // // Mind Exhaustion Passive
1509 // case 30025: break;
1510 // // Nether Beam - Serenity
1511 // case 30401: break;
1512 // Extract Gas
1513 case 30427:
1515 // move loot to player inventory and despawn target
1516 if(caster->GetTypeId() ==TYPEID_PLAYER &&
1517 target->GetTypeId() == TYPEID_UNIT &&
1518 ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
1520 Player* player = (Player*)caster;
1521 Creature* creature = (Creature*)target;
1522 // missing lootid has been reported on startup - just return
1523 if (!creature->GetCreatureInfo()->SkinLootId)
1525 return;
1527 Loot *loot = &creature->loot;
1528 loot->clear();
1529 loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL);
1530 for(uint8 i=0;i<loot->items.size();i++)
1532 LootItem *item = loot->LootItemInSlot(i,player);
1533 ItemPosCountVec dest;
1534 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count );
1535 if ( msg == EQUIP_ERR_OK )
1537 Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId);
1539 player->SendNewItem(newitem, uint32(item->count), false, false, true);
1541 else
1542 player->SendEquipError( msg, NULL, NULL );
1544 creature->setDeathState(JUST_DIED);
1545 creature->RemoveCorpse();
1546 creature->SetHealth(0); // just for nice GM-mode view
1548 return;
1549 break;
1551 // Quake
1552 case 30576: trigger_spell_id = 30571; break;
1553 // // Burning Maul
1554 // case 30598: break;
1555 // // Regeneration
1556 // case 30799:
1557 // case 30800:
1558 // case 30801:
1559 // break;
1560 // // Despawn Self - Smoke cloud
1561 // case 31269: break;
1562 // // Time Rift Periodic
1563 // case 31320: break;
1564 // // Corrupt Medivh
1565 // case 31326: break;
1566 // Doom
1567 case 31347:
1569 m_target->CastSpell(m_target,31350,true);
1570 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
1571 return;
1573 // Spellcloth
1574 case 31373:
1576 // Summon Elemental after create item
1577 caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
1578 return;
1580 // // Bloodmyst Tesla
1581 // case 31611: break;
1582 // // Doomfire
1583 // case 31944: break;
1584 // // Teleport Test
1585 // case 32236: break;
1586 // // Earthquake
1587 // case 32686: break;
1588 // // Possess
1589 // case 33401: break;
1590 // // Draw Shadows
1591 // case 33563: break;
1592 // // Murmur's Touch
1593 // case 33711: break;
1594 // Flame Quills
1595 case 34229:
1597 // cast 24 spells 34269-34289, 34314-34316
1598 for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
1599 caster->CastSpell(m_target,spell_id,true);
1600 for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
1601 caster->CastSpell(m_target,spell_id,true);
1602 return;
1604 // // Gravity Lapse
1605 // case 34480: break;
1606 // // Tornado
1607 // case 34683: break;
1608 // // Frostbite Rotate
1609 // case 34748: break;
1610 // // Arcane Flurry
1611 // case 34821: break;
1612 // // Interrupt Shutdown
1613 // case 35016: break;
1614 // // Interrupt Shutdown
1615 // case 35176: break;
1616 // // Inferno
1617 // case 35268: break;
1618 // // Salaadin's Tesla
1619 // case 35515: break;
1620 // // Ethereal Channel (Red)
1621 // case 35518: break;
1622 // // Nether Vapor
1623 // case 35879: break;
1624 // // Dark Portal Storm
1625 // case 36018: break;
1626 // // Burning Maul
1627 // case 36056: break;
1628 // // Living Grove Defender Lifespan
1629 // case 36061: break;
1630 // // Professor Dabiri Talks
1631 // case 36064: break;
1632 // // Kael Gaining Power
1633 // case 36091: break;
1634 // // They Must Burn Bomb Aura
1635 // case 36344: break;
1636 // // They Must Burn Bomb Aura (self)
1637 // case 36350: break;
1638 // // Stolen Ravenous Ravager Egg
1639 // case 36401: break;
1640 // // Activated Cannon
1641 // case 36410: break;
1642 // // Stolen Ravenous Ravager Egg
1643 // case 36418: break;
1644 // // Enchanted Weapons
1645 // case 36510: break;
1646 // // Cursed Scarab Periodic
1647 // case 36556: break;
1648 // // Cursed Scarab Despawn Periodic
1649 // case 36561: break;
1650 // // Vision Guide
1651 // case 36573: break;
1652 // // Cannon Charging (platform)
1653 // case 36785: break;
1654 // // Cannon Charging (self)
1655 // case 36860: break;
1656 // Remote Toy
1657 case 37027: trigger_spell_id = 37029; break;
1658 // // Mark of Death
1659 // case 37125: break;
1660 // // Arcane Flurry
1661 // case 37268: break;
1662 // // Spout
1663 // case 37429: break;
1664 // // Spout
1665 // case 37430: break;
1666 // // Karazhan - Chess NPC AI, Snapshot timer
1667 // case 37440: break;
1668 // // Karazhan - Chess NPC AI, action timer
1669 // case 37504: break;
1670 // // Karazhan - Chess: Is Square OCCUPIED aura (DND)
1671 // case 39400: break;
1672 // // Banish
1673 // case 37546: break;
1674 // // Shriveling Gaze
1675 // case 37589: break;
1676 // // Fake Aggro Radius (2 yd)
1677 // case 37815: break;
1678 // // Corrupt Medivh
1679 // case 37853: break;
1680 // Eye of Grillok
1681 case 38495:
1683 m_target->CastSpell(m_target, 38530, true);
1684 return;
1686 // Absorb Eye of Grillok (Zezzak's Shard)
1687 case 38554:
1689 if(m_target->GetTypeId() != TYPEID_UNIT)
1690 return;
1692 caster->CastSpell(caster, 38495, true);
1694 Creature* creatureTarget = (Creature*)m_target;
1696 creatureTarget->setDeathState(JUST_DIED);
1697 creatureTarget->RemoveCorpse();
1698 creatureTarget->SetHealth(0); // just for nice GM-mode view
1699 return;
1701 // // Magic Sucker Device timer
1702 // case 38672: break;
1703 // // Tomb Guarding Charging
1704 // case 38751: break;
1705 // // Murmur's Touch
1706 // case 38794: break;
1707 // // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item)
1708 // case 39105: break;
1709 // // Drain World Tree Visual
1710 // case 39140: break;
1711 // // Quest - Dustin's Undead Dragon Visual aura
1712 // case 39259: break;
1713 // // Hellfire - The Exorcism, Jules releases darkness, aura
1714 // case 39306: break;
1715 // // Inferno
1716 // case 39346: break;
1717 // // Enchanted Weapons
1718 // case 39489: break;
1719 // // Shadow Bolt Whirl
1720 // case 39630: break;
1721 // // Shadow Bolt Whirl
1722 // case 39634: break;
1723 // // Shadow Inferno
1724 // case 39645: break;
1725 // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
1726 case 39857: trigger_spell_id = 39856; break;
1727 // // Soulgrinder Ritual Visual (Smashed)
1728 // case 39974: break;
1729 // // Simon Game Pre-game timer
1730 // case 40041: break;
1731 // // Knockdown Fel Cannon: The Aggro Check Aura
1732 // case 40113: break;
1733 // // Spirit Lance
1734 // case 40157: break;
1735 // // Demon Transform 2
1736 // case 40398: break;
1737 // // Demon Transform 1
1738 // case 40511: break;
1739 // // Ancient Flames
1740 // case 40657: break;
1741 // // Ethereal Ring Cannon: Cannon Aura
1742 // case 40734: break;
1743 // // Cage Trap
1744 // case 40760: break;
1745 // // Random Periodic
1746 // case 40867: break;
1747 // // Prismatic Shield
1748 // case 40879: break;
1749 // // Aura of Desire
1750 // case 41350: break;
1751 // // Dementia
1752 // case 41404: break;
1753 // // Chaos Form
1754 // case 41629: break;
1755 // // Alert Drums
1756 // case 42177: break;
1757 // // Spout
1758 // case 42581: break;
1759 // // Spout
1760 // case 42582: break;
1761 // // Return to the Spirit Realm
1762 // case 44035: break;
1763 // // Curse of Boundless Agony
1764 // case 45050: break;
1765 // // Earthquake
1766 // case 46240: break;
1767 // Personalized Weather
1768 case 46736: trigger_spell_id = 46737; break;
1769 // // Stay Submerged
1770 // case 46981: break;
1771 // // Dragonblight Ram
1772 // case 47015: break;
1773 // // Party G.R.E.N.A.D.E.
1774 // case 51510: break;
1775 default:
1776 break;
1778 break;
1780 case SPELLFAMILY_MAGE:
1782 switch(auraId)
1784 // Invisibility
1785 case 66:
1787 if(!m_duration)
1788 m_target->CastSpell(m_target, 32612, true, NULL, this);
1789 return;
1791 default:
1792 break;
1794 break;
1796 // case SPELLFAMILY_WARRIOR:
1797 // {
1798 // switch(auraId)
1799 // {
1800 // // Wild Magic
1801 // case 23410: break;
1802 // // Corrupted Totems
1803 // case 23425: break;
1804 // default:
1805 // break;
1806 // }
1807 // break;
1808 // }
1809 // case SPELLFAMILY_PRIEST:
1810 // {
1811 // switch(auraId)
1812 // {
1813 // // Blue Beam
1814 // case 32930: break;
1815 // // Fury of the Dreghood Elders
1816 // case 35460: break;
1817 // default:
1818 // break;
1819 // }
1820 // break;
1821 // }
1822 case SPELLFAMILY_DRUID:
1824 switch(auraId)
1826 // Cat Form
1827 // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while
1828 case 768:
1829 return;
1830 // Frenzied Regeneration
1831 case 22842:
1832 case 22895:
1833 case 22896:
1834 case 26999:
1836 int32 LifePerRage = GetModifier()->m_amount;
1838 int32 lRage = m_target->GetPower(POWER_RAGE);
1839 if(lRage > 100) // rage stored as rage*10
1840 lRage = 100;
1841 m_target->ModifyPower(POWER_RAGE, -lRage);
1842 int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10);
1843 m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this);
1844 return;
1846 default:
1847 break;
1849 break;
1852 // case SPELLFAMILY_HUNTER:
1853 // {
1854 // switch(auraId)
1855 // {
1856 // //Frost Trap Aura
1857 // case 13810:
1858 // return;
1859 // //Rizzle's Frost Trap
1860 // case 39900:
1861 // return;
1862 // // Tame spells
1863 // case 19597: // Tame Ice Claw Bear
1864 // case 19676: // Tame Snow Leopard
1865 // case 19677: // Tame Large Crag Boar
1866 // case 19678: // Tame Adult Plainstrider
1867 // case 19679: // Tame Prairie Stalker
1868 // case 19680: // Tame Swoop
1869 // case 19681: // Tame Dire Mottled Boar
1870 // case 19682: // Tame Surf Crawler
1871 // case 19683: // Tame Armored Scorpid
1872 // case 19684: // Tame Webwood Lurker
1873 // case 19685: // Tame Nightsaber Stalker
1874 // case 19686: // Tame Strigid Screecher
1875 // case 30100: // Tame Crazed Dragonhawk
1876 // case 30103: // Tame Elder Springpaw
1877 // case 30104: // Tame Mistbat
1878 // case 30647: // Tame Barbed Crawler
1879 // case 30648: // Tame Greater Timberstrider
1880 // case 30652: // Tame Nightstalker
1881 // return;
1882 // default:
1883 // break;
1884 // }
1885 // break;
1886 // }
1887 case SPELLFAMILY_SHAMAN:
1889 switch(auraId)
1891 // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
1892 case 28820:
1894 // Need remove self if Lightning Shield not active
1895 Unit::AuraMap const& auras = target->GetAuras();
1896 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1898 SpellEntry const* spell = itr->second->GetSpellProto();
1899 if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
1900 spell->SpellFamilyFlags & 0x0000000000000400L)
1901 return;
1903 target->RemoveAurasDueToSpell(28820);
1904 return;
1906 // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
1907 case 38443:
1909 bool all = true;
1910 for(int i = 0; i < MAX_TOTEM; ++i)
1912 if(!caster->m_TotemSlot[i])
1914 all = false;
1915 break;
1919 if(all)
1920 caster->CastSpell(caster,38437,true);
1921 else
1922 caster->RemoveAurasDueToSpell(38437);
1923 return;
1925 default:
1926 break;
1928 break;
1930 default:
1931 break;
1933 // Reget trigger spell proto
1934 triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1935 if(triggeredSpellInfo == NULL)
1937 sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
1938 return;
1941 else
1943 // Spell exist but require custom code
1944 switch(auraId)
1946 // Curse of Idiocy
1947 case 1010:
1949 // TODO: spell casted by result in correct way mostly
1950 // BUT:
1951 // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell
1952 // but must show affect apply like item casting
1953 // 2) maybe aura must be replace by new with accumulative stat mods instead stacking
1955 // prevent cast by triggered auras
1956 if(m_caster_guid == m_target->GetGUID())
1957 return;
1959 // stop triggering after each affected stats lost > 90
1960 int32 intelectLoss = 0;
1961 int32 spiritLoss = 0;
1963 Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT);
1964 for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
1966 if ((*i)->GetId() == 1010)
1968 switch((*i)->GetModifier()->m_miscvalue)
1970 case STAT_INTELLECT: intelectLoss += (*i)->GetModifier()->m_amount; break;
1971 case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
1972 default: break;
1977 if(intelectLoss <= -90 && spiritLoss <= -90)
1978 return;
1980 caster = target;
1981 break;
1983 // Mana Tide
1984 case 16191:
1986 caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this);
1987 return;
1991 // All ok cast by default case
1992 caster->CastSpell(target, triggeredSpellInfo, true, 0, this);
1995 void Aura::TriggerSpellWithValue()
1997 Unit* caster = GetCaster();
1998 Unit* target = GetTriggerTarget();
2000 if(!caster || !target)
2001 return;
2003 // generic casting code with custom spells and target/caster customs
2004 uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
2005 int32 basepoints0 = this->GetModifier()->m_amount;
2007 caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, 0, 0, true, 0, this);
2010 /*********************************************************/
2011 /*** AURA EFFECTS ***/
2012 /*********************************************************/
2014 void Aura::HandleAuraDummy(bool apply, bool Real)
2016 // spells required only Real aura add/remove
2017 if(!Real)
2018 return;
2020 Unit* caster = GetCaster();
2022 // AT APPLY
2023 if(apply)
2025 switch(GetId())
2027 case 1515: // Tame beast
2028 // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
2029 if( caster && m_target->CanHaveThreatList())
2030 m_target->AddThreat(caster, 10.0f);
2031 return;
2032 case 13139: // net-o-matic
2033 // root to self part of (root_target->charge->root_self sequence
2034 if(caster)
2035 caster->CastSpell(caster,13138,true,NULL,this);
2036 return;
2037 case 39850: // Rocket Blast
2038 if(roll_chance_i(20)) // backfire stun
2039 m_target->CastSpell(m_target, 51581, true, NULL, this);
2040 return;
2041 case 43873: // Headless Horseman Laugh
2042 if(caster->GetTypeId() == TYPEID_PLAYER)
2043 ((Player*)caster)->PlaySound(11965, false);
2044 return;
2045 case 46354: // Blood Elf Illusion
2046 if(caster)
2048 switch(caster->getGender())
2050 case GENDER_FEMALE:
2051 caster->CastSpell(m_target,46356,true,NULL,this);
2052 break;
2053 case GENDER_MALE:
2054 caster->CastSpell(m_target,46355,true,NULL,this);
2055 break;
2056 default:
2057 break;
2060 return;
2061 case 46699: // Requires No Ammo
2062 if(m_target->GetTypeId()==TYPEID_PLAYER)
2063 ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
2064 return;
2067 // Earth Shield
2068 if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
2070 // prevent double apply bonuses
2071 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2072 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2073 return;
2076 // AT REMOVE
2077 else
2079 if( m_target->GetTypeId() == TYPEID_PLAYER &&
2080 ( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
2081 ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
2083 // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
2084 ((Player*)m_target)->SetFarSightGUID(0);
2085 WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
2086 ((Player*)m_target)->GetSession()->SendPacket(&data);
2087 return;
2090 if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive())
2092 uint32 finalSpelId = 0;
2093 switch(GetId())
2095 case 19548: finalSpelId = 19597; break;
2096 case 19674: finalSpelId = 19677; break;
2097 case 19687: finalSpelId = 19676; break;
2098 case 19688: finalSpelId = 19678; break;
2099 case 19689: finalSpelId = 19679; break;
2100 case 19692: finalSpelId = 19680; break;
2101 case 19693: finalSpelId = 19684; break;
2102 case 19694: finalSpelId = 19681; break;
2103 case 19696: finalSpelId = 19682; break;
2104 case 19697: finalSpelId = 19683; break;
2105 case 19699: finalSpelId = 19685; break;
2106 case 19700: finalSpelId = 19686; break;
2107 case 30646: finalSpelId = 30647; break;
2108 case 30653: finalSpelId = 30648; break;
2109 case 30654: finalSpelId = 30652; break;
2110 case 30099: finalSpelId = 30100; break;
2111 case 30102: finalSpelId = 30103; break;
2112 case 30105: finalSpelId = 30104; break;
2115 if(finalSpelId)
2116 caster->CastSpell(m_target,finalSpelId,true,NULL,this);
2117 return;
2120 // Waiting to Resurrect
2121 if(GetId()==2584)
2123 // Waiting to resurrect spell cancel, we must remove player from resurrect queue
2124 if(m_target->GetTypeId() == TYPEID_PLAYER)
2125 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
2126 bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
2127 return;
2130 // Dark Fiend
2131 if(GetId()==45934)
2133 // Kill target if dispelled
2134 if (m_removeMode==AURA_REMOVE_BY_DISPEL)
2135 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2136 return;
2139 // Burning Winds
2140 if(GetId()==46308) // casted only at creatures at spawn
2142 m_target->CastSpell(m_target,47287,true,NULL,this);
2143 return;
2146 if (caster && m_removeMode == AURA_REMOVE_BY_DEATH)
2148 // Stop caster Arcane Missle chanelling on death
2149 if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE &&
2150 m_spellProto->SpellFamilyFlags&0x0000000000000800LL)
2152 caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
2153 return;
2155 // Stop caster Penance chanelling on death
2156 if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST &&
2157 m_spellProto->SpellFamilyFlags2 & 0x00000080)
2159 caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
2160 return;
2166 // AT APPLY & REMOVE
2168 switch(m_spellProto->SpellFamilyName)
2170 case SPELLFAMILY_GENERIC:
2172 // Unstable Power
2173 if( GetId()==24658 )
2175 uint32 spellId = 24659;
2176 if (apply)
2178 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2179 if (!spell)
2180 return;
2181 for (int i=0; i < spell->StackAmount; ++i)
2182 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2183 return;
2185 m_target->RemoveAurasDueToSpell(spellId);
2186 return;
2188 // Restless Strength
2189 if( GetId()==24661 )
2191 uint32 spellId = 24662;
2192 if (apply)
2194 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2195 if (!spell)
2196 return;
2197 for (int i=0; i < spell->StackAmount; ++i)
2198 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2199 return;
2201 m_target->RemoveAurasDueToSpell(spellId);
2202 return;
2204 //Summon Fire Elemental
2205 if (GetId() == 40133 && caster)
2207 Unit *owner = caster->GetOwner();
2208 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2210 if(apply)
2211 owner->CastSpell(owner,8985,true);
2212 else
2213 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2215 return;
2218 //Summon Earth Elemental
2219 if (GetId() == 40132 && caster)
2221 Unit *owner = caster->GetOwner();
2222 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2224 if(apply)
2225 owner->CastSpell(owner,19704,true);
2226 else
2227 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2229 return;
2231 break;
2233 case SPELLFAMILY_MAGE:
2235 break;
2237 case SPELLFAMILY_DRUID:
2239 // Lifebloom
2240 if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
2242 if ( apply )
2244 if ( caster )
2245 // prevent double apply bonuses
2246 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2247 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2249 else
2251 // Final heal only on dispelled or duration end
2252 if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
2253 return;
2255 // have a look if there is still some other Lifebloom dummy aura
2256 Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2257 for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); ++itr)
2258 if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2259 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
2260 return;
2262 // final heal
2263 if(m_target->IsInWorld() && m_stackAmount > 0)
2265 int32 amount = m_modifier.m_amount / m_stackAmount;
2266 m_target->CastCustomSpell(m_target,33778,&amount,NULL,NULL,true,NULL,this,GetCasterGUID());
2269 return;
2272 // Predatory Strikes
2273 if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
2275 ((Player*)m_target)->UpdateAttackPowerAndDamage();
2276 return;
2278 // Idol of the Emerald Queen
2279 if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
2281 if(apply)
2283 SpellModifier *mod = new SpellModifier;
2284 mod->op = SPELLMOD_DOT;
2285 mod->value = m_modifier.m_amount/7;
2286 mod->type = SPELLMOD_FLAT;
2287 mod->spellId = GetId();
2288 mod->mask = 0x001000000000LL;
2289 mod->mask2= 0LL;
2291 m_spellmod = mod;
2294 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2295 return;
2297 break;
2299 case SPELLFAMILY_HUNTER:
2301 // Improved Aspect of the Viper
2302 if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
2304 if(apply)
2306 // + effect value for Aspect of the Viper
2307 SpellModifier *mod = new SpellModifier;
2308 mod->op = SPELLMOD_EFFECT1;
2309 mod->value = m_modifier.m_amount;
2310 mod->type = SPELLMOD_FLAT;
2311 mod->spellId = GetId();
2312 mod->mask = 0x4000000000000LL;
2313 mod->mask2= 0LL;
2315 m_spellmod = mod;
2318 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2319 return;
2321 break;
2323 case SPELLFAMILY_SHAMAN:
2325 // Improved Weapon Totems
2326 if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
2328 if(apply)
2330 SpellModifier *mod = new SpellModifier;
2331 mod->op = SPELLMOD_EFFECT1;
2332 mod->value = m_modifier.m_amount;
2333 mod->type = SPELLMOD_PCT;
2334 mod->spellId = GetId();
2335 switch (m_effIndex)
2337 case 0:
2338 mod->mask = 0x00200000000LL; // Windfury Totem
2339 mod->mask2= 0LL;
2340 break;
2341 case 1:
2342 mod->mask = 0x00400000000LL; // Flametongue Totem
2343 mod->mask2= 0LL;
2344 break;
2347 m_spellmod = mod;
2350 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2351 return;
2353 break;
2357 // pet auras
2358 if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
2360 if(apply)
2361 m_target->AddPetAura(petSpell);
2362 else
2363 m_target->RemovePetAura(petSpell);
2364 return;
2368 void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
2370 // spells required only Real aura add/remove
2371 if(!Real)
2372 return;
2374 Unit* caster = GetCaster();
2376 SpellEntry const*spell = GetSpellProto();
2377 switch( spell->SpellFamilyName)
2379 case SPELLFAMILY_ROGUE:
2381 // Master of Subtlety
2382 if (spell->Id==31666 && !apply && Real)
2384 m_target->RemoveAurasDueToSpell(31665);
2385 break;
2387 break;
2389 case SPELLFAMILY_HUNTER:
2391 // Aspect of the Viper
2392 if (spell->SpellFamilyFlags&0x0004000000000000LL)
2394 // Update regen on remove
2395 if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
2396 ((Player*)m_target)->UpdateManaRegen();
2397 break;
2399 // Explosive Shot
2400 if (spell->SpellFamilyFlags & 0x8000000000000000LL)
2402 if (apply && caster)
2404 int32 damage = m_modifier.m_amount + caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
2405 caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this);
2407 break;
2409 break;
2413 m_isPeriodic = apply;
2416 void Aura::HandleAuraMounted(bool apply, bool Real)
2418 // only at real add/remove aura
2419 if(!Real)
2420 return;
2422 if(apply)
2424 CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2425 if(!ci)
2427 sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
2428 return;
2431 uint32 team = 0;
2432 if (m_target->GetTypeId()==TYPEID_PLAYER)
2433 team = ((Player*)m_target)->GetTeam();
2435 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2436 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2437 if (minfo)
2438 display_id = minfo->modelid;
2440 m_target->Mount(display_id);
2442 else
2444 m_target->Unmount();
2448 void Aura::HandleAuraWaterWalk(bool apply, bool Real)
2450 // only at real add/remove aura
2451 if(!Real)
2452 return;
2454 WorldPacket data;
2455 if(apply)
2456 data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
2457 else
2458 data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
2459 data.append(m_target->GetPackGUID());
2460 data << uint32(0);
2461 m_target->SendMessageToSet(&data,true);
2464 void Aura::HandleAuraFeatherFall(bool apply, bool Real)
2466 // only at real add/remove aura
2467 if(!Real)
2468 return;
2470 WorldPacket data;
2471 if(apply)
2472 data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
2473 else
2474 data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
2475 data.append(m_target->GetPackGUID());
2476 data << (uint32)0;
2477 m_target->SendMessageToSet(&data,true);
2480 void Aura::HandleAuraHover(bool apply, bool Real)
2482 // only at real add/remove aura
2483 if(!Real)
2484 return;
2486 WorldPacket data;
2487 if(apply)
2488 data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
2489 else
2490 data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
2491 data.append(m_target->GetPackGUID());
2492 data << uint32(0);
2493 m_target->SendMessageToSet(&data,true);
2496 void Aura::HandleWaterBreathing(bool apply, bool Real)
2498 if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING))
2500 // update for enable timer in case not moving target
2501 if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
2503 ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
2504 ((Player*)m_target)->HandleDrowning();
2509 void Aura::HandleAuraModShapeshift(bool apply, bool Real)
2511 if(!Real)
2512 return;
2514 uint32 modelid = 0;
2515 Powers PowerType = POWER_MANA;
2516 ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
2517 switch(form)
2519 case FORM_CAT:
2520 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2521 modelid = 892;
2522 else
2523 modelid = 8571;
2524 PowerType = POWER_ENERGY;
2525 break;
2526 case FORM_TRAVEL:
2527 modelid = 632;
2528 break;
2529 case FORM_AQUA:
2530 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2531 modelid = 2428;
2532 else
2533 modelid = 2428;
2534 break;
2535 case FORM_BEAR:
2536 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2537 modelid = 2281;
2538 else
2539 modelid = 2289;
2540 PowerType = POWER_RAGE;
2541 break;
2542 case FORM_GHOUL:
2543 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2544 modelid = 10045;
2545 break;
2546 case FORM_DIREBEAR:
2547 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2548 modelid = 2281;
2549 else
2550 modelid = 2289;
2551 PowerType = POWER_RAGE;
2552 break;
2553 case FORM_CREATUREBEAR:
2554 modelid = 902;
2555 break;
2556 case FORM_GHOSTWOLF:
2557 modelid = 4613;
2558 break;
2559 case FORM_FLIGHT:
2560 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2561 modelid = 20857;
2562 else
2563 modelid = 20872;
2564 break;
2565 case FORM_MOONKIN:
2566 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2567 modelid = 15374;
2568 else
2569 modelid = 15375;
2570 break;
2571 case FORM_FLIGHT_EPIC:
2572 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2573 modelid = 21243;
2574 else
2575 modelid = 21244;
2576 break;
2577 case FORM_METAMORPHOSIS:
2578 modelid = 25277;
2579 break;
2580 case FORM_AMBIENT:
2581 case FORM_SHADOW:
2582 case FORM_STEALTH:
2583 break;
2584 case FORM_TREE:
2585 modelid = 864;
2586 break;
2587 case FORM_BATTLESTANCE:
2588 case FORM_BERSERKERSTANCE:
2589 case FORM_DEFENSIVESTANCE:
2590 PowerType = POWER_RAGE;
2591 break;
2592 case FORM_SPIRITOFREDEMPTION:
2593 modelid = 16031;
2594 break;
2595 default:
2596 sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
2599 // remove polymorph before changing display id to keep new display id
2600 switch ( form )
2602 case FORM_CAT:
2603 case FORM_TREE:
2604 case FORM_TRAVEL:
2605 case FORM_AQUA:
2606 case FORM_BEAR:
2607 case FORM_DIREBEAR:
2608 case FORM_FLIGHT_EPIC:
2609 case FORM_FLIGHT:
2610 case FORM_MOONKIN:
2611 // remove movement affects
2612 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2613 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2615 // and polymorphic affects
2616 if(m_target->IsPolymorphed())
2617 m_target->RemoveAurasDueToSpell(m_target->getTransForm());
2618 break;
2619 default:
2620 break;
2623 if(apply)
2625 // remove other shapeshift before applying a new one
2626 if(m_target->m_ShapeShiftFormSpellId)
2627 m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
2629 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
2631 if(modelid > 0)
2632 m_target->SetDisplayId(modelid);
2634 if(PowerType != POWER_MANA)
2636 // reset power to default values only at power change
2637 if(m_target->getPowerType()!=PowerType)
2638 m_target->setPowerType(PowerType);
2640 switch(form)
2642 case FORM_CAT:
2643 case FORM_BEAR:
2644 case FORM_DIREBEAR:
2646 // get furor proc chance
2647 uint32 FurorChance = 0;
2648 Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2649 for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
2651 if ((*i)->GetSpellProto()->SpellIconID == 238)
2653 FurorChance = (*i)->GetModifier()->m_amount;
2654 break;
2658 if (m_modifier.m_miscvalue == FORM_CAT)
2660 m_target->SetPower(POWER_ENERGY,0);
2661 if(urand(1,100) <= FurorChance)
2662 m_target->CastSpell(m_target,17099,true,NULL,this);
2664 else
2666 m_target->SetPower(POWER_RAGE,0);
2667 if(urand(1,100) <= FurorChance)
2668 m_target->CastSpell(m_target,17057,true,NULL,this);
2670 break;
2672 case FORM_BATTLESTANCE:
2673 case FORM_DEFENSIVESTANCE:
2674 case FORM_BERSERKERSTANCE:
2676 uint32 Rage_val = 0;
2677 // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
2678 if(m_target->GetTypeId() == TYPEID_PLAYER)
2680 PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
2681 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2683 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
2684 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2685 if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
2686 Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
2690 if (m_target->GetPower(POWER_RAGE) > Rage_val)
2691 m_target->SetPower(POWER_RAGE,Rage_val);
2692 break;
2694 default:
2695 break;
2699 m_target->m_ShapeShiftFormSpellId = GetId();
2700 m_target->m_form = form;
2702 else
2704 if(modelid > 0)
2705 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2706 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
2707 if(m_target->getClass() == CLASS_DRUID)
2708 m_target->setPowerType(POWER_MANA);
2709 m_target->m_ShapeShiftFormSpellId = 0;
2710 m_target->m_form = FORM_NONE;
2712 switch(form)
2714 // Nordrassil Harness - bonus
2715 case FORM_BEAR:
2716 case FORM_DIREBEAR:
2717 case FORM_CAT:
2719 if(Aura* dummy = m_target->GetDummyAura(37315) )
2720 m_target->CastSpell(m_target,37316,true,NULL,dummy);
2721 break;
2723 // Nordrassil Regalia - bonus
2724 case FORM_MOONKIN:
2726 if(Aura* dummy = m_target->GetDummyAura(37324) )
2727 m_target->CastSpell(m_target,37325,true,NULL,dummy);
2728 break;
2733 // adding/removing linked auras
2734 // add/remove the shapeshift aura's boosts
2735 HandleShapeshiftBoosts(apply);
2737 if(m_target->GetTypeId()==TYPEID_PLAYER)
2738 ((Player*)m_target)->InitDataForForm();
2741 void Aura::HandleAuraTransform(bool apply, bool Real)
2743 if (apply)
2745 // special case (spell specific functionality)
2746 if(m_modifier.m_miscvalue==0)
2748 // player applied only
2749 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2750 return;
2752 switch(GetId())
2754 // Orb of Deception
2755 case 16739:
2757 uint32 orb_model = m_target->GetNativeDisplayId();
2758 switch(orb_model)
2760 // Troll Female
2761 case 1479: m_target->SetDisplayId(10134); break;
2762 // Troll Male
2763 case 1478: m_target->SetDisplayId(10135); break;
2764 // Tauren Male
2765 case 59: m_target->SetDisplayId(10136); break;
2766 // Human Male
2767 case 49: m_target->SetDisplayId(10137); break;
2768 // Human Female
2769 case 50: m_target->SetDisplayId(10138); break;
2770 // Orc Male
2771 case 51: m_target->SetDisplayId(10139); break;
2772 // Orc Female
2773 case 52: m_target->SetDisplayId(10140); break;
2774 // Dwarf Male
2775 case 53: m_target->SetDisplayId(10141); break;
2776 // Dwarf Female
2777 case 54: m_target->SetDisplayId(10142); break;
2778 // NightElf Male
2779 case 55: m_target->SetDisplayId(10143); break;
2780 // NightElf Female
2781 case 56: m_target->SetDisplayId(10144); break;
2782 // Undead Female
2783 case 58: m_target->SetDisplayId(10145); break;
2784 // Undead Male
2785 case 57: m_target->SetDisplayId(10146); break;
2786 // Tauren Female
2787 case 60: m_target->SetDisplayId(10147); break;
2788 // Gnome Male
2789 case 1563: m_target->SetDisplayId(10148); break;
2790 // Gnome Female
2791 case 1564: m_target->SetDisplayId(10149); break;
2792 // BloodElf Female
2793 case 15475: m_target->SetDisplayId(17830); break;
2794 // BloodElf Male
2795 case 15476: m_target->SetDisplayId(17829); break;
2796 // Dranei Female
2797 case 16126: m_target->SetDisplayId(17828); break;
2798 // Dranei Male
2799 case 16125: m_target->SetDisplayId(17827); break;
2800 default: break;
2802 break;
2804 // Murloc costume
2805 case 42365: m_target->SetDisplayId(21723); break;
2806 default: break;
2809 else
2811 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2812 if(!ci)
2814 //pig pink ^_^
2815 m_target->SetDisplayId(16358);
2816 sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
2818 else
2820 // Will use the default model here
2821 m_target->SetDisplayId(ci->DisplayID_A);
2823 // Dragonmaw Illusion (set mount model also)
2824 if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
2825 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
2827 m_target->setTransForm(GetId());
2830 // polymorph case
2831 if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
2833 // for players, start regeneration after 1s (in polymorph fast regeneration case)
2834 // only if caster is Player (after patch 2.4.2)
2835 if(IS_PLAYER_GUID(GetCasterGUID()) )
2836 ((Player*)m_target)->setRegenTimer(1000);
2838 //dismount polymorphed target (after patch 2.4.2)
2839 if (m_target->IsMounted())
2840 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2843 else
2845 Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
2846 if(otherTransforms.empty())
2848 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2849 m_target->setTransForm(0);
2851 else
2853 // look for other transform auras
2854 Aura* handledAura = *otherTransforms.begin();
2855 for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
2857 // negative auras are preferred
2858 if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
2860 handledAura = *i;
2861 break;
2864 handledAura->ApplyModifier(true);
2867 // Dragonmaw Illusion (restore mount model)
2868 if(GetId()==42016 && m_target->GetMountID()==16314)
2870 if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
2872 uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
2873 if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
2875 uint32 team = 0;
2876 if (m_target->GetTypeId()==TYPEID_PLAYER)
2877 team = ((Player*)m_target)->GetTeam();
2879 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2880 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2881 if (minfo)
2882 display_id = minfo->modelid;
2884 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
2891 void Aura::HandleForceReaction(bool apply, bool Real)
2893 if(m_target->GetTypeId() != TYPEID_PLAYER)
2894 return;
2896 if(!Real)
2897 return;
2899 Player* player = (Player*)m_target;
2901 uint32 faction_id = m_modifier.m_miscvalue;
2902 uint32 faction_rank = m_modifier.m_amount;
2904 if(apply)
2905 player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
2906 else
2907 player->m_forcedReactions.erase(faction_id);
2909 WorldPacket data;
2910 data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
2911 data << uint32(player->m_forcedReactions.size());
2912 for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
2914 data << uint32(itr->first); // faction_id (Faction.dbc)
2915 data << uint32(itr->second); // reputation rank
2917 player->SendDirectMessage(&data);
2920 void Aura::HandleAuraModSkill(bool apply, bool Real)
2922 if(m_target->GetTypeId() != TYPEID_PLAYER)
2923 return;
2925 uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
2926 int32 points = GetModifier()->m_amount;
2928 ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
2929 if(prot == SKILL_DEFENSE)
2930 ((Player*)m_target)->UpdateDefenseBonusesMod();
2933 void Aura::HandleChannelDeathItem(bool apply, bool Real)
2935 if(Real && !apply)
2937 Unit* caster = GetCaster();
2938 Unit* victim = GetTarget();
2939 if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
2940 return;
2942 SpellEntry const *spellInfo = GetSpellProto();
2943 if(spellInfo->EffectItemType[m_effIndex] == 0)
2944 return;
2946 // Soul Shard only from non-grey units
2947 if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
2948 (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
2949 victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
2950 return;
2951 ItemPosCountVec dest;
2952 uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
2953 if( msg != EQUIP_ERR_OK )
2955 ((Player*)caster)->SendEquipError( msg, NULL, NULL );
2956 return;
2959 Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
2960 ((Player*)caster)->SendNewItem(newitem, 1, true, false);
2964 void Aura::HandleBindSight(bool apply, bool Real)
2966 Unit* caster = GetCaster();
2967 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2968 return;
2970 ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
2973 void Aura::HandleFarSight(bool apply, bool Real)
2975 Unit* caster = GetCaster();
2976 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2977 return;
2979 ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
2982 void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
2984 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2985 return;
2987 if(apply)
2988 m_target->RemoveNoStackAurasDueToAura(this);
2989 m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
2992 void Aura::HandleAuraTrackResources(bool apply, bool Real)
2994 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2995 return;
2997 if(apply)
2998 m_target->RemoveNoStackAurasDueToAura(this);
2999 m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
3002 void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
3004 if(m_target->GetTypeId()!=TYPEID_PLAYER)
3005 return;
3007 if(apply)
3008 m_target->RemoveNoStackAurasDueToAura(this);
3010 m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
3013 void Aura::HandleAuraModScale(bool apply, bool Real)
3015 m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
3018 void Aura::HandleModPossess(bool apply, bool Real)
3020 if(!Real)
3021 return;
3023 if(m_target->getLevel() > m_modifier.m_amount)
3024 return;
3026 // not possess yourself
3027 if(GetCasterGUID() == m_target->GetGUID())
3028 return;
3030 Unit* caster = GetCaster();
3031 if(!caster)
3032 return;
3034 if( apply )
3036 m_target->SetCharmerGUID(GetCasterGUID());
3037 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
3038 caster->SetCharm(m_target);
3040 m_target->CombatStop();
3041 m_target->DeleteThreatList();
3042 if(m_target->GetTypeId() == TYPEID_UNIT)
3044 m_target->StopMoving();
3045 m_target->GetMotionMaster()->Clear();
3046 m_target->GetMotionMaster()->MoveIdle();
3047 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3048 charmInfo->InitPossessCreateSpells();
3051 if(caster->GetTypeId() == TYPEID_PLAYER)
3053 ((Player*)caster)->PossessSpellInitialize();
3056 else
3058 m_target->SetCharmerGUID(0);
3060 if(m_target->GetTypeId() == TYPEID_PLAYER)
3061 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3062 else if(m_target->GetTypeId() == TYPEID_UNIT)
3064 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3065 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3068 caster->SetCharm(0);
3070 if(caster->GetTypeId() == TYPEID_PLAYER)
3072 WorldPacket data(SMSG_PET_SPELLS, 8);
3073 data << uint64(0);
3074 data << uint32(0);
3075 ((Player*)caster)->GetSession()->SendPacket(&data);
3077 if(m_target->GetTypeId() == TYPEID_UNIT)
3079 ((Creature*)m_target)->AIM_Initialize();
3081 if (((Creature*)m_target)->AI())
3082 ((Creature*)m_target)->AI()->AttackStart(caster);
3085 if(caster->GetTypeId() == TYPEID_PLAYER)
3086 ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
3089 void Aura::HandleModPossessPet(bool apply, bool Real)
3091 if(!Real)
3092 return;
3094 Unit* caster = GetCaster();
3095 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
3096 return;
3098 Pet *pet = caster->GetPet();
3099 if(!pet || pet != m_target)
3100 return;
3102 if(apply)
3103 pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
3104 else
3105 pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
3107 ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : NULL);
3108 ((Player*)caster)->SetCharm(apply ? pet : NULL);
3109 ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0);
3111 if(apply)
3113 pet->StopMoving();
3114 pet->GetMotionMaster()->Clear();
3115 pet->GetMotionMaster()->MoveIdle();
3117 else
3119 pet->AttackStop();
3120 pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
3121 pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
3125 void Aura::HandleAuraModPetTalentsPoints(bool Apply, bool Real)
3127 if(!Real)
3128 return;
3130 // Recalculate pet tlaent points
3131 if (Pet *pet=m_target->GetPet())
3132 pet->InitTalentForLevel();
3135 void Aura::HandleModCharm(bool apply, bool Real)
3137 if(!Real)
3138 return;
3140 // not charm yourself
3141 if(GetCasterGUID() == m_target->GetGUID())
3142 return;
3144 Unit* caster = GetCaster();
3145 if(!caster)
3146 return;
3148 if(int32(m_target->getLevel()) <= m_modifier.m_amount)
3150 if( apply )
3152 m_target->SetCharmerGUID(GetCasterGUID());
3153 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
3154 m_target->CastStop(m_target==caster ? GetId() : 0);
3155 caster->SetCharm(m_target);
3157 m_target->CombatStop();
3158 m_target->DeleteThreatList();
3160 if(m_target->GetTypeId() == TYPEID_UNIT)
3162 ((Creature*)m_target)->AIM_Initialize();
3163 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3164 charmInfo->InitCharmCreateSpells();
3165 charmInfo->SetReactState( REACT_DEFENSIVE );
3167 if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
3169 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3170 if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
3172 //to prevent client crash
3173 m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
3174 //just to enable stat window
3175 charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
3176 //if charmed two demons the same session, the 2nd gets the 1st one's name
3177 m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
3182 if(caster->GetTypeId() == TYPEID_PLAYER)
3184 ((Player*)caster)->CharmSpellInitialize();
3187 else
3189 m_target->SetCharmerGUID(0);
3191 if(m_target->GetTypeId() == TYPEID_PLAYER)
3192 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3193 else
3195 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3197 // restore faction
3198 if(((Creature*)m_target)->isPet())
3200 if(Unit* owner = m_target->GetOwner())
3201 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
3202 else if(cinfo)
3203 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3205 else if(cinfo) // normal creature
3206 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3208 // restore UNIT_FIELD_BYTES_0
3209 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
3211 CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
3212 if(cainfo && cainfo->bytes0 != 0)
3213 m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
3214 else
3215 m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
3217 if(m_target->GetCharmInfo())
3218 m_target->GetCharmInfo()->SetPetNumber(0, true);
3219 else
3220 sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
3224 caster->SetCharm(0);
3226 if(caster->GetTypeId() == TYPEID_PLAYER)
3228 WorldPacket data(SMSG_PET_SPELLS, 8);
3229 data << uint64(0);
3230 data << uint32(0);
3231 ((Player*)caster)->GetSession()->SendPacket(&data);
3233 if(m_target->GetTypeId() == TYPEID_UNIT)
3235 ((Creature*)m_target)->AIM_Initialize();
3236 if (((Creature*)m_target)->AI())
3237 ((Creature*)m_target)->AI()->AttackStart(caster);
3243 void Aura::HandleModConfuse(bool apply, bool Real)
3245 if(!Real)
3246 return;
3248 m_target->SetConfused(apply, GetCasterGUID(), GetId());
3251 void Aura::HandleModFear(bool apply, bool Real)
3253 if (!Real)
3254 return;
3256 m_target->SetFeared(apply, GetCasterGUID(), GetId());
3259 void Aura::HandleFeignDeath(bool apply, bool Real)
3261 if(!Real)
3262 return;
3264 if(m_target->GetTypeId() != TYPEID_PLAYER)
3265 return;
3267 if( apply )
3270 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3271 data<<m_target->GetGUID();
3272 data<<uint8(0);
3273 m_target->SendMessageToSet(&data,true);
3275 // blizz like 2.0.x
3276 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
3277 // blizz like 2.0.x
3278 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3279 // blizz like 2.0.x
3280 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3282 m_target->addUnitState(UNIT_STAT_DIED);
3283 m_target->CombatStop();
3285 // prevent interrupt message
3286 if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
3287 m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
3288 m_target->InterruptNonMeleeSpells(true);
3289 m_target->getHostilRefManager().deleteReferences();
3291 else
3294 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3295 data<<m_target->GetGUID();
3296 data<<uint8(1);
3297 m_target->SendMessageToSet(&data,true);
3299 // blizz like 2.0.x
3300 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
3301 // blizz like 2.0.x
3302 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3303 // blizz like 2.0.x
3304 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3306 m_target->clearUnitState(UNIT_STAT_DIED);
3310 void Aura::HandleAuraModDisarm(bool apply, bool Real)
3312 if(!Real)
3313 return;
3315 if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
3316 return;
3318 // not sure for it's correctness
3319 if(apply)
3320 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3321 else
3322 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3324 // only at real add/remove aura
3325 if (m_target->GetTypeId() != TYPEID_PLAYER)
3326 return;
3328 // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
3329 if (((Player *)m_target)->IsInFeralForm())
3330 return;
3332 if (apply)
3333 m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
3334 else
3335 ((Player *)m_target)->SetRegularAttackTime();
3337 m_target->UpdateDamagePhysical(BASE_ATTACK);
3340 void Aura::HandleAuraModStun(bool apply, bool Real)
3342 if(!Real)
3343 return;
3345 if (apply)
3347 m_target->addUnitState(UNIT_STAT_STUNNED);
3348 m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
3350 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3351 m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
3353 // Creature specific
3354 if(m_target->GetTypeId() != TYPEID_PLAYER)
3355 ((Creature*)m_target)->StopMoving();
3356 else
3357 m_target->SetUnitMovementFlags(0); //Clear movement flags
3359 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
3361 data.append(m_target->GetPackGUID());
3362 data << uint32(0);
3363 m_target->SendMessageToSet(&data,true);
3365 else
3367 // Real remove called after current aura remove from lists, check if other similar auras active
3368 if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
3369 return;
3371 m_target->clearUnitState(UNIT_STAT_STUNNED);
3372 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3374 if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
3376 if(m_target->getVictim() && m_target->isAlive())
3377 m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3379 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
3380 data.append(m_target->GetPackGUID());
3381 data << uint32(0);
3382 m_target->SendMessageToSet(&data,true);
3385 // Wyvern Sting
3386 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
3388 Unit* caster = GetCaster();
3389 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
3390 return;
3392 uint32 spell_id = 0;
3394 switch(GetId())
3396 case 19386: spell_id = 24131; break;
3397 case 24132: spell_id = 24134; break;
3398 case 24133: spell_id = 24135; break;
3399 case 27068: spell_id = 27069; break;
3400 default:
3401 sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
3402 return;
3405 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
3407 if(!spellInfo)
3408 return;
3410 caster->CastSpell(m_target,spellInfo,true,NULL,this);
3411 return;
3416 void Aura::HandleModStealth(bool apply, bool Real)
3418 if(apply)
3420 // drop flag at stealth in bg
3421 if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
3422 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3423 bg->EventPlayerDroppedFlag((Player*)m_target);
3425 // only at real aura add
3426 if(Real)
3428 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
3429 if(m_target->GetTypeId()==TYPEID_PLAYER)
3430 m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
3432 // apply only if not in GM invisibility (and overwrite invisibility state)
3433 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3435 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3436 m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
3440 else
3442 // only at real aura remove
3443 if(Real)
3445 // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
3446 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
3448 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
3449 if(m_target->GetTypeId()==TYPEID_PLAYER)
3450 m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
3452 // restore invisibility if any
3453 if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
3455 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3456 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3458 else
3459 m_target->SetVisibility(VISIBILITY_ON);
3464 // Master of Subtlety
3465 Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
3466 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
3468 if ((*i)->GetSpellProto()->SpellIconID == 2114)
3470 if (apply)
3472 int32 bp = (*i)->GetModifier()->m_amount;
3473 m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
3475 else
3476 m_target->CastSpell(m_target,31666,true);
3477 break;
3482 void Aura::HandleInvisibility(bool apply, bool Real)
3484 if(apply)
3486 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3488 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3490 // apply glow vision
3491 m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3493 // drop flag at invisible in bg
3494 if(((Player*)m_target)->InBattleGround())
3495 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3496 bg->EventPlayerDroppedFlag((Player*)m_target);
3499 // apply only if not in GM invisibility and not stealth
3500 if(m_target->GetVisibility()==VISIBILITY_ON)
3502 // Aura not added yet but visibility code expect temporary add aura
3503 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3504 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3507 else
3509 // recalculate value at modifier remove (current aura already removed)
3510 m_target->m_invisibilityMask = 0;
3511 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
3512 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3513 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3515 // only at real aura remove and if not have different invisibility auras.
3516 if(Real && m_target->m_invisibilityMask==0)
3518 // remove glow vision
3519 if(m_target->GetTypeId() == TYPEID_PLAYER)
3520 m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3522 // apply only if not in GM invisibility & not stealthed while invisible
3523 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3525 // if have stealth aura then already have stealth visibility
3526 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
3527 m_target->SetVisibility(VISIBILITY_ON);
3533 void Aura::HandleInvisibilityDetect(bool apply, bool Real)
3535 if(apply)
3537 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3539 else
3541 // recalculate value at modifier remove (current aura already removed)
3542 m_target->m_detectInvisibilityMask = 0;
3543 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
3544 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3545 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3547 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3548 ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
3551 void Aura::HandleAuraModRoot(bool apply, bool Real)
3553 // only at real add/remove aura
3554 if(!Real)
3555 return;
3557 // Frost root aura -> freeze/unfreeze target
3558 if (GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST)
3559 m_target->ModifyAuraState(AURA_STATE_FROZEN, apply);
3561 uint32 apply_stat = UNIT_STAT_ROOT;
3562 if (apply)
3564 m_target->addUnitState(UNIT_STAT_ROOT);
3565 m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
3566 // probably wrong (this add skinable flag)
3567 // TODO: find correct flag
3568 // m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3570 //Save last orientation
3571 if( m_target->getVictim() )
3572 m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
3574 if(m_target->GetTypeId() == TYPEID_PLAYER)
3576 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
3577 data.append(m_target->GetPackGUID());
3578 data << (uint32)2;
3579 m_target->SendMessageToSet(&data,true);
3581 //Clear unit movement flags
3582 m_target->SetUnitMovementFlags(0);
3584 else
3585 ((Creature *)m_target)->StopMoving();
3587 else
3589 // Real remove called after current aura remove from lists, check if other similar auras active
3590 if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
3591 return;
3593 m_target->clearUnitState(UNIT_STAT_ROOT);
3594 // probably wrong (this add skinable flag)
3595 // TODO: find correct flag
3596 // m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3598 if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
3600 if(m_target->getVictim() && m_target->isAlive())
3601 m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3603 if(m_target->GetTypeId() == TYPEID_PLAYER)
3605 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
3606 data.append(m_target->GetPackGUID());
3607 data << (uint32)2;
3608 m_target->SendMessageToSet(&data,true);
3614 void Aura::HandleAuraModSilence(bool apply, bool Real)
3616 // only at real add/remove aura
3617 if(!Real)
3618 return;
3620 if(apply)
3622 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3623 // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3624 for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
3626 Spell* currentSpell = m_target->m_currentSpells[i];
3627 if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
3629 uint32 state = currentSpell->getState();
3630 // Stop spells on prepare or casting state
3631 if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
3633 currentSpell->cancel();
3634 currentSpell->SetReferencedFromCurrent(false);
3635 m_target->m_currentSpells[i] = NULL;
3640 switch (GetId())
3642 // Arcane Torrent (Energy)
3643 case 25046:
3645 Unit * caster = GetCaster();
3646 if (!caster)
3647 return;
3649 // Search Mana Tap auras on caster
3650 Aura * dummy = caster->GetDummyAura(28734);
3651 if (dummy)
3653 int32 bp = dummy->GetStackAmount() * 10;
3654 caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true);
3655 caster->RemoveAurasDueToSpell(28734);
3660 else
3662 // Real remove called after current aura remove from lists, check if other similar auras active
3663 if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
3664 return;
3666 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3670 void Aura::HandleModThreat(bool apply, bool Real)
3672 // only at real add/remove aura
3673 if(!Real)
3674 return;
3676 if(!m_target->isAlive())
3677 return;
3679 Unit* caster = GetCaster();
3681 if(!caster || !caster->isAlive())
3682 return;
3684 int level_diff = 0;
3685 int multiplier = 0;
3686 switch (GetId())
3688 // Arcane Shroud
3689 case 26400:
3690 level_diff = m_target->getLevel() - 60;
3691 multiplier = 2;
3692 break;
3693 // The Eye of Diminution
3694 case 28862:
3695 level_diff = m_target->getLevel() - 60;
3696 multiplier = 1;
3697 break;
3699 if (level_diff > 0)
3700 m_modifier.m_amount += multiplier * level_diff;
3702 for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
3704 if(m_modifier.m_miscvalue & int32(1<<x))
3706 if(m_target->GetTypeId() == TYPEID_PLAYER)
3707 ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
3712 void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
3714 // only at real add/remove aura
3715 if(!Real)
3716 return;
3718 if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
3719 return;
3721 Unit* caster = GetCaster();
3723 if(!caster || !caster->isAlive())
3724 return;
3726 float threatMod = 0.0f;
3727 if(apply)
3728 threatMod = float(m_modifier.m_amount);
3729 else
3730 threatMod = float(-m_modifier.m_amount);
3732 m_target->getHostilRefManager().threatAssist(caster, threatMod);
3735 void Aura::HandleModTaunt(bool apply, bool Real)
3737 // only at real add/remove aura
3738 if(!Real)
3739 return;
3741 if(!m_target->isAlive() || !m_target->CanHaveThreatList())
3742 return;
3744 Unit* caster = GetCaster();
3746 if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
3747 return;
3749 if(apply)
3750 m_target->TauntApply(caster);
3751 else
3753 // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
3754 m_target->TauntFadeOut(caster);
3758 /*********************************************************/
3759 /*** MODIFY SPEED ***/
3760 /*********************************************************/
3761 void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real)
3763 // all applied/removed only at real aura add/remove
3764 if(!Real)
3765 return;
3767 m_target->UpdateSpeed(MOVE_RUN, true);
3770 void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real)
3772 // all applied/removed only at real aura add/remove
3773 if(!Real)
3774 return;
3776 m_target->UpdateSpeed(MOVE_RUN, true);
3779 void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
3781 // all applied/removed only at real aura add/remove
3782 if(!Real)
3783 return;
3785 // Enable Fly mode for flying mounts
3786 if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
3788 WorldPacket data;
3789 if(apply)
3790 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
3791 else
3792 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
3793 data.append(m_target->GetPackGUID());
3794 data << uint32(0); // unknown
3795 m_target->SendMessageToSet(&data, true);
3797 //Players on flying mounts must be immune to polymorph
3798 if (m_target->GetTypeId()==TYPEID_PLAYER)
3799 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
3801 // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
3802 if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
3803 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
3806 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3809 void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
3811 // all applied/removed only at real aura add/remove
3812 if(!Real)
3813 return;
3815 m_target->UpdateSpeed(MOVE_SWIM, true);
3818 void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
3820 // all applied/removed only at real aura add/remove
3821 if(!Real)
3822 return;
3824 m_target->UpdateSpeed(MOVE_RUN, true);
3825 m_target->UpdateSpeed(MOVE_SWIM, true);
3826 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3829 void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
3831 // all applied/removed only at real aura add/remove
3832 if(!Real)
3833 return;
3835 m_target->UpdateSpeed(MOVE_RUN, true);
3836 m_target->UpdateSpeed(MOVE_SWIM, true);
3837 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3840 /*********************************************************/
3841 /*** IMMUNITY ***/
3842 /*********************************************************/
3844 void Aura::HandleModMechanicImmunity(bool apply, bool Real)
3846 uint32 mechanic = 1 << m_modifier.m_miscvalue;
3848 //immune movement impairment and loss of control
3849 if(GetId()==42292)
3850 mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
3852 if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3854 Unit::AuraMap& Auras = m_target->GetAuras();
3855 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3857 next = iter;
3858 ++next;
3859 SpellEntry const *spell = iter->second->GetSpellProto();
3860 if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
3861 && !iter->second->IsPositive() // only remove negative spells
3862 && spell->Id != GetId())
3864 //check for mechanic mask
3865 if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
3867 m_target->RemoveAurasDueToSpell(spell->Id);
3868 if(Auras.empty())
3869 break;
3870 else
3871 next = Auras.begin();
3877 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
3879 // Bestial Wrath
3880 if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
3882 // The Beast Within cast on owner if talent present
3883 if ( Unit* owner = m_target->GetOwner() )
3885 // Search talent
3886 Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
3887 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3889 if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
3891 if (apply)
3892 owner->CastSpell(owner, 34471, true, 0, this);
3893 else
3894 owner->RemoveAurasDueToSpell(34471);
3895 break;
3901 // The Beast Within and Bestial Wrath - immunity
3902 if(GetId() == 19574 || GetId() == 34471)
3904 if(apply)
3906 m_target->CastSpell(m_target,24395,true);
3907 m_target->CastSpell(m_target,24396,true);
3908 m_target->CastSpell(m_target,24397,true);
3909 m_target->CastSpell(m_target,26592,true);
3911 else
3913 m_target->RemoveAurasDueToSpell(24395);
3914 m_target->RemoveAurasDueToSpell(24396);
3915 m_target->RemoveAurasDueToSpell(24397);
3916 m_target->RemoveAurasDueToSpell(26592);
3921 void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
3923 if(!apply)
3925 if(m_target->GetTypeId() == TYPEID_PLAYER)
3927 if(((Player*)m_target)->InBattleGround())
3929 BattleGround *bg = ((Player*)m_target)->GetBattleGround();
3930 if(bg)
3932 switch(bg->GetTypeID())
3934 case BATTLEGROUND_AV:
3936 break;
3938 case BATTLEGROUND_WS:
3940 // Warsong Flag, horde // Silverwing Flag, alliance
3941 if(GetId() == 23333 || GetId() == 23335)
3942 bg->EventPlayerDroppedFlag(((Player*)m_target));
3943 break;
3945 case BATTLEGROUND_AB:
3947 break;
3949 case BATTLEGROUND_EY:
3951 if(GetId() == 34976)
3952 bg->EventPlayerDroppedFlag(((Player*)m_target));
3953 break;
3961 m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
3964 void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
3966 if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3968 Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
3969 for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
3971 if (auraList.front() != this) // skip itself aura (it already added)
3973 m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
3974 itr = auraList.begin();
3976 else
3977 ++itr;
3981 m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
3984 void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
3986 m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
3988 if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3990 if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
3992 uint32 school_mask = m_modifier.m_miscvalue;
3993 Unit::AuraMap& Auras = m_target->GetAuras();
3994 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3996 next = iter;
3997 ++next;
3998 SpellEntry const *spell = iter->second->GetSpellProto();
3999 if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
4000 && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
4001 && !iter->second->IsPositive() //Don't remove positive spells
4002 && spell->Id != GetId() ) //Don't remove self
4004 m_target->RemoveAurasDueToSpell(spell->Id);
4005 if(Auras.empty())
4006 break;
4007 else
4008 next = Auras.begin();
4013 if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
4015 if( apply )
4016 m_target->addUnitState(UNIT_STAT_ISOLATED);
4017 else
4018 m_target->clearUnitState(UNIT_STAT_ISOLATED);
4022 void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
4024 m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
4027 void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
4029 // all applied/removed only at real aura add/remove
4030 if(!Real)
4031 return;
4033 m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
4036 void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
4038 if(!Real)
4039 return;
4041 if(apply)
4043 // some spell have charges by functionality not have its in spell data
4044 switch (GetId())
4046 case 28200: // Ascendance (Talisman of Ascendance trinket)
4047 SetAuraCharges(6);
4048 break;
4049 default: break;
4054 void Aura::HandleAuraModStalked(bool apply, bool Real)
4056 // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
4057 if(apply)
4058 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
4059 else
4060 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
4063 /*********************************************************/
4064 /*** PERIODIC ***/
4065 /*********************************************************/
4067 void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
4069 if (m_periodicTimer <= 0)
4070 m_periodicTimer += m_modifier.periodictime;
4072 m_isPeriodic = apply;
4075 void Aura::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real)
4077 if (m_periodicTimer <= 0)
4078 m_periodicTimer += m_modifier.periodictime;
4080 m_isPeriodic = apply;
4083 void Aura::HandlePeriodicEnergize(bool apply, bool Real)
4085 if (m_periodicTimer <= 0)
4086 m_periodicTimer += m_modifier.periodictime;
4088 m_isPeriodic = apply;
4091 void Aura::HandlePeriodicHeal(bool apply, bool Real)
4093 if (m_periodicTimer <= 0)
4094 m_periodicTimer += m_modifier.periodictime;
4096 m_isPeriodic = apply;
4098 // For prevent double apply bonuses
4099 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4101 if(!loading && apply)
4103 switch (m_spellProto->SpellFamilyName)
4105 case SPELLFAMILY_DRUID:
4107 // Rejuvenation
4108 if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
4110 if(Unit* caster = GetCaster())
4112 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4113 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4115 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4116 switch((*k)->GetModifier()->m_miscvalue)
4118 case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
4119 case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
4121 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4122 break;
4133 void Aura::HandlePeriodicDamage(bool apply, bool Real)
4135 // spells required only Real aura add/remove
4136 if(!Real)
4137 return;
4139 if (m_periodicTimer <= 0)
4140 m_periodicTimer += m_modifier.periodictime;
4142 m_isPeriodic = apply;
4144 // For prevent double apply bonuses
4145 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4147 Unit *caster = GetCaster();
4149 // Custom damage calculation after
4150 if (!apply || loading || !caster)
4151 return;
4153 switch (m_spellProto->SpellFamilyName)
4155 case SPELLFAMILY_GENERIC:
4157 // Pounce Bleed
4158 if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 )
4160 // $AP*0.18/6 bonus per tick
4161 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4162 return;
4164 break;
4166 case SPELLFAMILY_WARRIOR:
4168 // Rend
4169 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4171 // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
4172 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4173 int32 mws = caster->GetAttackTime(BASE_ATTACK);
4174 float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
4175 float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
4176 m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f);
4177 return;
4179 break;
4181 case SPELLFAMILY_DRUID:
4183 // Rake
4184 if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
4186 // $AP*0.06 bonus per tick
4187 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100);
4188 return;
4190 // Lacerate
4191 if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
4193 // $AP*0.05/5 bonus per tick
4194 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
4195 return;
4197 // Rip
4198 if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
4200 // 0.01*$AP*cp
4201 if (caster->GetTypeId() != TYPEID_PLAYER)
4202 return;
4204 uint8 cp = ((Player*)caster)->GetComboPoints();
4206 // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
4207 Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
4208 for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
4210 if((*itr)->GetId()==34241)
4212 m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
4213 break;
4216 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4217 return;
4219 // Lock Jaw
4220 if (m_spellProto->SpellFamilyFlags & 0x1000000000000000LL)
4222 // 0.15*$AP
4223 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 15 / 100);
4224 return;
4226 break;
4228 case SPELLFAMILY_ROGUE:
4230 // Rupture
4231 if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
4233 if (caster->GetTypeId() != TYPEID_PLAYER)
4234 return;
4235 //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs
4236 //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs
4237 //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs
4238 //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs
4239 //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs
4240 float AP_per_combo[] = {0, 0.015f, 0.024, 0.03, 0.03428571, 0.0375};
4241 uint8 cp = ((Player*)caster)->GetComboPoints();
4242 if (cp > 5) cp = 5;
4243 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]);
4244 return;
4246 // Garrote
4247 if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
4249 // $AP*0.07 bonus per tick
4250 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 7 / 100);
4251 return;
4253 // Deadly Poison
4254 if (m_spellProto->SpellFamilyFlags & 0x0000000000010000)
4256 // 0.08*$AP / 4 * amount of stack
4257 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 * GetStackAmount() / 100);
4258 return;
4260 break;
4262 case SPELLFAMILY_HUNTER:
4264 // Serpent Sting
4265 if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
4267 // $RAP*0.1/5 bonus per tick
4268 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4269 return;
4271 // Immolation Trap
4272 if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
4274 // $RAP*0.1/5 bonus per tick
4275 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4276 return;
4278 break;
4280 case SPELLFAMILY_PALADIN:
4282 // Consecration
4283 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4285 // ($m1+0.04*$SPH+0.04*$AP)
4286 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4287 int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) +
4288 caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target);
4289 m_modifier.m_amount += int32(0.04f*holy + 0.04f*ap);
4291 // Improved Consecration - Libram of the Eternal Rest
4292 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4293 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4295 switch((*k)->GetModifier()->m_miscvalue)
4297 case 5147:
4299 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4300 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4301 break;
4305 return;
4307 // Seal of Vengeance 0.013*$SPH+0.025*$AP per tick (also can stack)
4308 if(m_spellProto->SpellFamilyFlags & 0x0000080000000000LL)
4310 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4311 int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) +
4312 caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target);
4313 m_modifier.m_amount += int32((0.013f*holy + 0.025f*ap) * GetStackAmount());
4314 return;
4316 break;
4318 default:
4319 break;
4323 void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
4325 if (m_periodicTimer <= 0)
4326 m_periodicTimer += m_modifier.periodictime;
4328 m_isPeriodic = apply;
4331 void Aura::HandlePeriodicLeech(bool apply, bool Real)
4333 if (m_periodicTimer <= 0)
4334 m_periodicTimer += m_modifier.periodictime;
4336 m_isPeriodic = apply;
4339 void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
4341 if (m_periodicTimer <= 0)
4342 m_periodicTimer += m_modifier.periodictime;
4344 m_isPeriodic = apply;
4347 /*********************************************************/
4348 /*** MODIFY STATS ***/
4349 /*********************************************************/
4351 /********************************/
4352 /*** RESISTANCE ***/
4353 /********************************/
4355 void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
4357 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4359 if(m_modifier.m_miscvalue & int32(1<<x))
4361 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
4362 if(m_target->GetTypeId() == TYPEID_PLAYER)
4363 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4368 void Aura::HandleAuraModResistance(bool apply, bool Real)
4370 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4372 if(m_modifier.m_miscvalue & int32(1<<x))
4374 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4375 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4376 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4381 void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
4383 // only players have base stats
4384 if(m_target->GetTypeId() != TYPEID_PLAYER)
4386 //pets only have base armor
4387 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4388 m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
4390 else
4392 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4394 if(m_modifier.m_miscvalue & int32(1<<x))
4395 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
4400 void Aura::HandleModResistancePercent(bool apply, bool Real)
4402 for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4404 if(m_modifier.m_miscvalue & int32(1<<i))
4406 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4407 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4409 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
4410 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
4416 void Aura::HandleModBaseResistance(bool apply, bool Real)
4418 // only players have base stats
4419 if(m_target->GetTypeId() != TYPEID_PLAYER)
4421 //only pets have base stats
4422 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4423 m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4425 else
4427 for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4428 if(m_modifier.m_miscvalue & (1<<i))
4429 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4433 /********************************/
4434 /*** STAT ***/
4435 /********************************/
4437 void Aura::HandleAuraModStat(bool apply, bool Real)
4439 if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
4441 sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
4442 return;
4445 for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4447 // -1 or -2 is all stats ( misc < -2 checked in function beginning )
4448 if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
4450 //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
4451 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4452 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4453 m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
4458 void Aura::HandleModPercentStat(bool apply, bool Real)
4460 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4462 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4463 return;
4466 // only players have base stats
4467 if (m_target->GetTypeId() != TYPEID_PLAYER)
4468 return;
4470 for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
4472 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4473 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
4477 void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real)
4479 if(m_target->GetTypeId() != TYPEID_PLAYER)
4480 return;
4482 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4483 // This information for client side use only
4484 // Recalculate bonus
4485 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4488 void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real)
4490 if(m_target->GetTypeId() != TYPEID_PLAYER)
4491 return;
4493 // Recalculate bonus
4494 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4497 void Aura::HandleAuraModDispelResist(bool apply, bool Real)
4499 if(!Real || !apply)
4500 return;
4502 if(GetId()==33206)
4503 m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
4506 void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real)
4508 if(m_target->GetTypeId() != TYPEID_PLAYER)
4509 return;
4511 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4512 // This information for client side use only
4513 // Recalculate bonus
4514 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4517 void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real)
4519 if(m_target->GetTypeId() != TYPEID_PLAYER)
4520 return;
4522 // Recalculate bonus
4523 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4526 void Aura::HandleModHealingDone(bool /*apply*/, bool Real)
4528 if(m_target->GetTypeId() != TYPEID_PLAYER)
4529 return;
4530 // implemented in Unit::SpellHealingBonus
4531 // this information is for client side only
4532 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4535 void Aura::HandleModTotalPercentStat(bool apply, bool Real)
4537 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4539 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4540 return;
4543 //save current and max HP before applying aura
4544 uint32 curHPValue = m_target->GetHealth();
4545 uint32 maxHPValue = m_target->GetMaxHealth();
4547 for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4549 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4551 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4552 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4553 m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
4557 //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
4558 if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
4560 // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
4561 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
4562 m_target->SetHealth(newHPValue);
4566 void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
4568 if(m_target->GetTypeId() != TYPEID_PLAYER)
4569 return;
4571 if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
4573 // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
4574 // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
4575 sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
4576 return;
4579 // Recalculate Armor
4580 m_target->UpdateArmor();
4583 /********************************/
4584 /*** HEAL & ENERGIZE ***/
4585 /********************************/
4586 void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
4589 Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
4590 so this aura not fully working.
4592 if(apply)
4594 if(!m_target->isAlive())
4595 return;
4597 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4598 m_target->SetStandState(PLAYER_STATE_SIT);
4600 if(m_periodicTimer <= 0)
4602 m_periodicTimer += m_modifier.periodictime;
4604 if(m_target->GetHealth() < m_target->GetMaxHealth())
4606 // PeriodicTick can cast triggered spells with stats changes
4607 PeriodicTick();
4612 m_isPeriodic = apply;
4615 void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
4617 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4618 m_target->SetStandState(PLAYER_STATE_SIT);
4619 if(apply)
4621 if(m_modifier.periodictime == 0)
4622 m_modifier.periodictime = 1000;
4623 if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
4625 m_periodicTimer += m_modifier.periodictime;
4627 if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
4629 // PeriodicTick can cast triggered spells with stats changes
4630 PeriodicTick();
4635 m_isPeriodic = apply;
4638 void Aura::HandleModRegen(bool apply, bool Real) // eating
4640 if(apply)
4642 if(!m_target->isAlive())
4643 return;
4645 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4646 m_target->SetStandState(PLAYER_STATE_SIT);
4648 if(m_periodicTimer <= 0)
4650 m_periodicTimer += 5000;
4651 int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
4652 Unit *caster = GetCaster();
4653 if (caster)
4655 SpellEntry const *spellProto = GetSpellProto();
4656 if (spellProto)
4657 m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
4662 m_isPeriodic = apply;
4665 void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
4667 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4668 m_target->SetStandState(PLAYER_STATE_SIT);
4670 if(apply && m_periodicTimer <= 0)
4672 m_periodicTimer += 2000;
4674 Powers pt = m_target->getPowerType();
4675 if(int32(pt) != m_modifier.m_miscvalue)
4676 return;
4678 if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
4680 // eating anim
4681 m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
4683 else if( GetId() == 20577 )
4685 // cannibalize anim
4686 m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE);
4689 // Warrior talent, gain 1 rage every 3 seconds while in combat
4690 if(pt == POWER_RAGE && m_target->isInCombat())
4692 m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
4693 m_periodicTimer += 1000;
4696 m_isPeriodic = apply;
4697 if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
4698 ((Player*)m_target)->UpdateManaRegen();
4701 void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
4703 // spells required only Real aura add/remove
4704 if(!Real)
4705 return;
4707 if (m_target->GetTypeId() != TYPEID_PLAYER)
4708 return;
4710 // Update manaregen value
4711 if (m_modifier.m_miscvalue == POWER_MANA)
4712 ((Player*)m_target)->UpdateManaRegen();
4715 void Aura::HandleModManaRegen(bool /*apply*/, bool Real)
4717 // spells required only Real aura add/remove
4718 if(!Real)
4719 return;
4721 if (m_target->GetTypeId() != TYPEID_PLAYER)
4722 return;
4724 //Note: an increase in regen does NOT cause threat.
4725 ((Player*)m_target)->UpdateManaRegen();
4728 void Aura::HandleComprehendLanguage(bool apply, bool Real)
4730 if(apply)
4731 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4732 else
4733 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4736 void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
4738 // Special case with temporary increase max/current health
4739 switch(GetId())
4741 case 12976: // Warrior Last Stand triggered spell
4742 case 28726: // Nightmare Seed ( Nightmare Seed )
4743 case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
4744 case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
4746 if(Real)
4748 if(apply)
4750 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4751 m_target->ModifyHealth(m_modifier.m_amount);
4753 else
4755 if (int32(m_target->GetHealth()) > m_modifier.m_amount)
4756 m_target->ModifyHealth(-m_modifier.m_amount);
4757 else
4758 m_target->SetHealth(1);
4759 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4762 return;
4766 // generic case
4767 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4770 void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
4772 uint32 oldhealth = m_target->GetHealth();
4773 double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
4775 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4777 // refresh percentage
4778 if(oldhealth > 0)
4780 uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
4781 if(newhealth==0)
4782 newhealth = 1;
4784 m_target->SetHealth(newhealth);
4788 void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
4790 Powers powerType = m_target->getPowerType();
4791 if(int32(powerType) != m_modifier.m_miscvalue)
4792 return;
4794 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4796 m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4799 void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/)
4801 Powers powerType = m_target->getPowerType();
4802 if(int32(powerType) != m_modifier.m_miscvalue)
4803 return;
4805 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4807 m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply);
4810 void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/)
4812 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
4815 void Aura::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/)
4817 m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_modifier.m_amount), apply);
4820 /********************************/
4821 /*** FIGHT ***/
4822 /********************************/
4824 void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real)
4826 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4827 return;
4829 ((Player*)m_target)->UpdateParryPercentage();
4832 void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real)
4834 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4835 return;
4837 ((Player*)m_target)->UpdateDodgePercentage();
4838 //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
4841 void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real)
4843 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4844 return;
4846 ((Player*)m_target)->UpdateBlockPercentage();
4847 //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
4850 void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real)
4852 // spells required only Real aura add/remove
4853 if(!Real)
4854 return;
4856 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4857 return;
4859 ((Player*)m_target)->UpdateManaRegen();
4862 void Aura::HandleAuraModCritPercent(bool apply, bool Real)
4864 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4865 return;
4867 // apply item specific bonuses for already equipped weapon
4868 if(Real)
4870 for(int i = 0; i < MAX_ATTACK; ++i)
4871 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4872 ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
4875 // mods must be applied base at equipped weapon class and subclass comparison
4876 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4877 // m_modifier.m_miscvalue comparison with item generated damage types
4879 if (GetSpellProto()->EquippedItemClass == -1)
4881 ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4882 ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4883 ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4885 else
4887 // done in Player::_ApplyWeaponDependentAuraMods
4891 void Aura::HandleModHitChance(bool apply, bool Real)
4893 if(m_target->GetTypeId() == TYPEID_PLAYER)
4895 ((Player*)m_target)->UpdateMeleeHitChances();
4896 ((Player*)m_target)->UpdateRangedHitChances();
4898 else
4900 m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4901 m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4905 void Aura::HandleModSpellHitChance(bool apply, bool Real)
4907 if(m_target->GetTypeId() == TYPEID_PLAYER)
4909 ((Player*)m_target)->UpdateSpellHitChances();
4911 else
4913 m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
4917 void Aura::HandleModSpellCritChance(bool apply, bool Real)
4919 // spells required only Real aura add/remove
4920 if(!Real)
4921 return;
4923 if(m_target->GetTypeId() == TYPEID_PLAYER)
4925 ((Player*)m_target)->UpdateAllSpellCritChances();
4927 else
4929 m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
4933 void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
4935 // spells required only Real aura add/remove
4936 if(!Real)
4937 return;
4939 if(m_target->GetTypeId() != TYPEID_PLAYER)
4940 return;
4942 for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
4943 if (m_modifier.m_miscvalue & (1<<school))
4944 ((Player*)m_target)->UpdateSpellCritChance(school);
4947 /********************************/
4948 /*** ATTACK SPEED ***/
4949 /********************************/
4951 void Aura::HandleModCastingSpeed(bool apply, bool Real)
4953 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4956 void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
4958 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4959 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4960 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4963 void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
4965 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4966 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4967 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4968 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4971 void Aura::HandleModAttackSpeed(bool apply, bool Real)
4973 if(!m_target->isAlive() )
4974 return;
4976 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4979 void Aura::HandleHaste(bool apply, bool Real)
4981 m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
4982 m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
4983 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
4986 void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
4988 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4991 void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
4993 if(m_target->GetTypeId() != TYPEID_PLAYER)
4994 return;
4995 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
4998 /********************************/
4999 /*** ATTACK POWER ***/
5000 /********************************/
5002 void Aura::HandleAuraModAttackPower(bool apply, bool Real)
5004 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5007 void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
5009 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
5010 return;
5012 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5015 void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
5017 //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
5018 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
5021 void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
5023 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
5024 return;
5026 //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
5027 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5030 void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
5032 // spells required only Real aura add/remove
5033 if(!Real)
5034 return;
5036 // Recalculate bonus
5037 if(m_target->GetTypeId() == TYPEID_PLAYER && !(m_target->getClassMask() & CLASSMASK_WAND_USERS))
5038 ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
5041 void Aura::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real)
5043 // spells required only Real aura add/remove
5044 if(!Real)
5045 return;
5047 // Recalculate bonus
5048 if(m_target->GetTypeId() == TYPEID_PLAYER)
5049 ((Player*)m_target)->UpdateAttackPowerAndDamage(false);
5052 /********************************/
5053 /*** DAMAGE BONUS ***/
5054 /********************************/
5055 void Aura::HandleModDamageDone(bool apply, bool Real)
5057 // apply item specific bonuses for already equipped weapon
5058 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5060 for(int i = 0; i < MAX_ATTACK; ++i)
5061 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5062 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5065 // m_modifier.m_miscvalue is bitmask of spell schools
5066 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5067 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
5068 // 127 - full bitmask any damages
5070 // mods must be applied base at equipped weapon class and subclass comparison
5071 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5072 // m_modifier.m_miscvalue comparison with item generated damage types
5074 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5076 // apply generic physical damage bonuses including wand case
5077 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5079 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5080 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5081 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5083 else
5085 // done in Player::_ApplyWeaponDependentAuraMods
5088 if(m_target->GetTypeId() == TYPEID_PLAYER)
5090 if(m_positive)
5091 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
5092 else
5093 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
5097 // Skip non magic case for speedup
5098 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5099 return;
5101 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5103 // wand magic case (skip generic to all item spell bonuses)
5104 // done in Player::_ApplyWeaponDependentAuraMods
5106 // Skip item specific requirements for not wand magic damage
5107 return;
5110 // Magic damage modifiers implemented in Unit::SpellDamageBonus
5111 // This information for client side use only
5112 if(m_target->GetTypeId() == TYPEID_PLAYER)
5114 if(m_positive)
5116 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5118 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5119 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
5122 else
5124 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5126 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5127 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
5130 Pet* pet = m_target->GetPet();
5131 if(pet)
5132 pet->UpdateAttackPowerAndDamage();
5136 void Aura::HandleModDamagePercentDone(bool apply, bool Real)
5138 sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
5140 // apply item specific bonuses for already equipped weapon
5141 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5143 for(int i = 0; i < MAX_ATTACK; ++i)
5144 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5145 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5148 // m_modifier.m_miscvalue is bitmask of spell schools
5149 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5150 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
5151 // 127 - full bitmask any damages
5153 // mods must be applied base at equipped weapon class and subclass comparison
5154 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5155 // m_modifier.m_miscvalue comparison with item generated damage types
5157 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5159 // apply generic physical damage bonuses including wand case
5160 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5162 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5163 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5164 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5166 else
5168 // done in Player::_ApplyWeaponDependentAuraMods
5170 // For show in client
5171 if(m_target->GetTypeId() == TYPEID_PLAYER)
5172 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
5175 // Skip non magic case for speedup
5176 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5177 return;
5179 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5181 // wand magic case (skip generic to all item spell bonuses)
5182 // done in Player::_ApplyWeaponDependentAuraMods
5184 // Skip item specific requirements for not wand magic damage
5185 return;
5188 // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
5189 // Send info to client
5190 if(m_target->GetTypeId() == TYPEID_PLAYER)
5191 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
5192 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
5195 void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
5197 // spells required only Real aura add/remove
5198 if(!Real)
5199 return;
5201 sLog.outDebug("AURA MOD OFFHAND DAMAGE");
5203 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5206 /********************************/
5207 /*** POWER COST ***/
5208 /********************************/
5210 void Aura::HandleModPowerCostPCT(bool apply, bool Real)
5212 // spells required only Real aura add/remove
5213 if(!Real)
5214 return;
5216 float amount = m_modifier.m_amount/100.0f;
5217 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5218 if(m_modifier.m_miscvalue & (1<<i))
5219 m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
5222 void Aura::HandleModPowerCost(bool apply, bool Real)
5224 // spells required only Real aura add/remove
5225 if(!Real)
5226 return;
5228 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5229 if(m_modifier.m_miscvalue & (1<<i))
5230 m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
5233 void Aura::HandleNoReagentUseAura(bool Apply, bool Real)
5235 // spells required only Real aura add/remove
5236 if(!Real)
5237 return;
5238 if(m_target->GetTypeId() != TYPEID_PLAYER)
5239 return;
5240 uint32 mask[3] = {0, 0, 0};
5241 Unit::AuraList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE);
5242 for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
5244 uint32 const *ptr = (*i)->getAuraSpellClassMask();
5245 mask[0]|=ptr[0];
5246 mask[1]|=ptr[1];
5247 mask[2]|=ptr[2];
5250 m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]);
5251 m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]);
5252 m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]);
5255 /*********************************************************/
5256 /*** OTHERS ***/
5257 /*********************************************************/
5259 void Aura::HandleShapeshiftBoosts(bool apply)
5261 uint32 spellId = 0;
5262 uint32 spellId2 = 0;
5263 uint32 HotWSpellId = 0;
5265 switch(GetModifier()->m_miscvalue)
5267 case FORM_CAT:
5268 spellId = 3025;
5269 HotWSpellId = 24900;
5270 break;
5271 case FORM_TREE:
5272 spellId = 5420;
5273 break;
5274 case FORM_TRAVEL:
5275 spellId = 5419;
5276 break;
5277 case FORM_AQUA:
5278 spellId = 5421;
5279 break;
5280 case FORM_BEAR:
5281 spellId = 1178;
5282 spellId2 = 21178;
5283 HotWSpellId = 24899;
5284 break;
5285 case FORM_DIREBEAR:
5286 spellId = 9635;
5287 spellId2 = 21178;
5288 HotWSpellId = 24899;
5289 break;
5290 case FORM_BATTLESTANCE:
5291 spellId = 21156;
5292 break;
5293 case FORM_DEFENSIVESTANCE:
5294 spellId = 7376;
5295 break;
5296 case FORM_BERSERKERSTANCE:
5297 spellId = 7381;
5298 break;
5299 case FORM_MOONKIN:
5300 spellId = 24905;
5301 // aura from effect trigger spell
5302 spellId2 = 24907;
5303 break;
5304 case FORM_FLIGHT:
5305 spellId = 33948;
5306 spellId2 = 34764;
5307 break;
5308 case FORM_FLIGHT_EPIC:
5309 spellId = 40122;
5310 spellId2 = 40121;
5311 break;
5312 case FORM_METAMORPHOSIS:
5313 spellId = 54817;
5314 spellId2 = 54879;
5315 break;
5316 case FORM_SPIRITOFREDEMPTION:
5317 spellId = 27792;
5318 spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
5319 break;
5320 case FORM_GHOSTWOLF:
5321 case FORM_AMBIENT:
5322 case FORM_GHOUL:
5323 case FORM_SHADOW:
5324 case FORM_STEALTH:
5325 case FORM_CREATURECAT:
5326 case FORM_CREATUREBEAR:
5327 spellId = 0;
5328 break;
5331 uint32 form = GetModifier()->m_miscvalue-1;
5333 if(apply)
5335 if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
5336 if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
5338 if(m_target->GetTypeId() == TYPEID_PLAYER)
5340 const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
5341 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
5343 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
5344 if(itr->first==spellId || itr->first==spellId2) continue;
5345 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
5346 if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
5347 if (spellInfo->Stances & (1<<form))
5348 m_target->CastSpell(m_target, itr->first, true, NULL, this);
5350 //LotP
5351 if (((Player*)m_target)->HasSpell(17007))
5353 SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
5354 if (spellInfo && spellInfo->Stances & (1<<form))
5355 m_target->CastSpell(m_target, 24932, true, NULL, this);
5357 // HotW
5358 if (HotWSpellId)
5360 Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
5361 for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
5363 if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
5365 int32 HotWMod = (*i)->GetModifier()->m_amount;
5366 if(GetModifier()->m_miscvalue == FORM_CAT)
5367 HotWMod /= 2;
5369 m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
5370 break;
5376 else
5378 m_target->RemoveAurasDueToSpell(spellId);
5379 m_target->RemoveAurasDueToSpell(spellId2);
5381 Unit::AuraMap& tAuras = m_target->GetAuras();
5382 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
5384 if (itr->second->IsRemovedOnShapeLost())
5386 m_target->RemoveAurasDueToSpell(itr->second->GetId());
5387 itr = tAuras.begin();
5389 else
5391 ++itr;
5396 /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
5397 m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
5400 void Aura::HandleAuraEmpathy(bool apply, bool Real)
5402 if(m_target->GetTypeId() != TYPEID_UNIT)
5403 return;
5405 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
5406 if(ci && ci->type == CREATURE_TYPE_BEAST)
5407 m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
5410 void Aura::HandleAuraUntrackable(bool apply, bool Real)
5412 if(apply)
5413 m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5414 else
5415 m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5418 void Aura::HandleAuraModPacify(bool apply, bool Real)
5420 if(m_target->GetTypeId() != TYPEID_PLAYER)
5421 return;
5423 if(apply)
5424 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5425 else
5426 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5429 void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
5431 HandleAuraModPacify(apply,Real);
5432 HandleAuraModSilence(apply,Real);
5435 void Aura::HandleAuraGhost(bool apply, bool Real)
5437 if(m_target->GetTypeId() != TYPEID_PLAYER)
5438 return;
5440 if(apply)
5442 m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5444 else
5446 m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5450 void Aura::HandleAuraAllowFlight(bool apply, bool Real)
5452 // all applied/removed only at real aura add/remove
5453 if(!Real)
5454 return;
5456 // allow fly
5457 WorldPacket data;
5458 if(apply)
5459 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
5460 else
5461 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
5462 data.append(m_target->GetPackGUID());
5463 data << uint32(0); // unk
5464 m_target->SendMessageToSet(&data, true);
5467 void Aura::HandleModRating(bool apply, bool Real)
5469 // spells required only Real aura add/remove
5470 if(!Real)
5471 return;
5473 if(m_target->GetTypeId() != TYPEID_PLAYER)
5474 return;
5476 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5477 if (m_modifier.m_miscvalue & (1 << rating))
5478 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
5481 void Aura::HandleModRatingFromStat(bool apply, bool Real)
5483 // spells required only Real aura add/remove
5484 if(!Real)
5485 return;
5487 if(m_target->GetTypeId() != TYPEID_PLAYER)
5488 return;
5489 // Just recalculate ratings
5490 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5491 if (m_modifier.m_miscvalue & (1 << rating))
5492 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply);
5495 void Aura::HandleForceMoveForward(bool apply, bool Real)
5497 if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
5498 return;
5499 if(apply)
5500 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5501 else
5502 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5505 void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real)
5507 if(m_target->GetTypeId() != TYPEID_PLAYER)
5508 return;
5510 ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
5511 ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
5514 void Aura::HandleModTargetResistance(bool apply, bool Real)
5516 // spells required only Real aura add/remove
5517 if(!Real)
5518 return;
5519 // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
5521 // show armor penetration
5522 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
5523 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
5525 // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
5526 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
5527 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
5530 void Aura::HandleShieldBlockValue(bool apply, bool Real)
5532 BaseModType modType = FLAT_MOD;
5533 if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
5534 modType = PCT_MOD;
5536 if(m_target->GetTypeId() == TYPEID_PLAYER)
5537 ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
5540 void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
5542 // spells required only Real aura add/remove
5543 if(!Real)
5544 return;
5546 if(m_target->GetTypeId() != TYPEID_PLAYER)
5547 return;
5549 Player *target = (Player*)m_target;
5551 // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
5552 // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
5553 if( !apply && m_duration==0 && target->GetComboTarget())
5554 if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
5555 target->AddComboPoints(unit, -m_modifier.m_amount);
5558 void Aura::HandleModUnattackable( bool Apply, bool Real )
5560 if(Real && Apply)
5561 m_target->CombatStop();
5563 m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
5566 void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
5568 // spells required only Real aura add/remove
5569 if(!Real)
5570 return;
5572 // prepare spirit state
5573 if(apply)
5575 if(m_target->GetTypeId()==TYPEID_PLAYER)
5577 // disable breath/etc timers
5578 ((Player*)m_target)->StopMirrorTimers();
5580 // set stand state (expected in this form)
5581 if(!m_target->IsStandState())
5582 m_target->SetStandState(PLAYER_STATE_NONE);
5585 m_target->SetHealth(1);
5587 // die at aura end
5588 else
5589 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
5592 void Aura::CleanupTriggeredSpells()
5594 uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
5595 if(!tSpellId)
5596 return;
5598 SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
5599 if(!tProto)
5600 return;
5602 if(GetSpellDuration(tProto) != -1)
5603 return;
5605 // needed for spell 43680, maybe others
5606 // TODO: is there a spell flag, which can solve this in a more sophisticated way?
5607 if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
5608 GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
5609 return;
5610 m_target->RemoveAurasDueToSpell(tSpellId);
5613 void Aura::HandleAuraPowerBurn(bool apply, bool Real)
5615 if (m_periodicTimer <= 0)
5616 m_periodicTimer += m_modifier.periodictime;
5618 m_isPeriodic = apply;
5621 void Aura::HandleSchoolAbsorb(bool apply, bool Real)
5623 if(!Real)
5624 return;
5626 // prevent double apply bonuses
5627 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
5629 if(Unit* caster = GetCaster())
5631 float DoneActualBenefit = 0.0f;
5632 switch(m_spellProto->SpellFamilyName)
5634 case SPELLFAMILY_PRIEST:
5635 if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
5637 //+30% from +healing bonus
5638 DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
5639 break;
5641 break;
5642 case SPELLFAMILY_MAGE:
5643 if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
5645 //frost ward, fire ward, ice barrier
5646 //+10% from +spd bonus
5647 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5648 break;
5650 break;
5651 case SPELLFAMILY_WARLOCK:
5652 if(m_spellProto->SpellFamilyFlags == 0x00)
5654 //shadow ward
5655 //+10% from +spd bonus
5656 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5657 break;
5659 break;
5660 default:
5661 break;
5664 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
5666 m_modifier.m_amount += (int32)DoneActualBenefit;
5671 void Aura::PeriodicTick()
5673 if(!m_target->isAlive())
5674 return;
5676 switch(m_modifier.m_auraname)
5678 case SPELL_AURA_PERIODIC_DAMAGE:
5679 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
5681 Unit *pCaster = GetCaster();
5682 if(!pCaster)
5683 return;
5685 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5686 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5687 return;
5689 // Check for immune (not use charges)
5690 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5691 return;
5693 // some auras remove at specific health level or more
5694 if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
5696 switch(GetId())
5698 case 43093: case 31956: case 38801:
5699 case 35321: case 38363: case 39215:
5700 if(m_target->GetHealth() == m_target->GetMaxHealth() )
5702 m_target->RemoveAurasDueToSpell(GetId());
5703 return;
5705 break;
5706 case 38772:
5708 uint32 percent =
5709 GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
5710 pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
5711 100;
5712 if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
5714 m_target->RemoveAurasDueToSpell(GetId());
5715 return;
5717 break;
5719 default:
5720 break;
5724 uint32 absorb=0;
5725 uint32 resist=0;
5726 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5728 // ignore non positive values (can be result apply spellmods to aura damage
5729 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5731 uint32 pdamage;
5733 if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
5735 pdamage = amount;
5737 // Calculate armor mitigation if it is a physical spell
5738 // But not for bleed mechanic spells
5739 if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
5740 GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
5742 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5743 cleanDamage.damage += pdamage - pdamageReductedArmor;
5744 pdamage = pdamageReductedArmor;
5747 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5749 // Curse of Agony damage-per-tick calculation
5750 if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
5752 // 1..4 ticks, 1/2 from normal tick damage
5753 if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
5754 pdamage = pdamage/2;
5755 // 9..12 ticks, 3/2 from normal tick damage
5756 else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
5757 pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
5758 // 5..8 ticks have normal tick damage
5761 else
5762 pdamage = uint32(m_target->GetMaxHealth()*amount/100);
5764 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5765 // Reduce dot damage from resilience for players
5766 if (m_target->GetTypeId()==TYPEID_PLAYER)
5767 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5769 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5771 sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5772 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5774 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5775 data.append(m_target->GetPackGUID());
5776 data.appendPackGUID(GetCasterGUID());
5777 data << uint32(GetId());
5778 data << uint32(1);
5779 data << uint32(m_modifier.m_auraname);
5780 data << (uint32)pdamage;
5781 data << uint32(0); // overkill
5782 data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
5783 data << (uint32)absorb;
5784 data << (uint32)resist;
5785 m_target->SendMessageToSet(&data,true);
5787 Unit* target = m_target; // aura can be deleted in DealDamage
5788 SpellEntry const* spellProto = GetSpellProto();
5790 // Set trigger flag
5791 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
5792 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
5793 pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
5794 if (pdamage)
5795 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
5796 pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5798 pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true);
5799 break;
5801 case SPELL_AURA_PERIODIC_LEECH:
5803 Unit *pCaster = GetCaster();
5804 if(!pCaster)
5805 return;
5807 if(!pCaster->isAlive())
5808 return;
5810 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5811 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5812 return;
5814 // Check for immune (not use charges)
5815 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5816 return;
5818 uint32 absorb=0;
5819 uint32 resist=0;
5820 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5822 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5824 //Calculate armor mitigation if it is a physical spell
5825 if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
5827 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5828 cleanDamage.damage += pdamage - pdamageReductedArmor;
5829 pdamage = pdamageReductedArmor;
5832 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5834 // talent Soul Siphon add bonus to Drain Life spells
5835 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
5837 // find talent max bonus percentage
5838 Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5839 for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
5841 if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
5843 if((*i)->GetEffIndex()!=1)
5845 sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
5846 break;
5849 // effect 1 m_amount
5850 int32 maxPercent = (*i)->GetModifier()->m_amount;
5851 // effect 0 m_amount
5852 int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
5854 // count affliction effects and calc additional damage in percentage
5855 int32 modPercent = 0;
5856 Unit::AuraMap const& victimAuras = m_target->GetAuras();
5857 for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
5859 Aura* aura = itr->second;
5860 if (aura->IsPositive())continue;
5861 SpellEntry const* m_spell = aura->GetSpellProto();
5862 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
5863 continue;
5865 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
5866 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
5868 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
5870 if(_spell_idx->second->skillId == SKILL_AFFLICTION)
5872 modPercent += stepPercent;
5873 if (modPercent >= maxPercent)
5875 modPercent = maxPercent;
5876 break;
5881 pdamage += (pdamage*modPercent/100);
5882 break;
5887 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5888 // Reduce dot damage from resilience for players
5889 if (m_target->GetTypeId()==TYPEID_PLAYER)
5890 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5892 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5894 if(m_target->GetHealth() < pdamage)
5895 pdamage = uint32(m_target->GetHealth());
5897 sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5898 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5900 pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
5903 Unit* target = m_target; // aura can be deleted in DealDamage
5904 SpellEntry const* spellProto = GetSpellProto();
5905 float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
5907 // Set trigger flag
5908 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
5909 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
5910 pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
5911 if (pdamage)
5912 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
5913 pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5914 int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false);
5916 if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
5918 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
5920 if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
5921 pCaster->m_currentSpells[i]->cancel();
5926 if(Player *modOwner = pCaster->GetSpellModOwner())
5927 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
5929 uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
5931 int32 gain = pCaster->ModifyHealth(heal);
5932 pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
5934 pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
5935 break;
5937 case SPELL_AURA_PERIODIC_HEAL:
5938 case SPELL_AURA_OBS_MOD_HEALTH:
5940 Unit *pCaster = GetCaster();
5941 if(!pCaster)
5942 return;
5944 // heal for caster damage (must be alive)
5945 if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive())
5946 return;
5948 // ignore non positive values (can be result apply spellmods to aura damage
5949 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5951 uint32 pdamage;
5953 if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
5954 pdamage = uint32(m_target->GetMaxHealth() * amount/100);
5955 else
5956 pdamage = amount;
5958 pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
5960 sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
5961 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5963 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5964 data.append(m_target->GetPackGUID());
5965 data.appendPackGUID(GetCasterGUID());
5966 data << uint32(GetId());
5967 data << uint32(1);
5968 data << uint32(m_modifier.m_auraname);
5969 data << (uint32)pdamage;
5970 data << uint32(0); // wotlk
5971 m_target->SendMessageToSet(&data,true);
5973 int32 gain = m_target->ModifyHealth(pdamage);
5975 // add HoTs to amount healed in bgs
5976 if( pCaster->GetTypeId() == TYPEID_PLAYER )
5977 if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
5978 bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
5980 //Do check before because m_modifier.auraName can be invalidate by DealDamage.
5981 bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
5983 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5985 Unit* target = m_target; // aura can be deleted in DealDamage
5986 SpellEntry const* spellProto = GetSpellProto();
5987 bool haveCastItem = GetCastItemGUID()!=0;
5989 // heal for caster damage
5990 if(m_target!=pCaster && spellProto->SpellVisual[0]==163)
5992 uint32 dmg = spellProto->manaPerSecond;
5993 if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
5995 pCaster->RemoveAurasDueToSpell(GetId());
5997 // finish current generic/channeling spells, don't affect autorepeat
5998 if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
6000 pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
6002 if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
6004 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
6005 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
6008 else
6010 pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
6012 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
6013 pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
6017 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HEAL;
6018 uint32 procVictim = 0;//ROC_FLAG_ON_TAKE_PERIODIC | PROC_FLAG_TAKEN_HEAL;
6019 // ignore item heals
6020 // if(procSpell && !haveCastItem)
6021 // pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
6022 break;
6024 case SPELL_AURA_PERIODIC_MANA_LEECH:
6026 Unit *pCaster = GetCaster();
6027 if(!pCaster)
6028 return;
6030 if(!pCaster->isAlive())
6031 return;
6033 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
6034 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
6035 return;
6037 // Check for immune (not use charges)
6038 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
6039 return;
6041 // ignore non positive values (can be result apply spellmods to aura damage
6042 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6044 sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
6045 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
6047 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
6048 break;
6050 Powers power = Powers(m_modifier.m_miscvalue);
6052 // power type might have changed between aura applying and tick (druid's shapeshift)
6053 if(m_target->getPowerType() != power)
6054 break;
6056 int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
6058 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
6059 if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
6060 drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
6062 m_target->ModifyPower(power, -drain_amount);
6064 float gain_multiplier = 0;
6066 if(pCaster->GetMaxPower(power) > 0)
6068 gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
6070 if(Player *modOwner = pCaster->GetSpellModOwner())
6071 modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
6074 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
6075 data.append(m_target->GetPackGUID());
6076 data.appendPackGUID(GetCasterGUID());
6077 data << uint32(GetId());
6078 data << uint32(1);
6079 data << uint32(m_modifier.m_auraname);
6080 data << (uint32)power; // power type
6081 data << (uint32)drain_amount;
6082 data << (float)gain_multiplier;
6083 m_target->SendMessageToSet(&data,true);
6085 int32 gain_amount = int32(drain_amount*gain_multiplier);
6087 if(gain_amount)
6089 int32 gain = pCaster->ModifyPower(power,gain_amount);
6090 m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
6092 break;
6094 case SPELL_AURA_PERIODIC_ENERGIZE:
6096 // ignore non positive values (can be result apply spellmods to aura damage
6097 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6099 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
6100 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
6102 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
6103 break;
6105 Powers power = Powers(m_modifier.m_miscvalue);
6107 if(m_target->GetMaxPower(power) == 0)
6108 break;
6110 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
6111 data.append(m_target->GetPackGUID());
6112 data.appendPackGUID(GetCasterGUID());
6113 data << uint32(GetId());
6114 data << uint32(1);
6115 data << uint32(m_modifier.m_auraname);
6116 data << (uint32)power; // power type
6117 data << (uint32)pdamage;
6118 m_target->SendMessageToSet(&data,true);
6120 int32 gain = m_target->ModifyPower(power,pdamage);
6122 if(Unit* pCaster = GetCaster())
6123 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
6124 break;
6126 case SPELL_AURA_OBS_MOD_MANA:
6128 // ignore non positive values (can be result apply spellmods to aura damage
6129 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6131 uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
6133 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
6134 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
6136 if(m_target->GetMaxPower(POWER_MANA) == 0)
6137 break;
6139 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
6140 data.append(m_target->GetPackGUID());
6141 data.appendPackGUID(GetCasterGUID());
6142 data << uint32(GetId());
6143 data << uint32(1);
6144 data << uint32(m_modifier.m_auraname);
6145 data << (uint32)0; // ?
6146 data << (uint32)pdamage;
6147 m_target->SendMessageToSet(&data,true);
6149 int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
6151 if(Unit* pCaster = GetCaster())
6152 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
6153 break;
6155 case SPELL_AURA_POWER_BURN_MANA:
6157 Unit *pCaster = GetCaster();
6158 if(!pCaster)
6159 return;
6161 // Check for immune (not use charges)
6162 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
6163 return;
6165 int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6167 Powers powerType = Powers(m_modifier.m_miscvalue);
6169 if(!m_target->isAlive() || m_target->getPowerType() != powerType)
6170 return;
6172 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
6173 if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
6174 pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
6176 uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
6178 gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
6180 SpellEntry const* spellProto = GetSpellProto();
6181 //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
6182 SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask);
6183 pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto);
6184 pCaster->SendSpellNonMeleeDamageLog(&damageInfo);
6186 // Set trigger flag
6187 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
6188 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
6189 uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE);
6190 if (damageInfo.damage)
6191 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
6193 pCaster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);
6195 pCaster->DealSpellDamage(&damageInfo, true);
6196 break;
6198 // Here tick dummy auras
6199 case SPELL_AURA_PERIODIC_DUMMY:
6201 PeriodicDummyTick();
6202 break;
6204 case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
6206 TriggerSpell();
6207 break;
6209 case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
6211 TriggerSpellWithValue();
6212 break;
6214 default:
6215 break;
6219 void Aura::PeriodicDummyTick()
6221 Unit *caster = GetCaster();
6222 SpellEntry const* spell = GetSpellProto();
6223 switch (spell->SpellFamilyName)
6225 case SPELLFAMILY_GENERIC:
6226 switch (spell->Id)
6228 // Drink
6229 case 430:
6230 case 431:
6231 case 432:
6232 case 1133:
6233 case 1135:
6234 case 1137:
6235 case 10250:
6236 case 22734:
6237 case 27089:
6238 case 34291:
6239 case 43706:
6240 case 46755:
6241 case 49472: // Drink Coffee
6242 case 61830:
6244 if (m_target->GetTypeId() != TYPEID_PLAYER)
6245 return;
6246 // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
6247 Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
6248 for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
6250 if ((*i)->GetId() == GetId())
6252 // Get tick number
6253 int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
6254 // Default case (not on arenas)
6255 if (tick == 0)
6257 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6258 ((Player*)m_target)->UpdateManaRegen();
6259 // Disable continue
6260 m_isPeriodic = false;
6262 return;
6263 //**********************************************
6264 // Code commended since arena patch not added
6265 // This feature uses only in arenas
6266 //**********************************************
6267 // Here need increase mana regen per tick (6 second rule)
6268 // on 0 tick - 0 (handled in 2 second)
6269 // on 1 tick - 166% (handled in 4 second)
6270 // on 2 tick - 133% (handled in 6 second)
6271 // Not need update after 3 tick
6273 if (tick > 3)
6274 return;
6275 // Apply bonus for 0 - 3 tick
6276 switch (tick)
6278 case 0: // 0%
6279 (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
6280 break;
6281 case 1: // 166%
6282 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
6283 break;
6284 case 2: // 133%
6285 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
6286 break;
6287 default: // 100% - normal regen
6288 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6289 break;
6291 ((Player*)m_target)->UpdateManaRegen();
6292 return;*/
6295 return;
6297 // Forsaken Skills
6298 case 7054:
6300 // Possibly need cast one of them (but
6301 // 7038 Forsaken Skill: Swords
6302 // 7039 Forsaken Skill: Axes
6303 // 7040 Forsaken Skill: Daggers
6304 // 7041 Forsaken Skill: Maces
6305 // 7042 Forsaken Skill: Staves
6306 // 7043 Forsaken Skill: Bows
6307 // 7044 Forsaken Skill: Guns
6308 // 7045 Forsaken Skill: 2H Axes
6309 // 7046 Forsaken Skill: 2H Maces
6310 // 7047 Forsaken Skill: 2H Swords
6311 // 7048 Forsaken Skill: Defense
6312 // 7049 Forsaken Skill: Fire
6313 // 7050 Forsaken Skill: Frost
6314 // 7051 Forsaken Skill: Holy
6315 // 7053 Forsaken Skill: Shadow
6316 return;
6318 // // Panda
6319 // case 19230: break;
6320 // // Gossip NPC Periodic - Talk
6321 // case 33208: break;
6322 // // Gossip NPC Periodic - Despawn
6323 // case 33209: break;
6325 // TODO: now its not periodic dummy - need move out from here
6326 // Aspect of the Viper
6327 case 34074:
6329 if (m_target->GetTypeId() != TYPEID_PLAYER)
6330 return;
6331 // Should be manauser
6332 if (m_target->getPowerType()!=POWER_MANA)
6333 return;
6334 if (!caster)
6335 return;
6336 // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
6337 int mana = m_target->GetPower(POWER_MANA);
6338 int max_mana = m_target->GetMaxPower(POWER_MANA);
6339 int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
6340 float regen_pct = 1.20f - 1.1f * mana / max_mana;
6341 if (regen_pct > 1.0f) regen_pct = 1.0f;
6342 else if (regen_pct < 0.2f) regen_pct = 0.2f;
6343 m_modifier.m_amount = int32 (base_regen * regen_pct);
6344 ((Player*)m_target)->UpdateManaRegen();
6345 return;
6347 // // Steal Weapon
6348 // case 36207: break;
6349 // // Simon Game START timer, (DND)
6350 // case 39993: break;
6351 // // Knockdown Fel Cannon: break; The Aggro Burst
6352 // case 40119: break;
6353 // // Old Mount Spell
6354 // case 40154: break;
6355 // // Magnetic Pull
6356 // case 40581: break;
6357 // // Ethereal Ring: break; The Bolt Burst
6358 // case 40801: break;
6359 // // Crystal Prison
6360 // case 40846: break;
6361 // // Copy Weapon
6362 // case 41054: break;
6363 // // Dementia
6364 // case 41404: break;
6365 // // Ethereal Ring Visual, Lightning Aura
6366 // case 41477: break;
6367 // // Ethereal Ring Visual, Lightning Aura (Fork)
6368 // case 41525: break;
6369 // // Ethereal Ring Visual, Lightning Jumper Aura
6370 // case 41567: break;
6371 // // No Man's Land
6372 // case 41955: break;
6373 // // Headless Horseman - Fire
6374 // case 42074: break;
6375 // // Headless Horseman - Visual - Large Fire
6376 // case 42075: break;
6377 // // Headless Horseman - Start Fire, Periodic Aura
6378 // case 42140: break;
6379 // // Ram Speed Boost
6380 // case 42152: break;
6381 // // Headless Horseman - Fires Out Victory Aura
6382 // case 42235: break;
6383 // // Pumpkin Life Cycle
6384 // case 42280: break;
6385 // // Brewfest Request Chick Chuck Mug Aura
6386 // case 42537: break;
6387 // // Squashling
6388 // case 42596: break;
6389 // // Headless Horseman Climax, Head: Periodic
6390 // case 42603: break;
6391 // // Fire Bomb
6392 // case 42621: break;
6393 // // Headless Horseman - Conflagrate, Periodic Aura
6394 // case 42637: break;
6395 // // Headless Horseman - Create Pumpkin Treats Aura
6396 // case 42774: break;
6397 // // Headless Horseman Climax - Summoning Rhyme Aura
6398 // case 42879: break;
6399 // // Tricky Treat
6400 // case 42919: break;
6401 // // Giddyup!
6402 // case 42924: break;
6403 // // Ram - Trot
6404 // case 42992: break;
6405 // // Ram - Canter
6406 // case 42993: break;
6407 // // Ram - Gallop
6408 // case 42994: break;
6409 // // Ram Level - Neutral
6410 // case 43310: break;
6411 // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
6412 // case 43884: break;
6413 // // Wretched!
6414 // case 43963: break;
6415 // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
6416 // case 44000: break;
6417 // // Energy Feedback
6418 // case 44328: break;
6419 // // Romantic Picnic
6420 // case 45102: break;
6421 // // Romantic Picnic
6422 // case 45123: break;
6423 // // Looking for Love
6424 // case 45124: break;
6425 // // Kite - Lightning Strike Kite Aura
6426 // case 45197: break;
6427 // // Rocket Chicken
6428 // case 45202: break;
6429 // // Copy Offhand Weapon
6430 // case 45205: break;
6431 // // Upper Deck - Kite - Lightning Periodic Aura
6432 // case 45207: break;
6433 // // Kite -Sky Lightning Strike Kite Aura
6434 // case 45251: break;
6435 // // Ribbon Pole Dancer Check Aura
6436 // case 45390: break;
6437 // // Holiday - Midsummer, Ribbon Pole Periodic Visual
6438 // case 45406: break;
6439 // // Parachute
6440 // case 45472: break;
6441 // // Alliance Flag, Extra Damage Debuff
6442 // case 45898: break;
6443 // // Horde Flag, Extra Damage Debuff
6444 // case 45899: break;
6445 // // Ahune - Summoning Rhyme Aura
6446 // case 45926: break;
6447 // // Ahune - Slippery Floor
6448 // case 45945: break;
6449 // // Ahune's Shield
6450 // case 45954: break;
6451 // // Nether Vapor Lightning
6452 // case 45960: break;
6453 // // Darkness
6454 // case 45996: break;
6455 // // Summon Blood Elves Periodic
6456 // case 46041: break;
6457 // // Transform Visual Missile Periodic
6458 // case 46205: break;
6459 // // Find Opening Beam End
6460 // case 46333: break;
6461 // // Ice Spear Control Aura
6462 // case 46371: break;
6463 // // Hailstone Chill
6464 // case 46458: break;
6465 // // Hailstone Chill, Internal
6466 // case 46465: break;
6467 // // Chill, Internal Shifter
6468 // case 46549: break;
6469 // // Summon Ice Spear Knockback Delayer
6470 // case 46878: break;
6471 // // Burninate Effect
6472 // case 47214: break;
6473 // // Fizzcrank Practice Parachute
6474 // case 47228: break;
6475 // // Send Mug Control Aura
6476 // case 47369: break;
6477 // // Direbrew's Disarm (precast)
6478 // case 47407: break;
6479 // // Mole Machine Port Schedule
6480 // case 47489: break;
6481 // case 47941: break; // Crystal Spike
6482 // case 48200: break; // Healer Aura
6483 // case 48630: break; // Summon Gauntlet Mobs Periodic
6484 // case 49313: break; // Proximity Mine Area Aura
6485 // // Mole Machine Portal Schedule
6486 // case 49466: break;
6487 // case 49555: break; // Corpse Explode
6488 // case 49592: break; // Temporal Rift
6489 // case 49957: break; // Cutting Laser
6490 // case 50085: break; // Slow Fall
6491 // // Listening to Music
6492 // case 50493: break;
6493 // // Love Rocket Barrage
6494 // case 50530: break;
6495 // Exist more after, need add later
6496 default:
6497 break;
6499 break;
6500 case SPELLFAMILY_MAGE:
6502 // Mirror Image
6503 // if (spell->Id == 55342)
6504 // return;
6505 break;
6507 case SPELLFAMILY_WARRIOR:
6509 // Armored to the Teeth
6510 if (spell->SpellIconID == 3516)
6512 // Increases your attack power by $s1 for every $s2 armor value you have.
6513 // Calculate AP bonus (from 1 efect of this spell)
6514 int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
6515 m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
6516 return;
6518 break;
6520 case SPELLFAMILY_DRUID:
6522 switch (spell->Id)
6524 // Frenzied Regeneration
6525 case 22842:
6527 // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
6528 // Should be manauser
6529 if (m_target->getPowerType()!=POWER_RAGE)
6530 return;
6531 uint32 rage = m_target->GetPower(POWER_RAGE);
6532 // Nothing todo
6533 if (rage == 0)
6534 return;
6535 int32 mod = (rage < 100) ? rage : 100;
6536 int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
6537 int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000;
6538 m_target->CastCustomSpell(m_target, 22845, &regen, 0, 0, true, 0, this);
6539 m_target->SetPower(POWER_RAGE, rage-mod);
6540 return;
6542 // Force of Nature
6543 case 33831:
6544 return;
6545 default:
6546 break;
6548 break;
6550 case SPELLFAMILY_ROGUE:
6552 // switch (spell->Id)
6553 // {
6554 // Master of Subtlety
6555 // case 31666: break;
6556 // Killing Spree
6557 // case 51690: break;
6558 // Overkill
6559 // case 58428: break;
6560 // default:
6561 // break;
6562 // }
6563 break;
6565 case SPELLFAMILY_HUNTER:
6567 // Explosive Shot
6568 if (spell->SpellFamilyFlags & 0x8000000000000000LL)
6570 if (!caster)
6571 return;
6572 // Skip 0 tick
6573 if (m_duration > m_modifier.periodictime)
6574 return;
6575 int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target);
6576 damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
6577 damage/=4;
6578 caster->CastCustomSpell(m_target, 56298, &damage, 0, 0, true, 0, this);
6579 return;
6581 switch (spell->Id)
6583 // Harpooner's Mark
6584 // case 40084:
6585 // return;
6586 // Feeding Frenzy Rank 1
6587 case 53511:
6588 if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
6589 m_target->CastSpell(m_target, 60096, true, 0, this);
6590 return;
6591 // Feeding Frenzy Rank 2
6592 case 53512:
6593 if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
6594 m_target->CastSpell(m_target, 60097, true, 0, this);
6595 return;
6596 default:
6597 break;
6599 break;
6601 case SPELLFAMILY_SHAMAN:
6603 // Astral Shift
6604 if (spell->Id == 52179)
6606 // Periodic need for remove visual on stun/fear/silence lost
6607 if (!(m_target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)))
6608 m_target->RemoveAurasDueToSpell(52179);
6609 return;
6611 break;
6613 case SPELLFAMILY_DEATHKNIGHT:
6615 // Death and Decay
6616 if (spell->SpellFamilyFlags & 0x0000000000000020LL)
6618 if (caster)
6619 caster->CastCustomSpell(m_target, 52212, &m_modifier.m_amount, NULL, NULL, true, 0, this);
6620 return;
6622 // Raise Dead
6623 // if (spell->SpellFamilyFlags & 0x0000000000001000LL)
6624 // return;
6625 // Chains of Ice
6626 if (spell->SpellFamilyFlags & 0x0000400000000000LL)
6628 // Get 0 effect aura
6629 Aura *slow = m_target->GetAura(GetId(), 0);
6630 if (slow)
6632 slow->ApplyModifier(false, true);
6633 Modifier *mod = slow->GetModifier();
6634 mod->m_amount+= m_modifier.m_amount;
6635 if (mod->m_amount > 0) mod->m_amount = 0;
6636 slow->ApplyModifier(true, true);
6638 return;
6640 // Summon Gargoyle
6641 // if (spell->SpellFamilyFlags & 0x0000008000000000LL)
6642 // return;
6643 // Death Rune Mastery
6644 // if (spell->SpellFamilyFlags & 0x0000000000004000LL)
6645 // return;
6646 // Bladed Armor
6647 if (spell->SpellIconID == 2653)
6649 // Increases your attack power by $s1 for every $s2 armor value you have.
6650 // Calculate AP bonus (from 1 efect of this spell)
6651 int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
6652 m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
6653 return;
6655 // Reaping
6656 // if (spell->SpellIconID == 22)
6657 // return;
6658 // Blood of the North
6659 // if (spell->SpellIconID == 30412)
6660 // return;
6661 break;
6663 default:
6664 break;
6668 void Aura::HandlePreventFleeing(bool apply, bool Real)
6670 if(!Real)
6671 return;
6673 Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
6674 if( !fearAuras.empty() )
6676 if (apply)
6677 m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
6678 else
6679 m_target->SetFeared(true);
6683 void Aura::HandleManaShield(bool apply, bool Real)
6685 if(!Real)
6686 return;
6688 // prevent double apply bonuses
6689 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
6691 if(Unit* caster = GetCaster())
6693 float DoneActualBenefit = 0.0f;
6694 switch(m_spellProto->SpellFamilyName)
6696 case SPELLFAMILY_MAGE:
6697 if(m_spellProto->SpellFamilyFlags & 0x8000)
6699 // Mana Shield
6700 // +50% from +spd bonus
6701 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
6702 break;
6704 break;
6705 default:
6706 break;
6709 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
6711 m_modifier.m_amount += (int32)DoneActualBenefit;
6716 void Aura::HandleArenaPreparation(bool apply, bool Real)
6718 if(!Real)
6719 return;
6721 if(apply)
6722 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6723 else
6724 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6727 void Aura::HandleAuraControlVehicle(bool apply, bool Real)
6729 if(!Real)
6730 return;
6732 if(m_target->GetTypeId() != TYPEID_PLAYER)
6733 return;
6735 if(Pet *pet = m_target->GetPet())
6736 pet->Remove(PET_SAVE_AS_CURRENT);
6738 WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
6739 ((Player*)m_target)->GetSession()->SendPacket(&data);
6742 void Aura::HandleAuraConvertRune(bool apply, bool Real)
6744 if(!Real)
6745 return;
6747 if(m_target->GetTypeId() != TYPEID_PLAYER)
6748 return;
6750 Player *plr = (Player*)m_target;
6752 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6753 return;
6755 // how to determine what rune need to be converted?
6756 for(uint32 i = 0; i < MAX_RUNES; ++i)
6758 if(apply)
6760 if(!plr->GetRuneCooldown(i))
6762 plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]);
6763 break;
6766 else
6768 if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex])
6770 plr->ConvertRune(i, plr->GetBaseRune(i));
6771 break;