Restore damage calc for some paladin seal after client switch
[getmangos.git] / src / game / SpellAuras.cpp
blob0f1856d3f905f335013904bee2b87cfb75b1d559
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::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete?
199 &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete?
200 &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
201 &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
202 &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK
203 &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
204 &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
205 &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
206 &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
207 &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL
208 &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
209 &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
210 &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
211 &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
212 &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
213 &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
214 &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
215 &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA
216 &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE
217 &Aura::HandleUnused, //164 useless, only one test spell
218 &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
219 &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
220 &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
221 &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
222 &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
223 &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell
224 &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
225 &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
226 &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
227 &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus
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::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT)
249 &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
250 &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
251 &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
252 &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
253 &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP
254 &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
255 &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
256 &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
257 &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
258 &Aura::HandleNULL, //205 vulnerable to school dmg?
259 &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED
260 &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
261 &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive)
262 &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS
263 &Aura::HandleNULL, //210 Commentator's Command
264 &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
265 &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
266 &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
267 &Aura::HandleNULL, //214 Tamed Pet Passive
268 &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
269 &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
270 &Aura::HandleUnused, //217 unused
271 &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
272 &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
273 &Aura::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::HandleNULL, //227 periodic trigger spell
281 &Aura::HandleNoImmediateEffect, //228 stealth detection
282 &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
283 &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
284 &Aura::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::HandleNULL, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT
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::HandleNULL, //267 some immunity?
321 &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
322 &Aura::HandleNULL, //269 ignore DR effects?
323 &Aura::HandleNULL, //270
324 &Aura::HandleNULL, //271 increase damage done?
325 &Aura::HandleNULL, //272 reduce spell cast time?
326 &Aura::HandleNULL, //273
327 &Aura::HandleNULL, //274 proc free shot?
328 &Aura::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_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target),
341 m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS),
342 m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false),
343 m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false),
344 m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
346 assert(target);
348 assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
350 m_spellProto = spellproto;
352 m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff];
354 m_isPassive = IsPassiveSpell(GetId());
355 m_positive = IsPositiveEffect(GetId(), m_effIndex);
357 m_applyTime = time(NULL);
359 int32 damage;
360 if(!caster)
362 m_caster_guid = target->GetGUID();
363 damage = m_currentBasePoints+1; // stored value-1
364 m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target);
366 else
368 m_caster_guid = caster->GetGUID();
370 damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target);
371 m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target);
373 if (!damage && castItem && castItem->GetItemSuffixFactor())
375 ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
376 if(item_rand_suffix)
378 for (int k=0; k<3; k++)
380 SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
381 if(pEnchant)
383 for (int t=0; t<3; t++)
384 if(pEnchant->spellid[t] == m_spellProto->Id)
386 damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 );
387 break;
391 if(damage)
392 break;
398 if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0)
399 m_permanent = true;
401 Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
403 if(!m_permanent && modOwner)
404 modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration);
406 m_duration = m_maxduration;
408 if(modOwner)
409 modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
411 sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage);
413 m_effIndex = eff;
414 SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
416 m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
418 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;
624 if(m_isTrigger)
625 TriggerSpell();
626 else
627 PeriodicTick();
632 void AreaAura::Update(uint32 diff)
634 // update for the caster of the aura
635 if(m_caster_guid == m_target->GetGUID())
637 Unit* caster = m_target;
639 if( !caster->hasUnitState(UNIT_STAT_ISOLATED) )
641 Unit* owner = caster->GetCharmerOrOwner();
642 if (!owner)
643 owner = caster;
644 std::list<Unit *> targets;
646 switch(m_areaAuraType)
648 case AREA_AURA_PARTY:
650 Group *pGroup = NULL;
652 if (owner->GetTypeId() == TYPEID_PLAYER)
653 pGroup = ((Player*)owner)->GetGroup();
655 if( pGroup)
657 uint8 subgroup = ((Player*)owner)->GetSubGroup();
658 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
660 Player* Target = itr->getSource();
661 if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target))
663 if(caster->IsWithinDistInMap(Target, m_radius))
664 targets.push_back(Target);
665 Pet *pet = Target->GetPet();
666 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
667 targets.push_back(pet);
671 else
673 // add owner
674 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
675 targets.push_back(owner);
676 // add caster's pet
677 Unit* pet = caster->GetPet();
678 if( pet && caster->IsWithinDistInMap(pet, m_radius))
679 targets.push_back(pet);
681 break;
683 case AREA_AURA_RAID:
685 Group *pGroup = NULL;
687 if (owner->GetTypeId() == TYPEID_PLAYER)
688 pGroup = ((Player*)owner)->GetGroup();
690 if( pGroup)
692 uint8 subgroup = ((Player*)owner)->GetSubGroup();
693 for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
695 Player* Target = itr->getSource();
696 if(Target && Target->isAlive() && caster->IsFriendlyTo(Target))
698 if(caster->IsWithinDistInMap(Target, m_radius))
699 targets.push_back(Target);
700 Pet *pet = Target->GetPet();
701 if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
702 targets.push_back(pet);
706 else
708 // add owner
709 if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
710 targets.push_back(owner);
711 // add caster's pet
712 Unit* pet = caster->GetPet();
713 if( pet && caster->IsWithinDistInMap(pet, m_radius))
714 targets.push_back(pet);
716 break;
718 case AREA_AURA_FRIEND:
720 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
721 Cell cell(p);
722 cell.data.Part.reserved = ALL_DISTRICT;
723 cell.SetNoCreate();
725 MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius);
726 MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
727 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
728 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
729 CellLock<GridReadGuard> cell_lock(cell, p);
730 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
731 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
732 break;
734 case AREA_AURA_ENEMY:
736 CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
737 Cell cell(p);
738 cell.data.Part.reserved = ALL_DISTRICT;
739 cell.SetNoCreate();
741 MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
742 MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);
743 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
744 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
745 CellLock<GridReadGuard> cell_lock(cell, p);
746 cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
747 cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
748 break;
750 case AREA_AURA_OWNER:
751 case AREA_AURA_PET:
753 if(owner != caster)
754 targets.push_back(owner);
755 break;
759 for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
761 if((*tIter)->HasAura(GetId(), m_effIndex))
762 continue;
764 if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
766 int32 actualBasePoints = m_currentBasePoints;
767 // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
768 if(actualSpellInfo != GetSpellProto())
769 actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
770 AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL);
771 (*tIter)->AddAura(aur);
775 Aura::Update(diff);
777 else // aura at non-caster
779 Unit * tmp_target = m_target;
780 Unit* caster = GetCaster();
781 uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
783 // WARNING: the aura may get deleted during the update
784 // DO NOT access its members after update!
785 Aura::Update(diff);
787 // remove aura if out-of-range from caster (after teleport for example)
788 // or caster is isolated or caster no longer has the aura
789 // or caster is (no longer) friendly
790 bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
791 if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
792 !caster->IsWithinDistInMap(tmp_target, m_radius) ||
793 !caster->HasAura(tmp_spellId, tmp_effIndex) ||
794 caster->IsFriendlyTo(tmp_target) != needFriendly
797 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
799 else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
801 // not check group if target == owner or target == pet
802 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
804 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
806 Group *pGroup = check ? check->GetGroup() : NULL;
807 if( pGroup )
809 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
810 if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
811 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
813 else
814 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
817 else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
819 // not check group if target == owner or target == pet
820 if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
822 Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
824 Group *pGroup = check ? check->GetGroup() : NULL;
825 if( pGroup )
827 Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
828 if(!checkTarget)
829 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
831 else
832 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
835 else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
837 if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
838 tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
843 void PersistentAreaAura::Update(uint32 diff)
845 bool remove = false;
847 // remove the aura if its caster or the dynamic object causing it was removed
848 // or if the target moves too far from the dynamic object
849 Unit *caster = GetCaster();
850 if (caster)
852 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
853 if (dynObj)
855 if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius()))
856 remove = true;
858 else
859 remove = true;
861 else
862 remove = true;
864 Unit *tmp_target = m_target;
865 uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
867 // WARNING: the aura may get deleted during the update
868 // DO NOT access its members after update!
869 Aura::Update(diff);
871 if(remove)
872 tmp_target->RemoveAura(tmp_id, tmp_index);
875 void Aura::ApplyModifier(bool apply, bool Real)
877 AuraType aura = m_modifier.m_auraname;
879 m_in_use = true;
880 if(aura<TOTAL_AURAS)
881 (*this.*AuraHandler [aura])(apply,Real);
882 m_in_use = false;
885 void Aura::_AddAura()
887 if (!GetId())
888 return;
889 if(!m_target)
890 return;
892 // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT
893 bool samespell = false;
894 bool secondaura = false;
895 uint8 slot = NULL_AURA_SLOT;
897 for(uint8 i = 0; i < 3; i++)
899 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
900 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
902 // allow use single slot only by auras from same caster
903 if(itr->second->GetCasterGUID()==GetCasterGUID())
905 samespell = true;
906 if (m_effIndex > itr->second->GetEffIndex())
907 secondaura = true;
908 slot = itr->second->GetAuraSlot();
909 break;
913 if(samespell)
914 break;
917 // not call total regen auras at adding
918 switch (m_modifier.m_auraname)
920 case SPELL_AURA_OBS_MOD_HEALTH:
921 case SPELL_AURA_OBS_MOD_MANA:
922 m_periodicTimer = m_modifier.periodictime;
923 break;
924 case SPELL_AURA_MOD_REGEN:
925 case SPELL_AURA_MOD_POWER_REGEN:
926 case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
927 m_periodicTimer = 5000;
928 break;
931 // register aura
932 if (getDiminishGroup() != DIMINISHING_NONE )
933 m_target->ApplyDiminishingAura(getDiminishGroup(),true);
935 Unit* caster = GetCaster();
937 // passive auras (except totem auras) do not get placed in the slots
938 // area auras with SPELL_AURA_NONE are not shown on target
939 if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
940 (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
942 if(!samespell) // new slot need
944 if(m_target->GetVisibleAurasCount() < MAX_AURAS)
946 Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras();
947 for(uint8 i = 0; i < MAX_AURAS; ++i)
949 Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i);
950 if(itr == visibleAuras->end())
952 slot = i;
953 break;
958 SetAuraSlot( slot );
960 // Not update fields for not first spell's aura, all data already in fields
961 if(!secondaura)
963 if(slot < MAX_AURAS) // slot found
965 SetAura(false);
966 SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE));
967 SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
968 SendAuraUpdate(false);
970 // update for out of range group members
971 m_target->UpdateAuraForGroup(slot);
975 else // use found slot
977 SetAuraSlot( slot );
978 // Not recalculate stack count for second aura of the same spell
979 if (!secondaura)
980 UpdateSlotCounterAndDuration(true);
983 // Update Seals information
984 if( IsSealSpell(GetSpellProto()) )
985 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
987 // Conflagrate aura state
988 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
989 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
991 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
992 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
994 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
999 void Aura::_RemoveAura()
1001 // Remove all triggered by aura spells vs unlimited duration
1002 // except same aura replace case
1003 if(m_removeMode!=AURA_REMOVE_BY_STACK)
1004 CleanupTriggeredSpells();
1006 Unit* caster = GetCaster();
1008 if(caster && IsPersistent())
1010 DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
1011 if (dynObj)
1012 dynObj->RemoveAffected(m_target);
1015 // unregister aura
1016 if (getDiminishGroup() != DIMINISHING_NONE )
1017 m_target->ApplyDiminishingAura(getDiminishGroup(),false);
1019 //passive auras do not get put in slots
1020 // Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
1021 //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
1022 // return;
1024 uint8 slot = GetAuraSlot();
1026 if(slot >= MAX_AURAS) // slot not set
1027 return;
1029 if(m_target->GetVisibleAura(slot) == 0)
1030 return;
1032 bool samespell = false;
1033 bool sameaura = false;
1035 // find other aura in same slot (current already removed from list)
1036 for(uint8 i = 0; i < 3; i++)
1038 Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
1039 for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
1041 if(itr->second->GetAuraSlot()==slot)
1043 samespell = true;
1045 if(GetEffIndex()==i)
1046 sameaura = true;
1048 break;
1051 if(samespell)
1052 break;
1055 // only remove icon when the last aura of the spell is removed (current aura already removed from list)
1056 if (!samespell)
1058 SetAura(true);
1059 SetAuraFlags(AFLAG_NONE);
1060 SetAuraLevel(0);
1061 SetAuraCharges(0);
1062 SendAuraUpdate(true);
1064 // update for out of range group members
1065 m_target->UpdateAuraForGroup(slot);
1067 if( IsSealSpell(GetSpellProto()) )
1068 m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
1070 // Conflagrate aura state
1071 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
1072 m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false);
1074 // Swiftmend aura state
1075 if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1076 && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
1078 bool found = false;
1079 Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
1080 for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
1082 if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
1083 && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
1085 found = true;
1086 break;
1089 if(!found)
1090 m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false);
1093 // reset cooldown state for spells
1094 if(caster && caster->GetTypeId() == TYPEID_PLAYER)
1096 if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
1097 ((Player*)caster)->SendCooldownEvent(GetSpellProto());
1100 else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove process.
1101 UpdateSlotCounterAndDuration(false);
1104 void Aura::SendAuraUpdate(bool remove)
1106 WorldPacket data(SMSG_AURA_UPDATE);
1107 data.append(m_target->GetPackGUID());
1108 data << uint8(GetAuraSlot());
1109 data << uint32(remove ? 0 : GetId());
1111 if(remove)
1113 m_target->SendMessageToSet(&data, true);
1114 return;
1117 uint8 auraFlags = GetAuraFlags();
1118 data << uint8(auraFlags);
1119 data << uint8(GetAuraLevel());
1120 data << uint8(GetAuraCharges());
1122 if(!(auraFlags & AFLAG_NOT_CASTER))
1124 data << uint8(0); // pguid
1127 if(auraFlags & AFLAG_DURATION)
1129 data << uint32(GetAuraMaxDuration());
1130 data << uint32(GetAuraDuration());
1133 m_target->SendMessageToSet(&data, true);
1136 void Aura::UpdateSlotCounterAndDuration(bool add)
1138 uint8 slot = GetAuraSlot();
1139 if(slot >= MAX_AURAS)
1140 return;
1142 // calculate amount of similar auras by same effect index (similar different spells)
1143 int8 count = 0;
1145 // calculate auras and update durations in case aura adding
1146 Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname);
1147 for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i)
1149 if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex &&
1150 (*i)->GetCasterGUID()==GetCasterGUID() )
1152 ++count;
1154 if(add)
1155 (*i)->SetAuraDuration(GetAuraDuration());
1159 // at aura add aura not added yet, at aura remove aura already removed
1160 // in field stored (count-1)
1161 if(!add)
1162 --count;
1164 SetAuraCharges(count);
1165 SendAuraUpdate(false);
1168 bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
1170 // Check family name
1171 if (spell->SpellFamilyName != m_spellProto->SpellFamilyName)
1172 return false;
1173 // Check EffectClassMask
1174 uint32 const *ptr = getAuraSpellClassMask();
1175 if (((uint64*)ptr)[0] & spell->SpellFamilyFlags)
1176 return true;
1177 if (ptr[2] & spell->SpellFamilyFlags2)
1178 return true;
1179 return false;
1182 /*********************************************************/
1183 /*** BASIC AURA FUNCTION ***/
1184 /*********************************************************/
1185 void Aura::HandleAddModifier(bool apply, bool Real)
1187 if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
1188 return;
1190 if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
1191 return;
1193 if (apply)
1195 // Add custom charges for some mod aura
1196 switch (m_spellProto->Id)
1198 case 17941: // Shadow Trance
1199 case 22008: // Netherwind Focus
1200 case 31834: // Light's Grace
1201 case 34754: // Clearcasting
1202 case 34936: // Backlash
1203 case 48108: // Hot Streak
1204 SetAuraCharges(1);
1205 break;
1208 SpellModifier *mod = new SpellModifier;
1209 mod->op = SpellModOp(m_modifier.m_miscvalue);
1210 mod->value = m_modifier.m_amount;
1211 mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
1212 mod->spellId = GetId();
1214 uint32 const *ptr;
1215 SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
1216 if (spellAffect)
1217 ptr = &spellAffect->SpellClassMask[0];
1218 else
1220 switch (m_effIndex)
1222 case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break;
1223 case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break;
1224 case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break;
1225 default:
1226 return;
1230 mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
1231 mod->mask2= (uint64)ptr[2];
1232 mod->charges = m_procCharges;
1234 m_spellmod = mod;
1237 uint64 spellFamilyMask = m_spellmod->mask;
1239 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
1241 // reapply some passive spells after add/remove related spellmods
1242 if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
1244 m_target->RemoveAurasDueToSpell(45471);
1246 if(apply)
1247 m_target->CastSpell(m_target,45471,true);
1250 void Aura::HandleAddTargetTrigger(bool apply, bool Real)
1252 // Use SpellModifier structure for check
1253 // used only fields:
1254 // spellId, mask, mask2
1255 if (apply)
1257 SpellModifier *mod = new SpellModifier;
1258 mod->spellId = GetId();
1260 uint32 const *ptr;
1261 SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
1262 if (spellAffect)
1263 ptr = &spellAffect->SpellClassMask[0];
1264 else
1266 switch (m_effIndex)
1268 case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break;
1269 case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break;
1270 case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break;
1271 default:
1272 return;
1276 mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
1277 mod->mask2= (uint64)ptr[2];
1278 m_spellmod = mod;
1280 else
1282 delete m_spellmod;
1283 m_spellmod = NULL;
1286 void Aura::TriggerSpell()
1288 Unit* caster = GetCaster();
1289 Unit* target = GetTriggerTarget();
1291 if(!caster || !target)
1292 return;
1294 // generic casting code with custom spells and target/caster customs
1295 uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
1297 uint64 originalCasterGUID = GetCasterGUID();
1299 SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1300 SpellEntry const *auraSpellInfo = GetSpellProto();
1301 uint32 auraId = auraSpellInfo->Id;
1303 // specific code for cases with no trigger spell provided in field
1304 if (triggeredSpellInfo == NULL)
1306 switch(auraSpellInfo->SpellFamilyName)
1308 case SPELLFAMILY_GENERIC:
1310 switch(auraId)
1312 // Firestone Passive (1-5 ranks)
1313 case 758:
1314 case 17945:
1315 case 17947:
1316 case 17949:
1317 case 27252:
1319 if (caster->GetTypeId()!=TYPEID_PLAYER)
1320 return;
1321 Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
1322 if (!item)
1323 return;
1324 uint32 enchant_id = 0;
1325 switch (GetId())
1327 case 758: enchant_id = 1803; break; // Rank 1
1328 case 17945: enchant_id = 1823; break; // Rank 2
1329 case 17947: enchant_id = 1824; break; // Rank 3
1330 case 17949: enchant_id = 1825; break; // Rank 4
1331 case 27252: enchant_id = 2645; break; // Rank 5
1332 default:
1333 return;
1335 // remove old enchanting before applying new
1336 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1337 item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
1338 // add new enchanting
1339 ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
1340 return;
1342 // // Periodic Mana Burn
1343 // case 812: break;
1344 // // Polymorphic Ray
1345 // case 6965: break;
1346 // // Fire Nova (1-7 ranks)
1347 // case 8350:
1348 // case 8508:
1349 // case 8509:
1350 // case 11312:
1351 // case 11313:
1352 // case 25540:
1353 // case 25544:
1354 // break;
1355 // Thaumaturgy Channel
1356 case 9712: trigger_spell_id = 21029; break;
1357 // // Egan's Blaster
1358 // case 17368: break;
1359 // // Haunted
1360 // case 18347: break;
1361 // // Ranshalla Waiting
1362 // case 18953: break;
1363 // // Inferno
1364 // case 19695: break;
1365 // // Frostwolf Muzzle DND
1366 // case 21794: break;
1367 // // Alterac Ram Collar DND
1368 // case 21866: break;
1369 // // Celebras Waiting
1370 // case 21916: break;
1371 // Brood Affliction: Bronze
1372 case 23170:
1374 m_target->CastSpell(m_target, 23171, true, 0, this);
1375 return;
1377 // // Mark of Frost
1378 // case 23184: break;
1379 // Restoration
1380 case 23493:
1382 int32 heal = caster->GetMaxHealth() / 10;
1383 caster->ModifyHealth( heal );
1384 caster->SendHealSpellLog(caster, 23493, heal);
1386 int32 mana = caster->GetMaxPower(POWER_MANA);
1387 if (mana)
1389 mana /= 10;
1390 caster->ModifyPower( POWER_MANA, mana );
1391 caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
1393 break;
1395 // // Stoneclaw Totem Passive TEST
1396 // case 23792: break;
1397 // // Axe Flurry
1398 // case 24018: break;
1399 // // Mark of Arlokk
1400 // case 24210: break;
1401 // // Restoration
1402 // case 24379: break;
1403 // // Happy Pet
1404 // case 24716: break;
1405 // // Dream Fog
1406 // case 24780: break;
1407 // // Cannon Prep
1408 // case 24832: break;
1409 // // Shadow Bolt Whirl
1410 // case 24834: break;
1411 // // Stink Trap
1412 // case 24918: break;
1413 // // Mark of Nature
1414 // case 25041: break;
1415 // // Agro Drones
1416 // case 25152: break;
1417 // // Consume
1418 // case 25371: break;
1419 // // Pain Spike
1420 // case 25572: break;
1421 // // Rotate 360
1422 // case 26009: break;
1423 // // Rotate -360
1424 // case 26136: break;
1425 // // Consume
1426 // case 26196: break;
1427 // // Berserk
1428 // case 26615: break;
1429 // // Defile
1430 // case 27177: break;
1431 // // Teleport: IF/UC
1432 // case 27601: break;
1433 // // Five Fat Finger Exploding Heart Technique
1434 // case 27673: break;
1435 // // Nitrous Boost
1436 // case 27746: break;
1437 // // Steam Tank Passive
1438 // case 27747: break;
1439 // // Frost Blast
1440 // case 27808: break;
1441 // // Detonate Mana
1442 // case 27819: break;
1443 // // Controller Timer
1444 // case 28095: break;
1445 // // Stalagg Chain
1446 // case 28096: break;
1447 // // Stalagg Tesla Passive
1448 // case 28097: break;
1449 // // Feugen Tesla Passive
1450 // case 28109: break;
1451 // // Feugen Chain
1452 // case 28111: break;
1453 // // Mark of Didier
1454 // case 28114: break;
1455 // // Communique Timer, camp
1456 // case 28346: break;
1457 // // Icebolt
1458 // case 28522: break;
1459 // // Silithyst
1460 // case 29519: break;
1461 // // Inoculate Nestlewood Owlkin
1462 case 29528: trigger_spell_id = 28713; break;
1463 // // Overload
1464 // case 29768: break;
1465 // // Return Fire
1466 // case 29788: break;
1467 // // Return Fire
1468 // case 29793: break;
1469 // // Return Fire
1470 // case 29794: break;
1471 // // Guardian of Icecrown Passive
1472 // case 29897: break;
1473 // Feed Captured Animal
1474 case 29917: trigger_spell_id = 29916; break;
1475 // // Flame Wreath
1476 // case 29946: break;
1477 // // Flame Wreath
1478 // case 29947: break;
1479 // // Mind Exhaustion Passive
1480 // case 30025: break;
1481 // // Nether Beam - Serenity
1482 // case 30401: break;
1483 // Extract Gas
1484 case 30427:
1486 // move loot to player inventory and despawn target
1487 if(caster->GetTypeId() ==TYPEID_PLAYER &&
1488 target->GetTypeId() == TYPEID_UNIT &&
1489 ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
1491 Player* player = (Player*)caster;
1492 Creature* creature = (Creature*)target;
1493 // missing lootid has been reported on startup - just return
1494 if (!creature->GetCreatureInfo()->SkinLootId)
1496 return;
1498 Loot *loot = &creature->loot;
1499 loot->clear();
1500 loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL);
1501 for(uint8 i=0;i<loot->items.size();i++)
1503 LootItem *item = loot->LootItemInSlot(i,player);
1504 ItemPosCountVec dest;
1505 uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count );
1506 if ( msg == EQUIP_ERR_OK )
1508 Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId);
1510 player->SendNewItem(newitem, uint32(item->count), false, false, true);
1512 else
1513 player->SendEquipError( msg, NULL, NULL );
1515 creature->setDeathState(JUST_DIED);
1516 creature->RemoveCorpse();
1517 creature->SetHealth(0); // just for nice GM-mode view
1519 return;
1520 break;
1522 // Quake
1523 case 30576: trigger_spell_id = 30571; break;
1524 // // Burning Maul
1525 // case 30598: break;
1526 // // Regeneration
1527 // case 30799:
1528 // case 30800:
1529 // case 30801:
1530 // break;
1531 // // Despawn Self - Smoke cloud
1532 // case 31269: break;
1533 // // Time Rift Periodic
1534 // case 31320: break;
1535 // // Corrupt Medivh
1536 // case 31326: break;
1537 // Doom
1538 case 31347:
1540 m_target->CastSpell(m_target,31350,true);
1541 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
1542 return;
1544 // Spellcloth
1545 case 31373:
1547 // Summon Elemental after create item
1548 caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
1549 return;
1551 // // Bloodmyst Tesla
1552 // case 31611: break;
1553 // // Doomfire
1554 // case 31944: break;
1555 // // Teleport Test
1556 // case 32236: break;
1557 // // Earthquake
1558 // case 32686: break;
1559 // // Possess
1560 // case 33401: break;
1561 // // Draw Shadows
1562 // case 33563: break;
1563 // // Murmur's Touch
1564 // case 33711: break;
1565 // Flame Quills
1566 case 34229:
1568 // cast 24 spells 34269-34289, 34314-34316
1569 for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
1570 caster->CastSpell(m_target,spell_id,true);
1571 for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
1572 caster->CastSpell(m_target,spell_id,true);
1573 return;
1575 // // Gravity Lapse
1576 // case 34480: break;
1577 // // Tornado
1578 // case 34683: break;
1579 // // Frostbite Rotate
1580 // case 34748: break;
1581 // // Arcane Flurry
1582 // case 34821: break;
1583 // // Interrupt Shutdown
1584 // case 35016: break;
1585 // // Interrupt Shutdown
1586 // case 35176: break;
1587 // // Inferno
1588 // case 35268: break;
1589 // // Salaadin's Tesla
1590 // case 35515: break;
1591 // // Ethereal Channel (Red)
1592 // case 35518: break;
1593 // // Nether Vapor
1594 // case 35879: break;
1595 // // Dark Portal Storm
1596 // case 36018: break;
1597 // // Burning Maul
1598 // case 36056: break;
1599 // // Living Grove Defender Lifespan
1600 // case 36061: break;
1601 // // Professor Dabiri Talks
1602 // case 36064: break;
1603 // // Kael Gaining Power
1604 // case 36091: break;
1605 // // They Must Burn Bomb Aura
1606 // case 36344: break;
1607 // // They Must Burn Bomb Aura (self)
1608 // case 36350: break;
1609 // // Stolen Ravenous Ravager Egg
1610 // case 36401: break;
1611 // // Activated Cannon
1612 // case 36410: break;
1613 // // Stolen Ravenous Ravager Egg
1614 // case 36418: break;
1615 // // Enchanted Weapons
1616 // case 36510: break;
1617 // // Cursed Scarab Periodic
1618 // case 36556: break;
1619 // // Cursed Scarab Despawn Periodic
1620 // case 36561: break;
1621 // // Vision Guide
1622 // case 36573: break;
1623 // // Cannon Charging (platform)
1624 // case 36785: break;
1625 // // Cannon Charging (self)
1626 // case 36860: break;
1627 // Remote Toy
1628 case 37027: trigger_spell_id = 37029; break;
1629 // // Mark of Death
1630 // case 37125: break;
1631 // // Arcane Flurry
1632 // case 37268: break;
1633 // // Spout
1634 // case 37429: break;
1635 // // Spout
1636 // case 37430: break;
1637 // // Karazhan - Chess NPC AI, Snapshot timer
1638 // case 37440: break;
1639 // // Karazhan - Chess NPC AI, action timer
1640 // case 37504: break;
1641 // // Karazhan - Chess: Is Square OCCUPIED aura (DND)
1642 // case 39400: break;
1643 // // Banish
1644 // case 37546: break;
1645 // // Shriveling Gaze
1646 // case 37589: break;
1647 // // Fake Aggro Radius (2 yd)
1648 // case 37815: break;
1649 // // Corrupt Medivh
1650 // case 37853: break;
1651 // Eye of Grillok
1652 case 38495:
1654 m_target->CastSpell(m_target, 38530, true);
1655 return;
1657 // Absorb Eye of Grillok (Zezzak's Shard)
1658 case 38554:
1660 if(m_target->GetTypeId() != TYPEID_UNIT)
1661 return;
1663 caster->CastSpell(caster, 38495, true);
1665 Creature* creatureTarget = (Creature*)m_target;
1667 creatureTarget->setDeathState(JUST_DIED);
1668 creatureTarget->RemoveCorpse();
1669 creatureTarget->SetHealth(0); // just for nice GM-mode view
1670 return;
1672 // // Magic Sucker Device timer
1673 // case 38672: break;
1674 // // Tomb Guarding Charging
1675 // case 38751: break;
1676 // // Murmur's Touch
1677 // case 38794: break;
1678 // // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item)
1679 // case 39105: break;
1680 // // Drain World Tree Visual
1681 // case 39140: break;
1682 // // Quest - Dustin's Undead Dragon Visual aura
1683 // case 39259: break;
1684 // // Hellfire - The Exorcism, Jules releases darkness, aura
1685 // case 39306: break;
1686 // // Inferno
1687 // case 39346: break;
1688 // // Enchanted Weapons
1689 // case 39489: break;
1690 // // Shadow Bolt Whirl
1691 // case 39630: break;
1692 // // Shadow Bolt Whirl
1693 // case 39634: break;
1694 // // Shadow Inferno
1695 // case 39645: break;
1696 // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
1697 case 39857: trigger_spell_id = 39856; break;
1698 // // Soulgrinder Ritual Visual (Smashed)
1699 // case 39974: break;
1700 // // Simon Game Pre-game timer
1701 // case 40041: break;
1702 // // Knockdown Fel Cannon: The Aggro Check Aura
1703 // case 40113: break;
1704 // // Spirit Lance
1705 // case 40157: break;
1706 // // Demon Transform 2
1707 // case 40398: break;
1708 // // Demon Transform 1
1709 // case 40511: break;
1710 // // Ancient Flames
1711 // case 40657: break;
1712 // // Ethereal Ring Cannon: Cannon Aura
1713 // case 40734: break;
1714 // // Cage Trap
1715 // case 40760: break;
1716 // // Random Periodic
1717 // case 40867: break;
1718 // // Prismatic Shield
1719 // case 40879: break;
1720 // // Aura of Desire
1721 // case 41350: break;
1722 // // Dementia
1723 // case 41404: break;
1724 // // Chaos Form
1725 // case 41629: break;
1726 // // Alert Drums
1727 // case 42177: break;
1728 // // Spout
1729 // case 42581: break;
1730 // // Spout
1731 // case 42582: break;
1732 // // Return to the Spirit Realm
1733 // case 44035: break;
1734 // // Curse of Boundless Agony
1735 // case 45050: break;
1736 // // Earthquake
1737 // case 46240: break;
1738 // Personalized Weather
1739 case 46736: trigger_spell_id = 46737; break;
1740 // // Stay Submerged
1741 // case 46981: break;
1742 // // Dragonblight Ram
1743 // case 47015: break;
1744 // // Party G.R.E.N.A.D.E.
1745 // case 51510: break;
1746 default:
1747 break;
1749 break;
1751 case SPELLFAMILY_MAGE:
1753 switch(auraId)
1755 // Invisibility
1756 case 66:
1758 if(!m_duration)
1759 m_target->CastSpell(m_target, 32612, true, NULL, this);
1760 return;
1762 default:
1763 break;
1765 break;
1767 // case SPELLFAMILY_WARRIOR:
1768 // {
1769 // switch(auraId)
1770 // {
1771 // // Wild Magic
1772 // case 23410: break;
1773 // // Corrupted Totems
1774 // case 23425: break;
1775 // default:
1776 // break;
1777 // }
1778 // break;
1779 // }
1780 // case SPELLFAMILY_PRIEST:
1781 // {
1782 // switch(auraId)
1783 // {
1784 // // Blue Beam
1785 // case 32930: break;
1786 // // Fury of the Dreghood Elders
1787 // case 35460: break;
1788 // default:
1789 // break;
1790 // }
1791 // break;
1792 // }
1793 case SPELLFAMILY_DRUID:
1795 switch(auraId)
1797 // Cat Form
1798 // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while
1799 case 768:
1800 return;
1801 // Frenzied Regeneration
1802 case 22842:
1803 case 22895:
1804 case 22896:
1805 case 26999:
1807 int32 LifePerRage = GetModifier()->m_amount;
1809 int32 lRage = m_target->GetPower(POWER_RAGE);
1810 if(lRage > 100) // rage stored as rage*10
1811 lRage = 100;
1812 m_target->ModifyPower(POWER_RAGE, -lRage);
1813 int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10);
1814 m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this);
1815 return;
1817 default:
1818 break;
1820 break;
1823 // case SPELLFAMILY_HUNTER:
1824 // {
1825 // switch(auraId)
1826 // {
1827 // //Frost Trap Aura
1828 // case 13810:
1829 // return;
1830 // //Rizzle's Frost Trap
1831 // case 39900:
1832 // return;
1833 // // Tame spells
1834 // case 19597: // Tame Ice Claw Bear
1835 // case 19676: // Tame Snow Leopard
1836 // case 19677: // Tame Large Crag Boar
1837 // case 19678: // Tame Adult Plainstrider
1838 // case 19679: // Tame Prairie Stalker
1839 // case 19680: // Tame Swoop
1840 // case 19681: // Tame Dire Mottled Boar
1841 // case 19682: // Tame Surf Crawler
1842 // case 19683: // Tame Armored Scorpid
1843 // case 19684: // Tame Webwood Lurker
1844 // case 19685: // Tame Nightsaber Stalker
1845 // case 19686: // Tame Strigid Screecher
1846 // case 30100: // Tame Crazed Dragonhawk
1847 // case 30103: // Tame Elder Springpaw
1848 // case 30104: // Tame Mistbat
1849 // case 30647: // Tame Barbed Crawler
1850 // case 30648: // Tame Greater Timberstrider
1851 // case 30652: // Tame Nightstalker
1852 // return;
1853 // default:
1854 // break;
1855 // }
1856 // break;
1857 // }
1858 case SPELLFAMILY_SHAMAN:
1860 switch(auraId)
1862 // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
1863 case 28820:
1865 // Need remove self if Lightning Shield not active
1866 Unit::AuraMap const& auras = target->GetAuras();
1867 for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
1869 SpellEntry const* spell = itr->second->GetSpellProto();
1870 if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
1871 spell->SpellFamilyFlags & 0x0000000000000400L)
1872 return;
1874 target->RemoveAurasDueToSpell(28820);
1875 return;
1877 // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
1878 case 38443:
1880 bool all = true;
1881 for(int i = 0; i < MAX_TOTEM; ++i)
1883 if(!caster->m_TotemSlot[i])
1885 all = false;
1886 break;
1890 if(all)
1891 caster->CastSpell(caster,38437,true);
1892 else
1893 caster->RemoveAurasDueToSpell(38437);
1894 return;
1896 default:
1897 break;
1899 break;
1901 default:
1902 break;
1904 // Reget trigger spell proto
1905 triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
1906 if(triggeredSpellInfo == NULL)
1908 sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
1909 return;
1912 else
1914 // Spell exist but require custom code
1915 switch(auraId)
1917 // Curse of Idiocy
1918 case 1010:
1920 // TODO: spell casted by result in correct way mostly
1921 // BUT:
1922 // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell
1923 // but must show affect apply like item casting
1924 // 2) maybe aura must be replace by new with accumulative stat mods instead stacking
1926 // prevent cast by triggered auras
1927 if(m_caster_guid == m_target->GetGUID())
1928 return;
1930 // stop triggering after each affected stats lost > 90
1931 int32 intelectLoss = 0;
1932 int32 spiritLoss = 0;
1934 Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT);
1935 for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
1937 if ((*i)->GetId() == 1010)
1939 switch((*i)->GetModifier()->m_miscvalue)
1941 case STAT_INTELLECT: intelectLoss += (*i)->GetModifier()->m_amount; break;
1942 case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
1943 default: break;
1948 if(intelectLoss <= -90 && spiritLoss <= -90)
1949 return;
1951 caster = target;
1952 originalCasterGUID = 0;
1953 break;
1955 // Mana Tide
1956 case 16191:
1958 caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID);
1959 return;
1963 // All ok cast by default case
1964 Spell *spell = new Spell(caster, triggeredSpellInfo, true, originalCasterGUID );
1966 SpellCastTargets targets;
1967 targets.setUnitTarget( target );
1969 // if spell create dynamic object extract area from it
1970 if(DynamicObject* dynObj = caster->GetDynObject(GetId()))
1971 targets.setDestination(dynObj->GetPositionX(),dynObj->GetPositionY(),dynObj->GetPositionZ());
1973 spell->prepare(&targets, this);
1976 /*********************************************************/
1977 /*** AURA EFFECTS ***/
1978 /*********************************************************/
1980 void Aura::HandleAuraDummy(bool apply, bool Real)
1982 // spells required only Real aura add/remove
1983 if(!Real)
1984 return;
1986 Unit* caster = GetCaster();
1988 // AT APPLY
1989 if(apply)
1991 switch(GetId())
1993 case 1515: // Tame beast
1994 // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
1995 if( caster && m_target->CanHaveThreatList())
1996 m_target->AddThreat(caster, 10.0f);
1997 return;
1998 case 13139: // net-o-matic
1999 // root to self part of (root_target->charge->root_self sequence
2000 if(caster)
2001 caster->CastSpell(caster,13138,true,NULL,this);
2002 return;
2003 case 39850: // Rocket Blast
2004 if(roll_chance_i(20)) // backfire stun
2005 m_target->CastSpell(m_target, 51581, true, NULL, this);
2006 return;
2007 case 43873: // Headless Horseman Laugh
2008 if(caster->GetTypeId() == TYPEID_PLAYER)
2009 ((Player*)caster)->PlaySound(11965, false);
2010 return;
2011 case 46354: // Blood Elf Illusion
2012 if(caster)
2014 switch(caster->getGender())
2016 case GENDER_FEMALE:
2017 caster->CastSpell(m_target,46356,true,NULL,this);
2018 break;
2019 case GENDER_MALE:
2020 caster->CastSpell(m_target,46355,true,NULL,this);
2021 break;
2022 default:
2023 break;
2026 return;
2027 case 46699: // Requires No Ammo
2028 if(m_target->GetTypeId()==TYPEID_PLAYER)
2029 ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
2030 return;
2033 // Earth Shield
2034 if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
2036 // prevent double apply bonuses
2037 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2038 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2039 return;
2042 // AT REMOVE
2043 else
2045 if( m_target->GetTypeId() == TYPEID_PLAYER &&
2046 ( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
2047 ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
2049 // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
2050 ((Player*)m_target)->SetFarSight(NULL);
2051 WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
2052 ((Player*)m_target)->GetSession()->SendPacket(&data);
2053 return;
2056 if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive())
2058 uint32 finalSpelId = 0;
2059 switch(GetId())
2061 case 19548: finalSpelId = 19597; break;
2062 case 19674: finalSpelId = 19677; break;
2063 case 19687: finalSpelId = 19676; break;
2064 case 19688: finalSpelId = 19678; break;
2065 case 19689: finalSpelId = 19679; break;
2066 case 19692: finalSpelId = 19680; break;
2067 case 19693: finalSpelId = 19684; break;
2068 case 19694: finalSpelId = 19681; break;
2069 case 19696: finalSpelId = 19682; break;
2070 case 19697: finalSpelId = 19683; break;
2071 case 19699: finalSpelId = 19685; break;
2072 case 19700: finalSpelId = 19686; break;
2073 case 30646: finalSpelId = 30647; break;
2074 case 30653: finalSpelId = 30648; break;
2075 case 30654: finalSpelId = 30652; break;
2076 case 30099: finalSpelId = 30100; break;
2077 case 30102: finalSpelId = 30103; break;
2078 case 30105: finalSpelId = 30104; break;
2081 if(finalSpelId)
2082 caster->CastSpell(m_target,finalSpelId,true,NULL,this);
2083 return;
2086 // Waiting to Resurrect
2087 if(GetId()==2584)
2089 // Waiting to resurrect spell cancel, we must remove player from resurrect queue
2090 if(m_target->GetTypeId() == TYPEID_PLAYER)
2091 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
2092 bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
2093 return;
2096 // Dark Fiend
2097 if(GetId()==45934)
2099 // Kill target if dispelled
2100 if (m_removeMode==AURA_REMOVE_BY_DISPEL)
2101 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
2102 return;
2105 // Burning Winds
2106 if(GetId()==46308) // casted only at creatures at spawn
2108 m_target->CastSpell(m_target,47287,true,NULL,this);
2109 return;
2113 // AT APPLY & REMOVE
2115 switch(m_spellProto->SpellFamilyName)
2117 case SPELLFAMILY_GENERIC:
2119 // Unstable Power
2120 if( GetId()==24658 )
2122 uint32 spellId = 24659;
2123 if (apply)
2125 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2126 if (!spell)
2127 return;
2128 for (int i=0; i < spell->StackAmount; ++i)
2129 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2130 return;
2132 m_target->RemoveAurasDueToSpell(spellId);
2133 return;
2135 // Restless Strength
2136 if( GetId()==24661 )
2138 uint32 spellId = 24662;
2139 if (apply)
2141 const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
2142 if (!spell)
2143 return;
2144 for (int i=0; i < spell->StackAmount; ++i)
2145 caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
2146 return;
2148 m_target->RemoveAurasDueToSpell(spellId);
2149 return;
2151 // Victorious
2152 if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
2154 m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
2155 return;
2157 //Summon Fire Elemental
2158 if (GetId() == 40133 && caster)
2160 Unit *owner = caster->GetOwner();
2161 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2163 if(apply)
2164 owner->CastSpell(owner,8985,true);
2165 else
2166 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2168 return;
2171 //Summon Earth Elemental
2172 if (GetId() == 40132 && caster)
2174 Unit *owner = caster->GetOwner();
2175 if (owner && owner->GetTypeId() == TYPEID_PLAYER)
2177 if(apply)
2178 owner->CastSpell(owner,19704,true);
2179 else
2180 ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
2182 return;
2184 break;
2186 case SPELLFAMILY_MAGE:
2188 break;
2190 case SPELLFAMILY_DRUID:
2192 // Lifebloom
2193 if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
2195 if ( apply )
2197 if ( caster )
2198 // prevent double apply bonuses
2199 if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
2200 m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
2202 else
2204 // Final heal only on dispelled or duration end
2205 if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
2206 return;
2208 // have a look if there is still some other Lifebloom dummy aura
2209 Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2210 for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); ++itr)
2211 if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
2212 (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
2213 return;
2215 // final heal
2216 if(m_target->IsInWorld())
2217 m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
2219 return;
2222 // Predatory Strikes
2223 if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
2225 ((Player*)m_target)->UpdateAttackPowerAndDamage();
2226 return;
2228 // Idol of the Emerald Queen
2229 if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
2231 if(apply)
2233 SpellModifier *mod = new SpellModifier;
2234 mod->op = SPELLMOD_DOT;
2235 mod->value = m_modifier.m_amount/7;
2236 mod->type = SPELLMOD_FLAT;
2237 mod->spellId = GetId();
2238 mod->mask = 0x001000000000LL;
2239 mod->mask2= 0LL;
2241 m_spellmod = mod;
2244 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2245 return;
2247 break;
2249 case SPELLFAMILY_HUNTER:
2251 // Improved Aspect of the Viper
2252 if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
2254 if(apply)
2256 // + effect value for Aspect of the Viper
2257 SpellModifier *mod = new SpellModifier;
2258 mod->op = SPELLMOD_EFFECT1;
2259 mod->value = m_modifier.m_amount;
2260 mod->type = SPELLMOD_FLAT;
2261 mod->spellId = GetId();
2262 mod->mask = 0x4000000000000LL;
2263 mod->mask2= 0LL;
2265 m_spellmod = mod;
2268 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2269 return;
2271 break;
2273 case SPELLFAMILY_SHAMAN:
2275 // Improved Weapon Totems
2276 if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
2278 if(apply)
2280 SpellModifier *mod = new SpellModifier;
2281 mod->op = SPELLMOD_EFFECT1;
2282 mod->value = m_modifier.m_amount;
2283 mod->type = SPELLMOD_PCT;
2284 mod->spellId = GetId();
2285 switch (m_effIndex)
2287 case 0:
2288 mod->mask = 0x00200000000LL; // Windfury Totem
2289 mod->mask2= 0LL;
2290 break;
2291 case 1:
2292 mod->mask = 0x00400000000LL; // Flametongue Totem
2293 mod->mask2= 0LL;
2294 break;
2297 m_spellmod = mod;
2300 ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
2301 return;
2303 break;
2307 // pet auras
2308 if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
2310 if(apply)
2311 m_target->AddPetAura(petSpell);
2312 else
2313 m_target->RemovePetAura(petSpell);
2314 return;
2318 void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
2320 // spells required only Real aura add/remove
2321 if(!Real)
2322 return;
2324 Unit* caster = GetCaster();
2326 SpellEntry const*spell = GetSpellProto();
2327 switch( spell->SpellFamilyName)
2329 case SPELLFAMILY_ROGUE:
2331 // Master of Subtlety
2332 if (spell->Id==31666 && !apply && Real)
2334 m_target->RemoveAurasDueToSpell(31665);
2335 break;
2337 break;
2339 case SPELLFAMILY_HUNTER:
2341 // Aspect of the Viper
2342 if (spell->SpellFamilyFlags&0x0004000000000000LL)
2344 // Update regen on remove
2345 if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
2346 ((Player*)m_target)->UpdateManaRegen();
2347 break;
2349 // Explosive Shot
2350 if (spell->SpellFamilyFlags & 0x8000000000000000LL)
2352 if (apply && caster)
2354 int32 damage = m_modifier.m_amount + caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
2355 caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this);
2357 break;
2359 break;
2363 m_isPeriodic = apply;
2366 void Aura::HandleAuraMounted(bool apply, bool Real)
2368 // only at real add/remove aura
2369 if(!Real)
2370 return;
2372 if(apply)
2374 CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2375 if(!ci)
2377 sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
2378 return;
2381 uint32 team = 0;
2382 if (m_target->GetTypeId()==TYPEID_PLAYER)
2383 team = ((Player*)m_target)->GetTeam();
2385 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2386 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2387 if (minfo)
2388 display_id = minfo->modelid;
2390 m_target->Mount(display_id);
2392 else
2394 m_target->Unmount();
2398 void Aura::HandleAuraWaterWalk(bool apply, bool Real)
2400 // only at real add/remove aura
2401 if(!Real)
2402 return;
2404 WorldPacket data;
2405 if(apply)
2406 data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
2407 else
2408 data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
2409 data.append(m_target->GetPackGUID());
2410 data << uint32(0);
2411 m_target->SendMessageToSet(&data,true);
2414 void Aura::HandleAuraFeatherFall(bool apply, bool Real)
2416 // only at real add/remove aura
2417 if(!Real)
2418 return;
2420 WorldPacket data;
2421 if(apply)
2422 data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
2423 else
2424 data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
2425 data.append(m_target->GetPackGUID());
2426 data << (uint32)0;
2427 m_target->SendMessageToSet(&data,true);
2430 void Aura::HandleAuraHover(bool apply, bool Real)
2432 // only at real add/remove aura
2433 if(!Real)
2434 return;
2436 WorldPacket data;
2437 if(apply)
2438 data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
2439 else
2440 data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
2441 data.append(m_target->GetPackGUID());
2442 data << uint32(0);
2443 m_target->SendMessageToSet(&data,true);
2446 void Aura::HandleWaterBreathing(bool apply, bool Real)
2448 if(apply)
2449 m_target->waterbreath = true;
2450 else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
2452 m_target->waterbreath = false;
2454 // update for enable timer in case not moving target
2455 if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
2457 ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
2458 ((Player*)m_target)->HandleDrowning();
2463 void Aura::HandleAuraModShapeshift(bool apply, bool Real)
2465 if(!Real)
2466 return;
2468 uint32 modelid = 0;
2469 Powers PowerType = POWER_MANA;
2470 ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
2471 switch(form)
2473 case FORM_CAT:
2474 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2475 modelid = 892;
2476 else
2477 modelid = 8571;
2478 PowerType = POWER_ENERGY;
2479 break;
2480 case FORM_TRAVEL:
2481 modelid = 632;
2482 break;
2483 case FORM_AQUA:
2484 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2485 modelid = 2428;
2486 else
2487 modelid = 2428;
2488 break;
2489 case FORM_BEAR:
2490 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2491 modelid = 2281;
2492 else
2493 modelid = 2289;
2494 PowerType = POWER_RAGE;
2495 break;
2496 case FORM_GHOUL:
2497 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2498 modelid = 10045;
2499 break;
2500 case FORM_DIREBEAR:
2501 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2502 modelid = 2281;
2503 else
2504 modelid = 2289;
2505 PowerType = POWER_RAGE;
2506 break;
2507 case FORM_CREATUREBEAR:
2508 modelid = 902;
2509 break;
2510 case FORM_GHOSTWOLF:
2511 modelid = 4613;
2512 break;
2513 case FORM_FLIGHT:
2514 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2515 modelid = 20857;
2516 else
2517 modelid = 20872;
2518 break;
2519 case FORM_MOONKIN:
2520 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2521 modelid = 15374;
2522 else
2523 modelid = 15375;
2524 break;
2525 case FORM_FLIGHT_EPIC:
2526 if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
2527 modelid = 21243;
2528 else
2529 modelid = 21244;
2530 break;
2531 case FORM_METAMORPHOSIS:
2532 modelid = 25277;
2533 break;
2534 case FORM_AMBIENT:
2535 case FORM_SHADOW:
2536 case FORM_STEALTH:
2537 break;
2538 case FORM_TREE:
2539 modelid = 864;
2540 break;
2541 case FORM_BATTLESTANCE:
2542 case FORM_BERSERKERSTANCE:
2543 case FORM_DEFENSIVESTANCE:
2544 PowerType = POWER_RAGE;
2545 break;
2546 case FORM_SPIRITOFREDEMPTION:
2547 modelid = 16031;
2548 break;
2549 default:
2550 sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
2553 // remove polymorph before changing display id to keep new display id
2554 switch ( form )
2556 case FORM_CAT:
2557 case FORM_TREE:
2558 case FORM_TRAVEL:
2559 case FORM_AQUA:
2560 case FORM_BEAR:
2561 case FORM_DIREBEAR:
2562 case FORM_FLIGHT_EPIC:
2563 case FORM_FLIGHT:
2564 case FORM_MOONKIN:
2565 // remove movement affects
2566 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
2567 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
2569 // and polymorphic affects
2570 if(m_target->IsPolymorphed())
2571 m_target->RemoveAurasDueToSpell(m_target->getTransForm());
2572 break;
2573 default:
2574 break;
2577 if(apply)
2579 // remove other shapeshift before applying a new one
2580 if(m_target->m_ShapeShiftFormSpellId)
2581 m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
2583 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
2585 if(modelid > 0)
2586 m_target->SetDisplayId(modelid);
2588 if(PowerType != POWER_MANA)
2590 // reset power to default values only at power change
2591 if(m_target->getPowerType()!=PowerType)
2592 m_target->setPowerType(PowerType);
2594 switch(form)
2596 case FORM_CAT:
2597 case FORM_BEAR:
2598 case FORM_DIREBEAR:
2600 // get furor proc chance
2601 uint32 FurorChance = 0;
2602 Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
2603 for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
2605 if ((*i)->GetSpellProto()->SpellIconID == 238)
2607 FurorChance = (*i)->GetModifier()->m_amount;
2608 break;
2612 if (m_modifier.m_miscvalue == FORM_CAT)
2614 m_target->SetPower(POWER_ENERGY,0);
2615 if(urand(1,100) <= FurorChance)
2616 m_target->CastSpell(m_target,17099,true,NULL,this);
2618 else
2620 m_target->SetPower(POWER_RAGE,0);
2621 if(urand(1,100) <= FurorChance)
2622 m_target->CastSpell(m_target,17057,true,NULL,this);
2624 break;
2626 case FORM_BATTLESTANCE:
2627 case FORM_DEFENSIVESTANCE:
2628 case FORM_BERSERKERSTANCE:
2630 uint32 Rage_val = 0;
2631 // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
2632 if(m_target->GetTypeId() == TYPEID_PLAYER)
2634 PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
2635 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
2637 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
2638 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2639 if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
2640 Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
2644 if (m_target->GetPower(POWER_RAGE) > Rage_val)
2645 m_target->SetPower(POWER_RAGE,Rage_val);
2646 break;
2648 default:
2649 break;
2653 m_target->m_ShapeShiftFormSpellId = GetId();
2654 m_target->m_form = form;
2656 else
2658 if(modelid > 0)
2659 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2660 m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
2661 if(m_target->getClass() == CLASS_DRUID)
2662 m_target->setPowerType(POWER_MANA);
2663 m_target->m_ShapeShiftFormSpellId = 0;
2664 m_target->m_form = FORM_NONE;
2666 switch(form)
2668 // Nordrassil Harness - bonus
2669 case FORM_BEAR:
2670 case FORM_DIREBEAR:
2671 case FORM_CAT:
2673 if(Aura* dummy = m_target->GetDummyAura(37315) )
2674 m_target->CastSpell(m_target,37316,true,NULL,dummy);
2675 break;
2677 // Nordrassil Regalia - bonus
2678 case FORM_MOONKIN:
2680 if(Aura* dummy = m_target->GetDummyAura(37324) )
2681 m_target->CastSpell(m_target,37325,true,NULL,dummy);
2682 break;
2687 // adding/removing linked auras
2688 // add/remove the shapeshift aura's boosts
2689 HandleShapeshiftBoosts(apply);
2691 if(m_target->GetTypeId()==TYPEID_PLAYER)
2692 ((Player*)m_target)->InitDataForForm();
2695 void Aura::HandleAuraTransform(bool apply, bool Real)
2697 if (apply)
2699 // special case (spell specific functionality)
2700 if(m_modifier.m_miscvalue==0)
2702 // player applied only
2703 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2704 return;
2706 switch(GetId())
2708 // Orb of Deception
2709 case 16739:
2711 uint32 orb_model = m_target->GetNativeDisplayId();
2712 switch(orb_model)
2714 // Troll Female
2715 case 1479: m_target->SetDisplayId(10134); break;
2716 // Troll Male
2717 case 1478: m_target->SetDisplayId(10135); break;
2718 // Tauren Male
2719 case 59: m_target->SetDisplayId(10136); break;
2720 // Human Male
2721 case 49: m_target->SetDisplayId(10137); break;
2722 // Human Female
2723 case 50: m_target->SetDisplayId(10138); break;
2724 // Orc Male
2725 case 51: m_target->SetDisplayId(10139); break;
2726 // Orc Female
2727 case 52: m_target->SetDisplayId(10140); break;
2728 // Dwarf Male
2729 case 53: m_target->SetDisplayId(10141); break;
2730 // Dwarf Female
2731 case 54: m_target->SetDisplayId(10142); break;
2732 // NightElf Male
2733 case 55: m_target->SetDisplayId(10143); break;
2734 // NightElf Female
2735 case 56: m_target->SetDisplayId(10144); break;
2736 // Undead Female
2737 case 58: m_target->SetDisplayId(10145); break;
2738 // Undead Male
2739 case 57: m_target->SetDisplayId(10146); break;
2740 // Tauren Female
2741 case 60: m_target->SetDisplayId(10147); break;
2742 // Gnome Male
2743 case 1563: m_target->SetDisplayId(10148); break;
2744 // Gnome Female
2745 case 1564: m_target->SetDisplayId(10149); break;
2746 // BloodElf Female
2747 case 15475: m_target->SetDisplayId(17830); break;
2748 // BloodElf Male
2749 case 15476: m_target->SetDisplayId(17829); break;
2750 // Dranei Female
2751 case 16126: m_target->SetDisplayId(17828); break;
2752 // Dranei Male
2753 case 16125: m_target->SetDisplayId(17827); break;
2754 default: break;
2756 break;
2758 // Murloc costume
2759 case 42365: m_target->SetDisplayId(21723); break;
2760 default: break;
2763 else
2765 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
2766 if(!ci)
2768 //pig pink ^_^
2769 m_target->SetDisplayId(16358);
2770 sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
2772 else
2774 // Will use the default model here
2775 m_target->SetDisplayId(ci->DisplayID_A);
2777 // Dragonmaw Illusion (set mount model also)
2778 if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
2779 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
2781 m_target->setTransForm(GetId());
2784 // polymorph case
2785 if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
2787 // for players, start regeneration after 1s (in polymorph fast regeneration case)
2788 // only if caster is Player (after patch 2.4.2)
2789 if(IS_PLAYER_GUID(GetCasterGUID()) )
2790 ((Player*)m_target)->setRegenTimer(1000);
2792 //dismount polymorphed target (after patch 2.4.2)
2793 if (m_target->IsMounted())
2794 m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2797 else
2799 Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
2800 if(otherTransforms.empty())
2802 m_target->SetDisplayId(m_target->GetNativeDisplayId());
2803 m_target->setTransForm(0);
2805 else
2807 // look for other transform auras
2808 Aura* handledAura = *otherTransforms.begin();
2809 for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
2811 // negative auras are preferred
2812 if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
2814 handledAura = *i;
2815 break;
2818 handledAura->ApplyModifier(true);
2821 // Dragonmaw Illusion (restore mount model)
2822 if(GetId()==42016 && m_target->GetMountID()==16314)
2824 if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
2826 uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
2827 if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
2829 uint32 team = 0;
2830 if (m_target->GetTypeId()==TYPEID_PLAYER)
2831 team = ((Player*)m_target)->GetTeam();
2833 uint32 display_id = objmgr.ChooseDisplayId(team,ci);
2834 CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
2835 if (minfo)
2836 display_id = minfo->modelid;
2838 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
2845 void Aura::HandleForceReaction(bool apply, bool Real)
2847 if(m_target->GetTypeId() != TYPEID_PLAYER)
2848 return;
2850 if(!Real)
2851 return;
2853 Player* player = (Player*)m_target;
2855 uint32 faction_id = m_modifier.m_miscvalue;
2856 uint32 faction_rank = m_modifier.m_amount;
2858 if(apply)
2859 player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
2860 else
2861 player->m_forcedReactions.erase(faction_id);
2863 WorldPacket data;
2864 data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
2865 data << uint32(player->m_forcedReactions.size());
2866 for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
2868 data << uint32(itr->first); // faction_id (Faction.dbc)
2869 data << uint32(itr->second); // reputation rank
2871 player->SendDirectMessage(&data);
2874 void Aura::HandleAuraModSkill(bool apply, bool Real)
2876 if(m_target->GetTypeId() != TYPEID_PLAYER)
2877 return;
2879 uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
2880 int32 points = GetModifier()->m_amount;
2882 ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
2883 if(prot == SKILL_DEFENSE)
2884 ((Player*)m_target)->UpdateDefenseBonusesMod();
2887 void Aura::HandleChannelDeathItem(bool apply, bool Real)
2889 if(Real && !apply)
2891 Unit* caster = GetCaster();
2892 Unit* victim = GetTarget();
2893 if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
2894 return;
2896 SpellEntry const *spellInfo = GetSpellProto();
2897 if(spellInfo->EffectItemType[m_effIndex] == 0)
2898 return;
2900 // Soul Shard only from non-grey units
2901 if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
2902 (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
2903 victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
2904 return;
2905 ItemPosCountVec dest;
2906 uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
2907 if( msg != EQUIP_ERR_OK )
2909 ((Player*)caster)->SendEquipError( msg, NULL, NULL );
2910 return;
2913 Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
2914 ((Player*)caster)->SendNewItem(newitem, 1, true, false);
2918 void Aura::HandleBindSight(bool apply, bool Real)
2920 Unit* caster = GetCaster();
2921 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2922 return;
2924 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2927 void Aura::HandleFarSight(bool apply, bool Real)
2929 Unit* caster = GetCaster();
2930 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
2931 return;
2933 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
2936 void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
2938 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2939 return;
2941 if(apply)
2942 m_target->RemoveNoStackAurasDueToAura(this);
2943 m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
2946 void Aura::HandleAuraTrackResources(bool apply, bool Real)
2948 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2949 return;
2951 if(apply)
2952 m_target->RemoveNoStackAurasDueToAura(this);
2953 m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
2956 void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
2958 if(m_target->GetTypeId()!=TYPEID_PLAYER)
2959 return;
2961 if(apply)
2962 m_target->RemoveNoStackAurasDueToAura(this);
2964 m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
2967 void Aura::HandleAuraModScale(bool apply, bool Real)
2969 m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
2972 void Aura::HandleModPossess(bool apply, bool Real)
2974 if(!Real)
2975 return;
2977 if(m_target->getLevel() > m_modifier.m_amount)
2978 return;
2980 // not possess yourself
2981 if(GetCasterGUID() == m_target->GetGUID())
2982 return;
2984 Unit* caster = GetCaster();
2985 if(!caster)
2986 return;
2988 if( apply )
2990 m_target->SetCharmerGUID(GetCasterGUID());
2991 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
2992 caster->SetCharm(m_target);
2994 m_target->CombatStop();
2995 m_target->DeleteThreatList();
2996 if(m_target->GetTypeId() == TYPEID_UNIT)
2998 m_target->StopMoving();
2999 m_target->GetMotionMaster()->Clear();
3000 m_target->GetMotionMaster()->MoveIdle();
3001 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3002 charmInfo->InitPossessCreateSpells();
3005 if(caster->GetTypeId() == TYPEID_PLAYER)
3007 ((Player*)caster)->PossessSpellInitialize();
3010 else
3012 m_target->SetCharmerGUID(0);
3014 if(m_target->GetTypeId() == TYPEID_PLAYER)
3015 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3016 else if(m_target->GetTypeId() == TYPEID_UNIT)
3018 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3019 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3022 caster->SetCharm(0);
3024 if(caster->GetTypeId() == TYPEID_PLAYER)
3026 WorldPacket data(SMSG_PET_SPELLS, 8);
3027 data << uint64(0);
3028 data << uint32(0);
3029 ((Player*)caster)->GetSession()->SendPacket(&data);
3031 if(m_target->GetTypeId() == TYPEID_UNIT)
3033 ((Creature*)m_target)->AIM_Initialize();
3035 if (((Creature*)m_target)->AI())
3036 ((Creature*)m_target)->AI()->AttackStart(caster);
3039 if(caster->GetTypeId() == TYPEID_PLAYER)
3040 ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL);
3043 void Aura::HandleModPossessPet(bool apply, bool Real)
3045 if(!Real)
3046 return;
3048 Unit* caster = GetCaster();
3049 if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
3050 return;
3052 Pet *pet = caster->GetPet();
3053 if(!pet || pet != m_target)
3054 return;
3056 if(apply)
3057 pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
3058 else
3059 pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
3061 ((Player*)caster)->SetFarSight(apply ? pet->GetGUID() : NULL);
3062 ((Player*)caster)->SetCharm(apply ? pet : NULL);
3063 ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0);
3065 if(apply)
3067 pet->StopMoving();
3068 pet->GetMotionMaster()->Clear();
3069 pet->GetMotionMaster()->MoveIdle();
3071 else
3073 pet->AttackStop();
3074 pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
3075 pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
3079 void Aura::HandleModCharm(bool apply, bool Real)
3081 if(!Real)
3082 return;
3084 // not charm yourself
3085 if(GetCasterGUID() == m_target->GetGUID())
3086 return;
3088 Unit* caster = GetCaster();
3089 if(!caster)
3090 return;
3092 if(int32(m_target->getLevel()) <= m_modifier.m_amount)
3094 if( apply )
3096 m_target->SetCharmerGUID(GetCasterGUID());
3097 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
3098 m_target->CastStop(m_target==caster ? GetId() : 0);
3099 caster->SetCharm(m_target);
3101 m_target->CombatStop();
3102 m_target->DeleteThreatList();
3104 if(m_target->GetTypeId() == TYPEID_UNIT)
3106 ((Creature*)m_target)->AIM_Initialize();
3107 CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
3108 charmInfo->InitCharmCreateSpells();
3109 charmInfo->SetReactState( REACT_DEFENSIVE );
3111 if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
3113 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3114 if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
3116 //to prevent client crash
3117 m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
3118 //just to enable stat window
3119 charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
3120 //if charmed two demons the same session, the 2nd gets the 1st one's name
3121 m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
3126 if(caster->GetTypeId() == TYPEID_PLAYER)
3128 ((Player*)caster)->CharmSpellInitialize();
3131 else
3133 m_target->SetCharmerGUID(0);
3135 if(m_target->GetTypeId() == TYPEID_PLAYER)
3136 ((Player*)m_target)->setFactionForRace(m_target->getRace());
3137 else
3139 CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
3141 // restore faction
3142 if(((Creature*)m_target)->isPet())
3144 if(Unit* owner = m_target->GetOwner())
3145 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
3146 else if(cinfo)
3147 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3149 else if(cinfo) // normal creature
3150 m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
3152 // restore UNIT_FIELD_BYTES_0
3153 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
3155 CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
3156 if(cainfo && cainfo->bytes0 != 0)
3157 m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
3158 else
3159 m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
3161 if(m_target->GetCharmInfo())
3162 m_target->GetCharmInfo()->SetPetNumber(0, true);
3163 else
3164 sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
3168 caster->SetCharm(0);
3170 if(caster->GetTypeId() == TYPEID_PLAYER)
3172 WorldPacket data(SMSG_PET_SPELLS, 8);
3173 data << uint64(0);
3174 data << uint32(0);
3175 ((Player*)caster)->GetSession()->SendPacket(&data);
3177 if(m_target->GetTypeId() == TYPEID_UNIT)
3179 ((Creature*)m_target)->AIM_Initialize();
3180 if (((Creature*)m_target)->AI())
3181 ((Creature*)m_target)->AI()->AttackStart(caster);
3187 void Aura::HandleModConfuse(bool apply, bool Real)
3189 if(!Real)
3190 return;
3192 m_target->SetConfused(apply, GetCasterGUID(), GetId());
3195 void Aura::HandleModFear(bool apply, bool Real)
3197 if (!Real)
3198 return;
3200 m_target->SetFeared(apply, GetCasterGUID(), GetId());
3203 void Aura::HandleFeignDeath(bool apply, bool Real)
3205 if(!Real)
3206 return;
3208 if(m_target->GetTypeId() != TYPEID_PLAYER)
3209 return;
3211 if( apply )
3214 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3215 data<<m_target->GetGUID();
3216 data<<uint8(0);
3217 m_target->SendMessageToSet(&data,true);
3219 // blizz like 2.0.x
3220 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3221 // blizz like 2.0.x
3222 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3223 // blizz like 2.0.x
3224 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3226 m_target->addUnitState(UNIT_STAT_DIED);
3227 m_target->CombatStop();
3229 // prevent interrupt message
3230 if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
3231 m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
3232 m_target->InterruptNonMeleeSpells(true);
3233 m_target->getHostilRefManager().deleteReferences();
3235 else
3238 WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
3239 data<<m_target->GetGUID();
3240 data<<uint8(1);
3241 m_target->SendMessageToSet(&data,true);
3243 // blizz like 2.0.x
3244 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
3245 // blizz like 2.0.x
3246 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
3247 // blizz like 2.0.x
3248 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
3250 m_target->clearUnitState(UNIT_STAT_DIED);
3254 void Aura::HandleAuraModDisarm(bool apply, bool Real)
3256 if(!Real)
3257 return;
3259 if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
3260 return;
3262 // not sure for it's correctness
3263 if(apply)
3264 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3265 else
3266 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
3268 // only at real add/remove aura
3269 if (m_target->GetTypeId() != TYPEID_PLAYER)
3270 return;
3272 // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
3273 if (((Player *)m_target)->IsInFeralForm())
3274 return;
3276 if (apply)
3277 m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
3278 else
3279 ((Player *)m_target)->SetRegularAttackTime();
3281 m_target->UpdateDamagePhysical(BASE_ATTACK);
3284 void Aura::HandleAuraModStun(bool apply, bool Real)
3286 if(!Real)
3287 return;
3289 if (apply)
3291 m_target->addUnitState(UNIT_STAT_STUNNED);
3292 m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
3294 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3295 m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
3297 // Creature specific
3298 if(m_target->GetTypeId() != TYPEID_PLAYER)
3299 ((Creature*)m_target)->StopMoving();
3300 else
3301 m_target->SetUnitMovementFlags(0); //Clear movement flags
3303 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
3305 data.append(m_target->GetPackGUID());
3306 data << uint32(0);
3307 m_target->SendMessageToSet(&data,true);
3309 else
3311 // Real remove called after current aura remove from lists, check if other similar auras active
3312 if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
3313 return;
3315 m_target->clearUnitState(UNIT_STAT_STUNNED);
3316 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
3318 if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
3320 if(m_target->getVictim() && m_target->isAlive())
3321 m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3323 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
3324 data.append(m_target->GetPackGUID());
3325 data << uint32(0);
3326 m_target->SendMessageToSet(&data,true);
3329 // Wyvern Sting
3330 if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
3332 Unit* caster = GetCaster();
3333 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
3334 return;
3336 uint32 spell_id = 0;
3338 switch(GetId())
3340 case 19386: spell_id = 24131; break;
3341 case 24132: spell_id = 24134; break;
3342 case 24133: spell_id = 24135; break;
3343 case 27068: spell_id = 27069; break;
3344 default:
3345 sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
3346 return;
3349 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
3351 if(!spellInfo)
3352 return;
3354 caster->CastSpell(m_target,spellInfo,true,NULL,this);
3355 return;
3360 void Aura::HandleModStealth(bool apply, bool Real)
3362 if(apply)
3364 // drop flag at stealth in bg
3365 if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
3366 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3367 bg->EventPlayerDroppedFlag((Player*)m_target);
3369 // only at real aura add
3370 if(Real)
3372 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
3373 if(m_target->GetTypeId()==TYPEID_PLAYER)
3374 m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
3376 // apply only if not in GM invisibility (and overwrite invisibility state)
3377 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3379 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3380 m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
3383 // for RACE_NIGHTELF stealth
3384 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3385 m_target->CastSpell(m_target, 21009, true, NULL, this);
3388 else
3390 // only at real aura remove
3391 if(Real)
3393 // for RACE_NIGHTELF stealth
3394 if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
3395 m_target->RemoveAurasDueToSpell(21009);
3397 // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
3398 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
3400 m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
3401 if(m_target->GetTypeId()==TYPEID_PLAYER)
3402 m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
3404 // restore invisibility if any
3405 if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
3407 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3408 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3410 else
3411 m_target->SetVisibility(VISIBILITY_ON);
3416 // Master of Subtlety
3417 Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
3418 for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
3420 if ((*i)->GetSpellProto()->SpellIconID == 2114)
3422 if (apply)
3424 int32 bp = (*i)->GetModifier()->m_amount;
3425 m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
3427 else
3428 m_target->CastSpell(m_target,31666,true);
3429 break;
3434 void Aura::HandleInvisibility(bool apply, bool Real)
3436 if(apply)
3438 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3440 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3442 // apply glow vision
3443 m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3445 // drop flag at invisible in bg
3446 if(((Player*)m_target)->InBattleGround())
3447 if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
3448 bg->EventPlayerDroppedFlag((Player*)m_target);
3451 // apply only if not in GM invisibility and not stealth
3452 if(m_target->GetVisibility()==VISIBILITY_ON)
3454 // Aura not added yet but visibility code expect temporary add aura
3455 m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
3456 m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
3459 else
3461 // recalculate value at modifier remove (current aura already removed)
3462 m_target->m_invisibilityMask = 0;
3463 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
3464 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3465 m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
3467 // only at real aura remove and if not have different invisibility auras.
3468 if(Real && m_target->m_invisibilityMask==0)
3470 // remove glow vision
3471 if(m_target->GetTypeId() == TYPEID_PLAYER)
3472 m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
3474 // apply only if not in GM invisibility & not stealthed while invisible
3475 if(m_target->GetVisibility()!=VISIBILITY_OFF)
3477 // if have stealth aura then already have stealth visibility
3478 if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
3479 m_target->SetVisibility(VISIBILITY_ON);
3485 void Aura::HandleInvisibilityDetect(bool apply, bool Real)
3487 if(apply)
3489 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3491 else
3493 // recalculate value at modifier remove (current aura already removed)
3494 m_target->m_detectInvisibilityMask = 0;
3495 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
3496 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3497 m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
3499 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
3500 ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
3503 void Aura::HandleAuraModRoot(bool apply, bool Real)
3505 // only at real add/remove aura
3506 if(!Real)
3507 return;
3509 uint32 apply_stat = UNIT_STAT_ROOT;
3510 if (apply)
3512 m_target->addUnitState(UNIT_STAT_ROOT);
3513 m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
3514 // probably wrong
3515 m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3517 //Save last orientation
3518 if( m_target->getVictim() )
3519 m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
3521 if(m_target->GetTypeId() == TYPEID_PLAYER)
3523 WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
3524 data.append(m_target->GetPackGUID());
3525 data << (uint32)2;
3526 m_target->SendMessageToSet(&data,true);
3528 //Clear unit movement flags
3529 m_target->SetUnitMovementFlags(0);
3531 else
3532 ((Creature *)m_target)->StopMoving();
3534 else
3536 // Real remove called after current aura remove from lists, check if other similar auras active
3537 if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
3538 return;
3540 m_target->clearUnitState(UNIT_STAT_ROOT);
3541 // probably wrong
3542 m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
3544 if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
3546 if(m_target->getVictim() && m_target->isAlive())
3547 m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
3549 if(m_target->GetTypeId() == TYPEID_PLAYER)
3551 WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
3552 data.append(m_target->GetPackGUID());
3553 data << (uint32)2;
3554 m_target->SendMessageToSet(&data,true);
3560 void Aura::HandleAuraModSilence(bool apply, bool Real)
3562 // only at real add/remove aura
3563 if(!Real)
3564 return;
3566 if(apply)
3568 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3569 // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
3570 for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
3572 Spell* currentSpell = m_target->m_currentSpells[i];
3573 if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
3575 uint32 state = currentSpell->getState();
3576 // Stop spells on prepare or casting state
3577 if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
3579 currentSpell->cancel();
3580 currentSpell->SetReferencedFromCurrent(false);
3581 m_target->m_currentSpells[i] = NULL;
3586 switch (GetId())
3588 // Arcane Torrent (Energy)
3589 case 25046:
3591 Unit * caster = GetCaster();
3592 if (!caster)
3593 return;
3595 // Search Mana Tap auras on caster
3596 int32 energy = 0;
3597 Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
3598 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3599 if ((*i)->GetId() == 28734)
3600 ++energy;
3601 if (energy)
3603 energy *= 10;
3604 caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true);
3605 caster->RemoveAurasDueToSpell(28734);
3610 else
3612 // Real remove called after current aura remove from lists, check if other similar auras active
3613 if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
3614 return;
3616 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
3620 void Aura::HandleModThreat(bool apply, bool Real)
3622 // only at real add/remove aura
3623 if(!Real)
3624 return;
3626 if(!m_target->isAlive())
3627 return;
3629 Unit* caster = GetCaster();
3631 if(!caster || !caster->isAlive())
3632 return;
3634 int level_diff = 0;
3635 int multiplier = 0;
3636 switch (GetId())
3638 // Arcane Shroud
3639 case 26400:
3640 level_diff = m_target->getLevel() - 60;
3641 multiplier = 2;
3642 break;
3643 // The Eye of Diminution
3644 case 28862:
3645 level_diff = m_target->getLevel() - 60;
3646 multiplier = 1;
3647 break;
3649 if (level_diff > 0)
3650 m_modifier.m_amount += multiplier * level_diff;
3652 for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
3654 if(m_modifier.m_miscvalue & int32(1<<x))
3656 if(m_target->GetTypeId() == TYPEID_PLAYER)
3657 ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
3662 void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
3664 // only at real add/remove aura
3665 if(!Real)
3666 return;
3668 if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
3669 return;
3671 Unit* caster = GetCaster();
3673 if(!caster || !caster->isAlive())
3674 return;
3676 float threatMod = 0.0f;
3677 if(apply)
3678 threatMod = float(m_modifier.m_amount);
3679 else
3680 threatMod = float(-m_modifier.m_amount);
3682 m_target->getHostilRefManager().threatAssist(caster, threatMod);
3685 void Aura::HandleModTaunt(bool apply, bool Real)
3687 // only at real add/remove aura
3688 if(!Real)
3689 return;
3691 if(!m_target->isAlive() || !m_target->CanHaveThreatList())
3692 return;
3694 Unit* caster = GetCaster();
3696 if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
3697 return;
3699 if(apply)
3700 m_target->TauntApply(caster);
3701 else
3703 // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
3704 m_target->TauntFadeOut(caster);
3708 /*********************************************************/
3709 /*** MODIFY SPEED ***/
3710 /*********************************************************/
3711 void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real)
3713 // all applied/removed only at real aura add/remove
3714 if(!Real)
3715 return;
3717 m_target->UpdateSpeed(MOVE_RUN, true);
3720 void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real)
3722 // all applied/removed only at real aura add/remove
3723 if(!Real)
3724 return;
3726 m_target->UpdateSpeed(MOVE_RUN, true);
3729 void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
3731 // all applied/removed only at real aura add/remove
3732 if(!Real)
3733 return;
3735 // Enable Fly mode for flying mounts
3736 if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
3738 WorldPacket data;
3739 if(apply)
3740 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
3741 else
3742 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
3743 data.append(m_target->GetPackGUID());
3744 data << uint32(0); // unknown
3745 m_target->SendMessageToSet(&data, true);
3747 //Players on flying mounts must be immune to polymorph
3748 if (m_target->GetTypeId()==TYPEID_PLAYER)
3749 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
3751 // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
3752 if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
3753 m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
3756 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3759 void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
3761 // all applied/removed only at real aura add/remove
3762 if(!Real)
3763 return;
3765 m_target->UpdateSpeed(MOVE_SWIM, true);
3768 void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
3770 // all applied/removed only at real aura add/remove
3771 if(!Real)
3772 return;
3774 m_target->UpdateSpeed(MOVE_RUN, true);
3775 m_target->UpdateSpeed(MOVE_SWIM, true);
3776 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3779 void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
3781 // all applied/removed only at real aura add/remove
3782 if(!Real)
3783 return;
3785 m_target->UpdateSpeed(MOVE_RUN, true);
3786 m_target->UpdateSpeed(MOVE_SWIM, true);
3787 m_target->UpdateSpeed(MOVE_FLIGHT, true);
3790 /*********************************************************/
3791 /*** IMMUNITY ***/
3792 /*********************************************************/
3794 void Aura::HandleModMechanicImmunity(bool apply, bool Real)
3796 uint32 mechanic = 1 << m_modifier.m_miscvalue;
3798 //immune movement impairment and loss of control
3799 if(GetId()==42292)
3800 mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
3802 if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3804 Unit::AuraMap& Auras = m_target->GetAuras();
3805 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3807 next = iter;
3808 ++next;
3809 SpellEntry const *spell = iter->second->GetSpellProto();
3810 if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
3811 && !iter->second->IsPositive() // only remove negative spells
3812 && spell->Id != GetId())
3814 //check for mechanic mask
3815 if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
3817 m_target->RemoveAurasDueToSpell(spell->Id);
3818 if(Auras.empty())
3819 break;
3820 else
3821 next = Auras.begin();
3827 m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
3829 // Bestial Wrath
3830 if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
3832 // The Beast Within cast on owner if talent present
3833 if ( Unit* owner = m_target->GetOwner() )
3835 // Search talent
3836 Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
3837 for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
3839 if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
3841 if (apply)
3842 owner->CastSpell(owner, 34471, true, 0, this);
3843 else
3844 owner->RemoveAurasDueToSpell(34471);
3845 break;
3851 // The Beast Within and Bestial Wrath - immunity
3852 if(GetId() == 19574 || GetId() == 34471)
3854 if(apply)
3856 m_target->CastSpell(m_target,24395,true);
3857 m_target->CastSpell(m_target,24396,true);
3858 m_target->CastSpell(m_target,24397,true);
3859 m_target->CastSpell(m_target,26592,true);
3861 else
3863 m_target->RemoveAurasDueToSpell(24395);
3864 m_target->RemoveAurasDueToSpell(24396);
3865 m_target->RemoveAurasDueToSpell(24397);
3866 m_target->RemoveAurasDueToSpell(26592);
3871 void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
3873 if(!apply)
3875 if(m_target->GetTypeId() == TYPEID_PLAYER)
3877 if(((Player*)m_target)->InBattleGround())
3879 BattleGround *bg = ((Player*)m_target)->GetBattleGround();
3880 if(bg)
3882 switch(bg->GetTypeID())
3884 case BATTLEGROUND_AV:
3886 break;
3888 case BATTLEGROUND_WS:
3890 // Warsong Flag, horde // Silverwing Flag, alliance
3891 if(GetId() == 23333 || GetId() == 23335)
3892 bg->EventPlayerDroppedFlag(((Player*)m_target));
3893 break;
3895 case BATTLEGROUND_AB:
3897 break;
3899 case BATTLEGROUND_EY:
3901 if(GetId() == 34976)
3902 bg->EventPlayerDroppedFlag(((Player*)m_target));
3903 break;
3911 m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
3914 void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
3916 if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3918 Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
3919 for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
3921 if (auraList.front() != this) // skip itself aura (it already added)
3923 m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
3924 itr = auraList.begin();
3926 else
3927 ++itr;
3931 m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
3934 void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
3936 m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
3938 if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
3940 if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
3942 uint32 school_mask = m_modifier.m_miscvalue;
3943 Unit::AuraMap& Auras = m_target->GetAuras();
3944 for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
3946 next = iter;
3947 ++next;
3948 SpellEntry const *spell = iter->second->GetSpellProto();
3949 if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
3950 && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
3951 && !iter->second->IsPositive() //Don't remove positive spells
3952 && spell->Id != GetId() ) //Don't remove self
3954 m_target->RemoveAurasDueToSpell(spell->Id);
3955 if(Auras.empty())
3956 break;
3957 else
3958 next = Auras.begin();
3963 if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
3965 if( apply )
3966 m_target->addUnitState(UNIT_STAT_ISOLATED);
3967 else
3968 m_target->clearUnitState(UNIT_STAT_ISOLATED);
3972 void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
3974 m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
3977 void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
3979 // all applied/removed only at real aura add/remove
3980 if(!Real)
3981 return;
3983 m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
3986 void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
3988 if(!Real)
3989 return;
3991 if(apply)
3993 // some spell have charges by functionality not have its in spell data
3994 switch (GetId())
3996 case 28200: // Ascendance (Talisman of Ascendance trinket)
3997 SetAuraCharges(6);
3998 break;
3999 default: break;
4004 void Aura::HandleAuraModStalked(bool apply, bool Real)
4006 // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
4007 if(apply)
4008 m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
4009 else
4010 m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
4013 /*********************************************************/
4014 /*** PERIODIC ***/
4015 /*********************************************************/
4017 void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
4019 if (m_periodicTimer <= 0)
4020 m_periodicTimer += m_modifier.periodictime;
4022 m_isPeriodic = apply;
4023 m_isTrigger = apply;
4026 void Aura::HandlePeriodicEnergize(bool apply, bool Real)
4028 if (m_periodicTimer <= 0)
4029 m_periodicTimer += m_modifier.periodictime;
4031 m_isPeriodic = apply;
4034 void Aura::HandlePeriodicHeal(bool apply, bool Real)
4036 if (m_periodicTimer <= 0)
4037 m_periodicTimer += m_modifier.periodictime;
4039 m_isPeriodic = apply;
4041 // For prevent double apply bonuses
4042 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4044 if(!loading && apply)
4046 switch (m_spellProto->SpellFamilyName)
4048 case SPELLFAMILY_DRUID:
4050 // Rejuvenation
4051 if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
4053 if(Unit* caster = GetCaster())
4055 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4056 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4058 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4059 switch((*k)->GetModifier()->m_miscvalue)
4061 case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
4062 case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
4064 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4065 break;
4076 void Aura::HandlePeriodicDamage(bool apply, bool Real)
4078 // spells required only Real aura add/remove
4079 if(!Real)
4080 return;
4082 if (m_periodicTimer <= 0)
4083 m_periodicTimer += m_modifier.periodictime;
4085 m_isPeriodic = apply;
4087 // For prevent double apply bonuses
4088 bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
4090 Unit *caster = GetCaster();
4092 switch (m_spellProto->SpellFamilyName)
4094 case SPELLFAMILY_GENERIC:
4096 // Pounce Bleed
4097 if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 )
4099 // $AP*0.18/6 bonus per tick
4100 if (apply && !loading && caster)
4101 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4102 return;
4104 break;
4106 case SPELLFAMILY_WARRIOR:
4108 // Rend
4109 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4111 // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
4112 if (apply && !loading && caster)
4114 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4115 int32 mws = caster->GetAttackTime(BASE_ATTACK);
4116 float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
4117 float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
4118 // WARNING! in 3.0 multiplier 0.00743f change to 0.6
4119 m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
4121 return;
4123 break;
4125 case SPELLFAMILY_DRUID:
4127 // Rake
4128 if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
4130 // $AP*0.06/3 bonus per tick
4131 if (apply && !loading && caster)
4132 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
4133 return;
4135 // Lacerate
4136 if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
4138 // $AP*0.05/5 bonus per tick
4139 if (apply && !loading && caster)
4140 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
4141 return;
4143 // Rip
4144 if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
4146 // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used]
4147 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4149 uint8 cp = ((Player*)caster)->GetComboPoints();
4151 // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
4152 Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
4153 for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
4155 if((*itr)->GetId()==34241)
4157 m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
4158 break;
4162 if (cp > 4) cp = 4;
4163 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4165 return;
4167 break;
4169 case SPELLFAMILY_ROGUE:
4171 // Deadly poison aura state
4172 if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual[0]==5100)
4174 if(apply)
4175 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
4176 else
4178 // current aura already removed, search present of another
4179 bool found = false;
4180 Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
4181 for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
4183 SpellEntry const* itr_spell = (*itr)->GetSpellProto();
4184 if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual[0]==5100)
4186 found = true;
4187 break;
4190 // this has been last deadly poison aura
4191 if(!found)
4192 m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
4194 return;
4196 // Rupture
4197 if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
4199 // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP]
4200 if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
4202 uint8 cp = ((Player*)caster)->GetComboPoints();
4203 if (cp > 3) cp = 3;
4204 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
4206 return;
4208 // Garrote
4209 if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
4211 // $AP*0.18/6 bonus per tick
4212 if (apply && !loading && caster)
4213 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
4214 return;
4216 break;
4218 case SPELLFAMILY_HUNTER:
4220 // Serpent Sting
4221 if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
4223 // $RAP*0.1/5 bonus per tick
4224 if (apply && !loading && caster)
4225 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4226 return;
4228 // Immolation Trap
4229 if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
4231 // $RAP*0.1/5 bonus per tick
4232 if (apply && !loading && caster)
4233 m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
4234 return;
4236 break;
4238 case SPELLFAMILY_PALADIN:
4240 // Consecration
4241 if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
4243 if (apply && !loading && caster)
4245 Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4246 for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
4248 int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
4249 switch((*k)->GetModifier()->m_miscvalue)
4251 case 5147: // Improved Consecration - Libram of the Eternal Rest
4253 m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
4254 break;
4259 return;
4261 // Seal of Vengeance 0.013*$SPH+0.025*$AP per tick
4262 if(m_spellProto->SpellFamilyFlags & 0x0000080000000000LL)
4264 if (apply && !loading && caster)
4266 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
4267 int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) +
4268 caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target);
4269 m_modifier.m_amount += int32(ap * 0.025f) + int32(holy * 13 / 1000);
4271 return;
4273 break;
4275 default:
4276 break;
4280 void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
4282 if (m_periodicTimer <= 0)
4283 m_periodicTimer += m_modifier.periodictime;
4285 m_isPeriodic = apply;
4288 void Aura::HandlePeriodicLeech(bool apply, bool Real)
4290 if (m_periodicTimer <= 0)
4291 m_periodicTimer += m_modifier.periodictime;
4293 m_isPeriodic = apply;
4296 void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
4298 if (m_periodicTimer <= 0)
4299 m_periodicTimer += m_modifier.periodictime;
4301 m_isPeriodic = apply;
4304 /*********************************************************/
4305 /*** MODIFY STATS ***/
4306 /*********************************************************/
4308 /********************************/
4309 /*** RESISTANCE ***/
4310 /********************************/
4312 void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
4314 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4316 if(m_modifier.m_miscvalue & int32(1<<x))
4318 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
4319 if(m_target->GetTypeId() == TYPEID_PLAYER)
4320 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4325 void Aura::HandleAuraModResistance(bool apply, bool Real)
4327 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4329 if(m_modifier.m_miscvalue & int32(1<<x))
4331 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4332 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4333 m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
4337 // Faerie Fire (druid versions)
4338 if( m_spellProto->SpellIconID == 109 &&
4339 m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
4340 m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
4342 m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
4346 void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
4348 // only players have base stats
4349 if(m_target->GetTypeId() != TYPEID_PLAYER)
4351 //pets only have base armor
4352 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4353 m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
4355 else
4357 for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
4359 if(m_modifier.m_miscvalue & int32(1<<x))
4360 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
4365 void Aura::HandleModResistancePercent(bool apply, bool Real)
4367 for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4369 if(m_modifier.m_miscvalue & int32(1<<i))
4371 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4372 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4374 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
4375 m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
4381 void Aura::HandleModBaseResistance(bool apply, bool Real)
4383 // only players have base stats
4384 if(m_target->GetTypeId() != TYPEID_PLAYER)
4386 //only pets have base stats
4387 if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
4388 m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4390 else
4392 for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
4393 if(m_modifier.m_miscvalue & (1<<i))
4394 m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4398 /********************************/
4399 /*** STAT ***/
4400 /********************************/
4402 void Aura::HandleAuraModStat(bool apply, bool Real)
4404 if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
4406 sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
4407 return;
4410 for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4412 // -1 or -2 is all stats ( misc < -2 checked in function beginning )
4413 if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
4415 //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
4416 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
4417 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4418 m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
4423 void Aura::HandleModPercentStat(bool apply, bool Real)
4425 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4427 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4428 return;
4431 // only players have base stats
4432 if (m_target->GetTypeId() != TYPEID_PLAYER)
4433 return;
4435 for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
4437 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4438 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
4442 void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real)
4444 if(m_target->GetTypeId() != TYPEID_PLAYER)
4445 return;
4447 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4448 // This information for client side use only
4449 // Recalculate bonus
4450 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4453 void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real)
4455 if(m_target->GetTypeId() != TYPEID_PLAYER)
4456 return;
4458 // Recalculate bonus
4459 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4462 void Aura::HandleAuraModDispelResist(bool apply, bool Real)
4464 if(!Real || !apply)
4465 return;
4467 if(GetId()==33206)
4468 m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
4471 void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real)
4473 if(m_target->GetTypeId() != TYPEID_PLAYER)
4474 return;
4476 // Magic damage modifiers implemented in Unit::SpellDamageBonus
4477 // This information for client side use only
4478 // Recalculate bonus
4479 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4482 void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real)
4484 if(m_target->GetTypeId() != TYPEID_PLAYER)
4485 return;
4487 // Recalculate bonus
4488 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4491 void Aura::HandleModHealingDone(bool /*apply*/, bool Real)
4493 if(m_target->GetTypeId() != TYPEID_PLAYER)
4494 return;
4495 // implemented in Unit::SpellHealingBonus
4496 // this information is for client side only
4497 ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
4500 void Aura::HandleModTotalPercentStat(bool apply, bool Real)
4502 if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
4504 sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
4505 return;
4508 //save current and max HP before applying aura
4509 uint32 curHPValue = m_target->GetHealth();
4510 uint32 maxHPValue = m_target->GetMaxHealth();
4512 for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
4514 if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
4516 m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
4517 if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
4518 m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
4522 //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
4523 if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
4525 // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
4526 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
4527 m_target->SetHealth(newHPValue);
4531 void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
4533 if(m_target->GetTypeId() != TYPEID_PLAYER)
4534 return;
4536 if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
4538 // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
4539 // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
4540 sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
4541 return;
4544 // Recalculate Armor
4545 m_target->UpdateArmor();
4548 /********************************/
4549 /*** HEAL & ENERGIZE ***/
4550 /********************************/
4551 void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
4554 Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
4555 so this aura not fully working.
4557 if(apply)
4559 if(!m_target->isAlive())
4560 return;
4562 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4563 m_target->SetStandState(PLAYER_STATE_SIT);
4565 if(m_periodicTimer <= 0)
4567 m_periodicTimer += m_modifier.periodictime;
4569 if(m_target->GetHealth() < m_target->GetMaxHealth())
4571 // PeriodicTick can cast triggered spells with stats changes
4572 PeriodicTick();
4577 m_isPeriodic = apply;
4580 void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
4582 if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4583 m_target->SetStandState(PLAYER_STATE_SIT);
4584 if(apply)
4586 if(m_modifier.periodictime == 0)
4587 m_modifier.periodictime = 1000;
4588 if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
4590 m_periodicTimer += m_modifier.periodictime;
4592 if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
4594 // PeriodicTick can cast triggered spells with stats changes
4595 PeriodicTick();
4600 m_isPeriodic = apply;
4603 void Aura::HandleModRegen(bool apply, bool Real) // eating
4605 if(apply)
4607 if(!m_target->isAlive())
4608 return;
4610 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
4611 m_target->SetStandState(PLAYER_STATE_SIT);
4613 if(m_periodicTimer <= 0)
4615 m_periodicTimer += 5000;
4616 int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
4617 Unit *caster = GetCaster();
4618 if (caster)
4620 SpellEntry const *spellProto = GetSpellProto();
4621 if (spellProto)
4622 m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
4627 m_isPeriodic = apply;
4630 void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
4632 if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
4633 m_target->SetStandState(PLAYER_STATE_SIT);
4635 if(apply && m_periodicTimer <= 0)
4637 m_periodicTimer += 2000;
4639 Powers pt = m_target->getPowerType();
4640 if(int32(pt) != m_modifier.m_miscvalue)
4641 return;
4643 if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
4645 // eating anim
4646 m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
4648 else if( GetId() == 20577 )
4650 // cannibalize anim
4651 m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE);
4654 // Warrior talent, gain 1 rage every 3 seconds while in combat
4655 if(pt == POWER_RAGE && m_target->isInCombat())
4657 m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
4658 m_periodicTimer += 1000;
4661 m_isPeriodic = apply;
4662 if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
4663 ((Player*)m_target)->UpdateManaRegen();
4666 void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
4668 // spells required only Real aura add/remove
4669 if(!Real)
4670 return;
4672 if (m_target->GetTypeId() != TYPEID_PLAYER)
4673 return;
4675 // Update manaregen value
4676 if (m_modifier.m_miscvalue == POWER_MANA)
4677 ((Player*)m_target)->UpdateManaRegen();
4680 void Aura::HandleModManaRegen(bool /*apply*/, bool Real)
4682 // spells required only Real aura add/remove
4683 if(!Real)
4684 return;
4686 if (m_target->GetTypeId() != TYPEID_PLAYER)
4687 return;
4689 //Note: an increase in regen does NOT cause threat.
4690 ((Player*)m_target)->UpdateManaRegen();
4693 void Aura::HandleComprehendLanguage(bool apply, bool Real)
4695 if(apply)
4696 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4697 else
4698 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
4701 void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
4703 // Special case with temporary increase max/current health
4704 switch(GetId())
4706 case 12976: // Warrior Last Stand triggered spell
4707 case 28726: // Nightmare Seed ( Nightmare Seed )
4708 case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
4709 case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
4711 if(Real)
4713 if(apply)
4715 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4716 m_target->ModifyHealth(m_modifier.m_amount);
4718 else
4720 if (int32(m_target->GetHealth()) > m_modifier.m_amount)
4721 m_target->ModifyHealth(-m_modifier.m_amount);
4722 else
4723 m_target->SetHealth(1);
4724 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4727 return;
4731 // generic case
4732 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4735 void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
4737 uint32 oldhealth = m_target->GetHealth();
4738 double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
4740 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4742 // refresh percentage
4743 if(oldhealth > 0)
4745 uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
4746 if(newhealth==0)
4747 newhealth = 1;
4749 m_target->SetHealth(newhealth);
4753 void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
4755 Powers powerType = m_target->getPowerType();
4756 if(int32(powerType) != m_modifier.m_miscvalue)
4757 return;
4759 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4761 m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4764 void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/)
4766 Powers powerType = m_target->getPowerType();
4767 if(int32(powerType) != m_modifier.m_miscvalue)
4768 return;
4770 UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
4772 m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply);
4775 void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/)
4777 m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
4780 void Aura::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/)
4782 m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_modifier.m_amount), apply);
4785 /********************************/
4786 /*** FIGHT ***/
4787 /********************************/
4789 void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real)
4791 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4792 return;
4794 ((Player*)m_target)->UpdateParryPercentage();
4797 void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real)
4799 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4800 return;
4802 ((Player*)m_target)->UpdateDodgePercentage();
4803 //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
4806 void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real)
4808 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4809 return;
4811 ((Player*)m_target)->UpdateBlockPercentage();
4812 //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
4815 void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real)
4817 // spells required only Real aura add/remove
4818 if(!Real)
4819 return;
4821 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4822 return;
4824 ((Player*)m_target)->UpdateManaRegen();
4827 void Aura::HandleAuraModCritPercent(bool apply, bool Real)
4829 if(m_target->GetTypeId()!=TYPEID_PLAYER)
4830 return;
4832 // apply item specific bonuses for already equipped weapon
4833 if(Real)
4835 for(int i = 0; i < MAX_ATTACK; ++i)
4836 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
4837 ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
4840 // mods must be applied base at equipped weapon class and subclass comparison
4841 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
4842 // m_modifier.m_miscvalue comparison with item generated damage types
4844 if (GetSpellProto()->EquippedItemClass == -1)
4846 ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4847 ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4848 ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
4850 else
4852 // done in Player::_ApplyWeaponDependentAuraMods
4856 void Aura::HandleModHitChance(bool apply, bool Real)
4858 if(m_target->GetTypeId() == TYPEID_PLAYER)
4860 ((Player*)m_target)->UpdateMeleeHitChances();
4861 ((Player*)m_target)->UpdateRangedHitChances();
4863 else
4865 m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4866 m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
4870 void Aura::HandleModSpellHitChance(bool apply, bool Real)
4872 if(m_target->GetTypeId() == TYPEID_PLAYER)
4874 ((Player*)m_target)->UpdateSpellHitChances();
4876 else
4878 m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
4882 void Aura::HandleModSpellCritChance(bool apply, bool Real)
4884 // spells required only Real aura add/remove
4885 if(!Real)
4886 return;
4888 if(m_target->GetTypeId() == TYPEID_PLAYER)
4890 ((Player*)m_target)->UpdateAllSpellCritChances();
4892 else
4894 m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
4898 void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
4900 // spells required only Real aura add/remove
4901 if(!Real)
4902 return;
4904 if(m_target->GetTypeId() != TYPEID_PLAYER)
4905 return;
4907 for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
4908 if (m_modifier.m_miscvalue & (1<<school))
4909 ((Player*)m_target)->UpdateSpellCritChance(school);
4912 /********************************/
4913 /*** ATTACK SPEED ***/
4914 /********************************/
4916 void Aura::HandleModCastingSpeed(bool apply, bool Real)
4918 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4921 void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
4923 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4924 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4925 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4928 void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
4930 m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
4931 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4932 m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
4933 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4936 void Aura::HandleModAttackSpeed(bool apply, bool Real)
4938 if(!m_target->isAlive() )
4939 return;
4941 m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
4944 void Aura::HandleHaste(bool apply, bool Real)
4946 m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
4947 m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
4948 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
4951 void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
4953 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
4956 void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
4958 if(m_target->GetTypeId() != TYPEID_PLAYER)
4959 return;
4960 m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
4963 /********************************/
4964 /*** ATTACK POWER ***/
4965 /********************************/
4967 void Aura::HandleAuraModAttackPower(bool apply, bool Real)
4969 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4972 void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
4974 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4975 return;
4977 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
4980 void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
4982 //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
4983 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
4986 void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
4988 if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
4989 return;
4991 //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
4992 m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
4995 void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
4997 // spells required only Real aura add/remove
4998 if(!Real)
4999 return;
5001 // Recalculate bonus
5002 if(m_target->GetTypeId() == TYPEID_PLAYER && !(m_target->getClassMask() & CLASSMASK_WAND_USERS))
5003 ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
5006 void Aura::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real)
5008 // spells required only Real aura add/remove
5009 if(!Real)
5010 return;
5012 // Recalculate bonus
5013 if(m_target->GetTypeId() == TYPEID_PLAYER)
5014 ((Player*)m_target)->UpdateAttackPowerAndDamage(false);
5017 /********************************/
5018 /*** DAMAGE BONUS ***/
5019 /********************************/
5020 void Aura::HandleModDamageDone(bool apply, bool Real)
5022 // apply item specific bonuses for already equipped weapon
5023 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5025 for(int i = 0; i < MAX_ATTACK; ++i)
5026 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5027 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5030 // m_modifier.m_miscvalue is bitmask of spell schools
5031 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5032 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
5033 // 127 - full bitmask any damages
5035 // mods must be applied base at equipped weapon class and subclass comparison
5036 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5037 // m_modifier.m_miscvalue comparison with item generated damage types
5039 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5041 // apply generic physical damage bonuses including wand case
5042 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5044 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5045 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5046 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
5048 else
5050 // done in Player::_ApplyWeaponDependentAuraMods
5053 if(m_target->GetTypeId() == TYPEID_PLAYER)
5055 if(m_positive)
5056 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
5057 else
5058 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
5062 // Skip non magic case for speedup
5063 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5064 return;
5066 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5068 // wand magic case (skip generic to all item spell bonuses)
5069 // done in Player::_ApplyWeaponDependentAuraMods
5071 // Skip item specific requirements for not wand magic damage
5072 return;
5075 // Magic damage modifiers implemented in Unit::SpellDamageBonus
5076 // This information for client side use only
5077 if(m_target->GetTypeId() == TYPEID_PLAYER)
5079 if(m_positive)
5081 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5083 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5084 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
5087 else
5089 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
5091 if((m_modifier.m_miscvalue & (1<<i)) != 0)
5092 m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
5095 Pet* pet = m_target->GetPet();
5096 if(pet)
5097 pet->UpdateAttackPowerAndDamage();
5101 void Aura::HandleModDamagePercentDone(bool apply, bool Real)
5103 sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
5105 // apply item specific bonuses for already equipped weapon
5106 if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
5108 for(int i = 0; i < MAX_ATTACK; ++i)
5109 if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
5110 ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
5113 // m_modifier.m_miscvalue is bitmask of spell schools
5114 // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
5115 // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
5116 // 127 - full bitmask any damages
5118 // mods must be applied base at equipped weapon class and subclass comparison
5119 // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
5120 // m_modifier.m_miscvalue comparison with item generated damage types
5122 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
5124 // apply generic physical damage bonuses including wand case
5125 if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
5127 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5128 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5129 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
5131 else
5133 // done in Player::_ApplyWeaponDependentAuraMods
5135 // For show in client
5136 if(m_target->GetTypeId() == TYPEID_PLAYER)
5137 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
5140 // Skip non magic case for speedup
5141 if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
5142 return;
5144 if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
5146 // wand magic case (skip generic to all item spell bonuses)
5147 // done in Player::_ApplyWeaponDependentAuraMods
5149 // Skip item specific requirements for not wand magic damage
5150 return;
5153 // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
5154 // Send info to client
5155 if(m_target->GetTypeId() == TYPEID_PLAYER)
5156 for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
5157 m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
5160 void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
5162 // spells required only Real aura add/remove
5163 if(!Real)
5164 return;
5166 sLog.outDebug("AURA MOD OFFHAND DAMAGE");
5168 m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
5171 /********************************/
5172 /*** POWER COST ***/
5173 /********************************/
5175 void Aura::HandleModPowerCostPCT(bool apply, bool Real)
5177 // spells required only Real aura add/remove
5178 if(!Real)
5179 return;
5181 float amount = m_modifier.m_amount/100.0f;
5182 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5183 if(m_modifier.m_miscvalue & (1<<i))
5184 m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
5187 void Aura::HandleModPowerCost(bool apply, bool Real)
5189 // spells required only Real aura add/remove
5190 if(!Real)
5191 return;
5193 for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
5194 if(m_modifier.m_miscvalue & (1<<i))
5195 m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
5198 void Aura::HandleNoReagentUseAura(bool Apply, bool Real)
5200 // spells required only Real aura add/remove
5201 if(!Real)
5202 return;
5203 if(m_target->GetTypeId() != TYPEID_PLAYER)
5204 return;
5205 uint32 mask[3] = {0, 0, 0};
5206 Unit::AuraList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE);
5207 for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
5209 uint32 const *ptr = (*i)->getAuraSpellClassMask();
5210 mask[0]|=ptr[0];
5211 mask[1]|=ptr[1];
5212 mask[2]|=ptr[2];
5215 m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]);
5216 m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]);
5217 m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]);
5220 /*********************************************************/
5221 /*** OTHERS ***/
5222 /*********************************************************/
5224 void Aura::HandleShapeshiftBoosts(bool apply)
5226 uint32 spellId = 0;
5227 uint32 spellId2 = 0;
5228 uint32 HotWSpellId = 0;
5230 switch(GetModifier()->m_miscvalue)
5232 case FORM_CAT:
5233 spellId = 3025;
5234 HotWSpellId = 24900;
5235 break;
5236 case FORM_TREE:
5237 spellId = 5420;
5238 break;
5239 case FORM_TRAVEL:
5240 spellId = 5419;
5241 break;
5242 case FORM_AQUA:
5243 spellId = 5421;
5244 break;
5245 case FORM_BEAR:
5246 spellId = 1178;
5247 spellId2 = 21178;
5248 HotWSpellId = 24899;
5249 break;
5250 case FORM_DIREBEAR:
5251 spellId = 9635;
5252 spellId2 = 21178;
5253 HotWSpellId = 24899;
5254 break;
5255 case FORM_BATTLESTANCE:
5256 spellId = 21156;
5257 break;
5258 case FORM_DEFENSIVESTANCE:
5259 spellId = 7376;
5260 break;
5261 case FORM_BERSERKERSTANCE:
5262 spellId = 7381;
5263 break;
5264 case FORM_MOONKIN:
5265 spellId = 24905;
5266 // aura from effect trigger spell
5267 spellId2 = 24907;
5268 break;
5269 case FORM_FLIGHT:
5270 spellId = 33948;
5271 break;
5272 case FORM_FLIGHT_EPIC:
5273 spellId = 40122;
5274 spellId2 = 40121;
5275 break;
5276 case FORM_METAMORPHOSIS:
5277 spellId = 54817;
5278 spellId2 = 54879;
5279 break;
5280 case FORM_SPIRITOFREDEMPTION:
5281 spellId = 27792;
5282 spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
5283 break;
5284 case FORM_GHOSTWOLF:
5285 case FORM_AMBIENT:
5286 case FORM_GHOUL:
5287 case FORM_SHADOW:
5288 case FORM_STEALTH:
5289 case FORM_CREATURECAT:
5290 case FORM_CREATUREBEAR:
5291 spellId = 0;
5292 break;
5295 uint32 form = GetModifier()->m_miscvalue-1;
5297 if(apply)
5299 if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
5300 if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
5302 if(m_target->GetTypeId() == TYPEID_PLAYER)
5304 const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
5305 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
5307 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
5308 if(itr->first==spellId || itr->first==spellId2) continue;
5309 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
5310 if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
5311 if (spellInfo->Stances & (1<<form))
5312 m_target->CastSpell(m_target, itr->first, true, NULL, this);
5314 //LotP
5315 if (((Player*)m_target)->HasSpell(17007))
5317 SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
5318 if (spellInfo && spellInfo->Stances & (1<<form))
5319 m_target->CastSpell(m_target, 24932, true, NULL, this);
5321 // HotW
5322 if (HotWSpellId)
5324 Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
5325 for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
5327 if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
5329 int32 HotWMod = (*i)->GetModifier()->m_amount;
5330 if(GetModifier()->m_miscvalue == FORM_CAT)
5331 HotWMod /= 2;
5333 m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
5334 break;
5340 else
5342 m_target->RemoveAurasDueToSpell(spellId);
5343 m_target->RemoveAurasDueToSpell(spellId2);
5345 Unit::AuraMap& tAuras = m_target->GetAuras();
5346 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
5348 if (itr->second->IsRemovedOnShapeLost())
5350 m_target->RemoveAurasDueToSpell(itr->second->GetId());
5351 itr = tAuras.begin();
5353 else
5355 ++itr;
5360 /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
5361 m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
5364 void Aura::HandleAuraEmpathy(bool apply, bool Real)
5366 if(m_target->GetTypeId() != TYPEID_UNIT)
5367 return;
5369 CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
5370 if(ci && ci->type == CREATURE_TYPE_BEAST)
5371 m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
5374 void Aura::HandleAuraUntrackable(bool apply, bool Real)
5376 if(apply)
5377 m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5378 else
5379 m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
5382 void Aura::HandleAuraModPacify(bool apply, bool Real)
5384 if(m_target->GetTypeId() != TYPEID_PLAYER)
5385 return;
5387 if(apply)
5388 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5389 else
5390 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
5393 void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
5395 HandleAuraModPacify(apply,Real);
5396 HandleAuraModSilence(apply,Real);
5399 void Aura::HandleAuraGhost(bool apply, bool Real)
5401 if(m_target->GetTypeId() != TYPEID_PLAYER)
5402 return;
5404 if(apply)
5406 m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5408 else
5410 m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
5414 void Aura::HandleAuraAllowFlight(bool apply, bool Real)
5416 // all applied/removed only at real aura add/remove
5417 if(!Real)
5418 return;
5420 // allow fly
5421 WorldPacket data;
5422 if(apply)
5423 data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
5424 else
5425 data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
5426 data.append(m_target->GetPackGUID());
5427 data << uint32(0); // unk
5428 m_target->SendMessageToSet(&data, true);
5431 void Aura::HandleModRating(bool apply, bool Real)
5433 // spells required only Real aura add/remove
5434 if(!Real)
5435 return;
5437 if(m_target->GetTypeId() != TYPEID_PLAYER)
5438 return;
5440 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5441 if (m_modifier.m_miscvalue & (1 << rating))
5442 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
5445 void Aura::HandleModRatingFromStat(bool apply, bool Real)
5447 // spells required only Real aura add/remove
5448 if(!Real)
5449 return;
5451 if(m_target->GetTypeId() != TYPEID_PLAYER)
5452 return;
5453 // Just recalculate ratings
5454 for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
5455 if (m_modifier.m_miscvalue & (1 << rating))
5456 ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply);
5459 void Aura::HandleForceMoveForward(bool apply, bool Real)
5461 if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
5462 return;
5463 if(apply)
5464 m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5465 else
5466 m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
5469 void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real)
5471 if(m_target->GetTypeId() != TYPEID_PLAYER)
5472 return;
5474 ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
5475 ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
5478 void Aura::HandleModTargetResistance(bool apply, bool Real)
5480 // spells required only Real aura add/remove
5481 if(!Real)
5482 return;
5483 // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
5485 // show armor penetration
5486 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
5487 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
5489 // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
5490 if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
5491 m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
5494 void Aura::HandleShieldBlockValue(bool apply, bool Real)
5496 BaseModType modType = FLAT_MOD;
5497 if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
5498 modType = PCT_MOD;
5500 if(m_target->GetTypeId() == TYPEID_PLAYER)
5501 ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
5504 void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
5506 // spells required only Real aura add/remove
5507 if(!Real)
5508 return;
5510 if(m_target->GetTypeId() != TYPEID_PLAYER)
5511 return;
5513 Player *target = (Player*)m_target;
5515 // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
5516 // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
5517 if( !apply && m_duration==0 && target->GetComboTarget())
5518 if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
5519 target->AddComboPoints(unit, -m_modifier.m_amount);
5522 void Aura::HandleModUnattackable( bool Apply, bool Real )
5524 if(Real && Apply)
5525 m_target->CombatStop();
5527 m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
5530 void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
5532 // spells required only Real aura add/remove
5533 if(!Real)
5534 return;
5536 // prepare spirit state
5537 if(apply)
5539 if(m_target->GetTypeId()==TYPEID_PLAYER)
5541 // disable breath/etc timers
5542 ((Player*)m_target)->StopMirrorTimers();
5544 // set stand state (expected in this form)
5545 if(!m_target->IsStandState())
5546 m_target->SetStandState(PLAYER_STATE_NONE);
5549 m_target->SetHealth(1);
5551 // die at aura end
5552 else
5553 m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
5556 void Aura::CleanupTriggeredSpells()
5558 uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
5559 if(!tSpellId)
5560 return;
5562 SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
5563 if(!tProto)
5564 return;
5566 if(GetSpellDuration(tProto) != -1)
5567 return;
5569 // needed for spell 43680, maybe others
5570 // TODO: is there a spell flag, which can solve this in a more sophisticated way?
5571 if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
5572 GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
5573 return;
5574 m_target->RemoveAurasDueToSpell(tSpellId);
5577 void Aura::HandleAuraPowerBurn(bool apply, bool Real)
5579 if (m_periodicTimer <= 0)
5580 m_periodicTimer += m_modifier.periodictime;
5582 m_isPeriodic = apply;
5585 void Aura::HandleSchoolAbsorb(bool apply, bool Real)
5587 if(!Real)
5588 return;
5590 // prevent double apply bonuses
5591 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
5593 if(Unit* caster = GetCaster())
5595 float DoneActualBenefit = 0.0f;
5596 switch(m_spellProto->SpellFamilyName)
5598 case SPELLFAMILY_PRIEST:
5599 if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
5601 //+30% from +healing bonus
5602 DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
5603 break;
5605 break;
5606 case SPELLFAMILY_MAGE:
5607 if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
5609 //frost ward, fire ward, ice barrier
5610 //+10% from +spd bonus
5611 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5612 break;
5614 break;
5615 case SPELLFAMILY_WARLOCK:
5616 if(m_spellProto->SpellFamilyFlags == 0x00)
5618 //shadow ward
5619 //+10% from +spd bonus
5620 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
5621 break;
5623 break;
5624 default:
5625 break;
5628 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
5630 m_modifier.m_amount += (int32)DoneActualBenefit;
5635 void Aura::PeriodicTick()
5637 if(!m_target->isAlive())
5638 return;
5640 switch(m_modifier.m_auraname)
5642 case SPELL_AURA_PERIODIC_DAMAGE:
5643 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
5645 Unit *pCaster = GetCaster();
5646 if(!pCaster)
5647 return;
5649 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5650 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5651 return;
5653 // Check for immune (not use charges)
5654 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5655 return;
5657 // some auras remove at specific health level or more
5658 if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
5660 switch(GetId())
5662 case 43093: case 31956: case 38801:
5663 case 35321: case 38363: case 39215:
5664 if(m_target->GetHealth() == m_target->GetMaxHealth() )
5666 m_target->RemoveAurasDueToSpell(GetId());
5667 return;
5669 break;
5670 case 38772:
5672 uint32 percent =
5673 GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
5674 pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
5675 100;
5676 if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
5678 m_target->RemoveAurasDueToSpell(GetId());
5679 return;
5681 break;
5683 default:
5684 break;
5688 uint32 absorb=0;
5689 uint32 resist=0;
5690 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5692 // ignore non positive values (can be result apply spellmods to aura damage
5693 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5695 uint32 pdamage;
5697 if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
5699 pdamage = amount;
5701 // Calculate armor mitigation if it is a physical spell
5702 // But not for bleed mechanic spells
5703 if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
5704 GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
5706 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5707 cleanDamage.damage += pdamage - pdamageReductedArmor;
5708 pdamage = pdamageReductedArmor;
5711 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5713 // Curse of Agony damage-per-tick calculation
5714 if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
5716 // 1..4 ticks, 1/2 from normal tick damage
5717 if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
5718 pdamage = pdamage/2;
5719 // 9..12 ticks, 3/2 from normal tick damage
5720 else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
5721 pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
5722 // 5..8 ticks have normal tick damage
5725 else
5726 pdamage = uint32(m_target->GetMaxHealth()*amount/100);
5728 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5729 // Reduce dot damage from resilience for players
5730 if (m_target->GetTypeId()==TYPEID_PLAYER)
5731 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5733 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5735 sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5736 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5738 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5739 data.append(m_target->GetPackGUID());
5740 data.appendPackGUID(GetCasterGUID());
5741 data << uint32(GetId());
5742 data << uint32(1);
5743 data << uint32(m_modifier.m_auraname);
5744 data << (uint32)pdamage;
5745 data << uint32(0); // overkill
5746 data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
5747 data << (uint32)absorb;
5748 data << (uint32)resist;
5749 m_target->SendMessageToSet(&data,true);
5751 Unit* target = m_target; // aura can be deleted in DealDamage
5752 SpellEntry const* spellProto = GetSpellProto();
5754 // Set trigger flag
5755 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
5756 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
5757 pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
5758 if (pdamage)
5759 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
5760 pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5762 pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true);
5763 break;
5765 case SPELL_AURA_PERIODIC_LEECH:
5767 Unit *pCaster = GetCaster();
5768 if(!pCaster)
5769 return;
5771 if(!pCaster->isAlive())
5772 return;
5774 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5775 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5776 return;
5778 // Check for immune (not use charges)
5779 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
5780 return;
5782 uint32 absorb=0;
5783 uint32 resist=0;
5784 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5786 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5788 //Calculate armor mitigation if it is a physical spell
5789 if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
5791 uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
5792 cleanDamage.damage += pdamage - pdamageReductedArmor;
5793 pdamage = pdamageReductedArmor;
5796 pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
5798 // talent Soul Siphon add bonus to Drain Life spells
5799 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
5801 // find talent max bonus percentage
5802 Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
5803 for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
5805 if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
5807 if((*i)->GetEffIndex()!=1)
5809 sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
5810 break;
5813 // effect 1 m_amount
5814 int32 maxPercent = (*i)->GetModifier()->m_amount;
5815 // effect 0 m_amount
5816 int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
5818 // count affliction effects and calc additional damage in percentage
5819 int32 modPercent = 0;
5820 Unit::AuraMap const& victimAuras = m_target->GetAuras();
5821 for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
5823 Aura* aura = itr->second;
5824 if (aura->IsPositive())continue;
5825 SpellEntry const* m_spell = aura->GetSpellProto();
5826 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
5827 continue;
5829 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
5830 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
5832 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
5834 if(_spell_idx->second->skillId == SKILL_AFFLICTION)
5836 modPercent += stepPercent;
5837 if (modPercent >= maxPercent)
5839 modPercent = maxPercent;
5840 break;
5845 pdamage += (pdamage*modPercent/100);
5846 break;
5851 //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
5852 // Reduce dot damage from resilience for players
5853 if (m_target->GetTypeId()==TYPEID_PLAYER)
5854 pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
5856 pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
5858 if(m_target->GetHealth() < pdamage)
5859 pdamage = uint32(m_target->GetHealth());
5861 sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
5862 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
5864 pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
5867 Unit* target = m_target; // aura can be deleted in DealDamage
5868 SpellEntry const* spellProto = GetSpellProto();
5869 float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
5871 // Set trigger flag
5872 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
5873 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
5874 pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
5875 if (pdamage)
5876 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
5877 pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5878 int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false);
5880 if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
5882 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
5884 if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
5885 pCaster->m_currentSpells[i]->cancel();
5890 if(Player *modOwner = pCaster->GetSpellModOwner())
5891 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
5893 uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
5895 int32 gain = pCaster->ModifyHealth(heal);
5896 pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
5898 pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
5899 break;
5901 case SPELL_AURA_PERIODIC_HEAL:
5902 case SPELL_AURA_OBS_MOD_HEALTH:
5904 Unit *pCaster = GetCaster();
5905 if(!pCaster)
5906 return;
5908 // heal for caster damage (must be alive)
5909 if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive())
5910 return;
5912 // ignore non positive values (can be result apply spellmods to aura damage
5913 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
5915 uint32 pdamage;
5917 if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
5918 pdamage = uint32(m_target->GetMaxHealth() * amount/100);
5919 else
5920 pdamage = amount;
5922 pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
5924 sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
5925 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
5927 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
5928 data.append(m_target->GetPackGUID());
5929 data.appendPackGUID(GetCasterGUID());
5930 data << uint32(GetId());
5931 data << uint32(1);
5932 data << uint32(m_modifier.m_auraname);
5933 data << (uint32)pdamage;
5934 data << uint32(0); // wotlk
5935 m_target->SendMessageToSet(&data,true);
5937 int32 gain = m_target->ModifyHealth(pdamage);
5939 // add HoTs to amount healed in bgs
5940 if( pCaster->GetTypeId() == TYPEID_PLAYER )
5941 if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
5942 bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
5944 //Do check before because m_modifier.auraName can be invalidate by DealDamage.
5945 bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
5947 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
5949 Unit* target = m_target; // aura can be deleted in DealDamage
5950 SpellEntry const* spellProto = GetSpellProto();
5951 bool haveCastItem = GetCastItemGUID()!=0;
5953 // heal for caster damage
5954 if(m_target!=pCaster && spellProto->SpellVisual[0]==163)
5956 uint32 dmg = spellProto->manaPerSecond;
5957 if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
5959 pCaster->RemoveAurasDueToSpell(GetId());
5961 // finish current generic/channeling spells, don't affect autorepeat
5962 if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
5964 pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
5966 if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
5968 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
5969 pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
5972 else
5974 pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
5976 CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
5977 pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
5981 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HEAL;
5982 uint32 procVictim = 0;//ROC_FLAG_ON_TAKE_PERIODIC | PROC_FLAG_TAKEN_HEAL;
5983 // ignore item heals
5984 // if(procSpell && !haveCastItem)
5985 // pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
5986 break;
5988 case SPELL_AURA_PERIODIC_MANA_LEECH:
5990 Unit *pCaster = GetCaster();
5991 if(!pCaster)
5992 return;
5994 if(!pCaster->isAlive())
5995 return;
5997 if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
5998 pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
5999 return;
6001 // Check for immune (not use charges)
6002 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
6003 return;
6005 // ignore non positive values (can be result apply spellmods to aura damage
6006 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6008 sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
6009 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
6011 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
6012 break;
6014 Powers power = Powers(m_modifier.m_miscvalue);
6016 // power type might have changed between aura applying and tick (druid's shapeshift)
6017 if(m_target->getPowerType() != power)
6018 break;
6020 int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
6022 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
6023 if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
6024 drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
6026 m_target->ModifyPower(power, -drain_amount);
6028 float gain_multiplier = 0;
6030 if(pCaster->GetMaxPower(power) > 0)
6032 gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
6034 if(Player *modOwner = pCaster->GetSpellModOwner())
6035 modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
6038 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
6039 data.append(m_target->GetPackGUID());
6040 data.appendPackGUID(GetCasterGUID());
6041 data << uint32(GetId());
6042 data << uint32(1);
6043 data << uint32(m_modifier.m_auraname);
6044 data << (uint32)power; // power type
6045 data << (uint32)drain_amount;
6046 data << (float)gain_multiplier;
6047 m_target->SendMessageToSet(&data,true);
6049 int32 gain_amount = int32(drain_amount*gain_multiplier);
6051 if(gain_amount)
6053 int32 gain = pCaster->ModifyPower(power,gain_amount);
6054 m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
6056 break;
6058 case SPELL_AURA_PERIODIC_ENERGIZE:
6060 // ignore non positive values (can be result apply spellmods to aura damage
6061 uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6063 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
6064 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
6066 if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
6067 break;
6069 Powers power = Powers(m_modifier.m_miscvalue);
6071 if(m_target->GetMaxPower(power) == 0)
6072 break;
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)pdamage;
6082 m_target->SendMessageToSet(&data,true);
6084 int32 gain = m_target->ModifyPower(power,pdamage);
6086 if(Unit* pCaster = GetCaster())
6087 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
6088 break;
6090 case SPELL_AURA_OBS_MOD_MANA:
6092 // ignore non positive values (can be result apply spellmods to aura damage
6093 uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6095 uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
6097 sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
6098 GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
6100 if(m_target->GetMaxPower(POWER_MANA) == 0)
6101 break;
6103 WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
6104 data.append(m_target->GetPackGUID());
6105 data.appendPackGUID(GetCasterGUID());
6106 data << uint32(GetId());
6107 data << uint32(1);
6108 data << uint32(m_modifier.m_auraname);
6109 data << (uint32)0; // ?
6110 data << (uint32)pdamage;
6111 m_target->SendMessageToSet(&data,true);
6113 int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
6115 if(Unit* pCaster = GetCaster())
6116 m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
6117 break;
6119 case SPELL_AURA_POWER_BURN_MANA:
6121 Unit *pCaster = GetCaster();
6122 if(!pCaster)
6123 return;
6125 // Check for immune (not use charges)
6126 if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
6127 return;
6129 int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
6131 Powers powerType = Powers(m_modifier.m_miscvalue);
6133 if(!m_target->isAlive() || m_target->getPowerType() != powerType)
6134 return;
6136 // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
6137 if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
6138 pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
6140 uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
6142 gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
6144 SpellEntry const* spellProto = GetSpellProto();
6145 //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
6146 SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask);
6147 pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto);
6148 pCaster->SendSpellNonMeleeDamageLog(&damageInfo);
6150 // Set trigger flag
6151 uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
6152 uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
6153 uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE);
6154 if (damageInfo.damage)
6155 procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
6157 pCaster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);
6159 pCaster->DealSpellDamage(&damageInfo, true);
6160 break;
6162 // Here tick dummy auras
6163 case SPELL_AURA_PERIODIC_DUMMY:
6165 PeriodicDummyTick();
6166 break;
6168 default:
6169 break;
6173 void Aura::PeriodicDummyTick()
6175 Unit *caster = GetCaster();
6176 SpellEntry const* spell = GetSpellProto();
6177 switch (spell->SpellFamilyName)
6179 case SPELLFAMILY_GENERIC:
6180 switch (spell->Id)
6182 // Drink
6183 case 430:
6184 case 431:
6185 case 432:
6186 case 1133:
6187 case 1135:
6188 case 1137:
6189 case 10250:
6190 case 22734:
6191 case 27089:
6192 case 34291:
6193 case 43706:
6194 case 46755:
6195 case 49472: // Drink Coffee
6196 case 61830:
6198 if (m_target->GetTypeId() != TYPEID_PLAYER)
6199 return;
6200 // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
6201 Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
6202 for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
6204 if ((*i)->GetId() == GetId())
6206 // Get tick number
6207 int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
6208 // Default case (not on arenas)
6209 if (tick == 0)
6211 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6212 ((Player*)m_target)->UpdateManaRegen();
6213 // Disable continue
6214 m_isPeriodic = false;
6216 return;
6217 //**********************************************
6218 // Code commended since arena patch not added
6219 // This feature uses only in arenas
6220 //**********************************************
6221 // Here need increase mana regen per tick (6 second rule)
6222 // on 0 tick - 0 (handled in 2 second)
6223 // on 1 tick - 166% (handled in 4 second)
6224 // on 2 tick - 133% (handled in 6 second)
6225 // Not need update after 3 tick
6227 if (tick > 3)
6228 return;
6229 // Apply bonus for 0 - 3 tick
6230 switch (tick)
6232 case 0: // 0%
6233 (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
6234 break;
6235 case 1: // 166%
6236 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
6237 break;
6238 case 2: // 133%
6239 (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
6240 break;
6241 default: // 100% - normal regen
6242 (*i)->GetModifier()->m_amount = m_modifier.m_amount;
6243 break;
6245 ((Player*)m_target)->UpdateManaRegen();
6246 return;*/
6249 return;
6251 // Forsaken Skills
6252 case 7054:
6254 // Possibly need cast one of them (but
6255 // 7038 Forsaken Skill: Swords
6256 // 7039 Forsaken Skill: Axes
6257 // 7040 Forsaken Skill: Daggers
6258 // 7041 Forsaken Skill: Maces
6259 // 7042 Forsaken Skill: Staves
6260 // 7043 Forsaken Skill: Bows
6261 // 7044 Forsaken Skill: Guns
6262 // 7045 Forsaken Skill: 2H Axes
6263 // 7046 Forsaken Skill: 2H Maces
6264 // 7047 Forsaken Skill: 2H Swords
6265 // 7048 Forsaken Skill: Defense
6266 // 7049 Forsaken Skill: Fire
6267 // 7050 Forsaken Skill: Frost
6268 // 7051 Forsaken Skill: Holy
6269 // 7053 Forsaken Skill: Shadow
6270 return;
6272 // // Panda
6273 // case 19230: break;
6274 // // Gossip NPC Periodic - Talk
6275 // case 33208: break;
6276 // // Gossip NPC Periodic - Despawn
6277 // case 33209: break;
6279 // TODO: now its not periodic dummy - need move out from here
6280 // Aspect of the Viper
6281 case 34074:
6283 if (m_target->GetTypeId() != TYPEID_PLAYER)
6284 return;
6285 // Should be manauser
6286 if (m_target->getPowerType()!=POWER_MANA)
6287 return;
6288 if (!caster)
6289 return;
6290 // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
6291 int mana = m_target->GetPower(POWER_MANA);
6292 int max_mana = m_target->GetMaxPower(POWER_MANA);
6293 int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
6294 float regen_pct = 1.20f - 1.1f * mana / max_mana;
6295 if (regen_pct > 1.0f) regen_pct = 1.0f;
6296 else if (regen_pct < 0.2f) regen_pct = 0.2f;
6297 m_modifier.m_amount = int32 (base_regen * regen_pct);
6298 ((Player*)m_target)->UpdateManaRegen();
6299 return;
6301 // // Steal Weapon
6302 // case 36207: break;
6303 // // Simon Game START timer, (DND)
6304 // case 39993: break;
6305 // // Knockdown Fel Cannon: break; The Aggro Burst
6306 // case 40119: break;
6307 // // Old Mount Spell
6308 // case 40154: break;
6309 // // Magnetic Pull
6310 // case 40581: break;
6311 // // Ethereal Ring: break; The Bolt Burst
6312 // case 40801: break;
6313 // // Crystal Prison
6314 // case 40846: break;
6315 // // Copy Weapon
6316 // case 41054: break;
6317 // // Dementia
6318 // case 41404: break;
6319 // // Ethereal Ring Visual, Lightning Aura
6320 // case 41477: break;
6321 // // Ethereal Ring Visual, Lightning Aura (Fork)
6322 // case 41525: break;
6323 // // Ethereal Ring Visual, Lightning Jumper Aura
6324 // case 41567: break;
6325 // // No Man's Land
6326 // case 41955: break;
6327 // // Headless Horseman - Fire
6328 // case 42074: break;
6329 // // Headless Horseman - Visual - Large Fire
6330 // case 42075: break;
6331 // // Headless Horseman - Start Fire, Periodic Aura
6332 // case 42140: break;
6333 // // Ram Speed Boost
6334 // case 42152: break;
6335 // // Headless Horseman - Fires Out Victory Aura
6336 // case 42235: break;
6337 // // Pumpkin Life Cycle
6338 // case 42280: break;
6339 // // Brewfest Request Chick Chuck Mug Aura
6340 // case 42537: break;
6341 // // Squashling
6342 // case 42596: break;
6343 // // Headless Horseman Climax, Head: Periodic
6344 // case 42603: break;
6345 // // Fire Bomb
6346 // case 42621: break;
6347 // // Headless Horseman - Conflagrate, Periodic Aura
6348 // case 42637: break;
6349 // // Headless Horseman - Create Pumpkin Treats Aura
6350 // case 42774: break;
6351 // // Headless Horseman Climax - Summoning Rhyme Aura
6352 // case 42879: break;
6353 // // Tricky Treat
6354 // case 42919: break;
6355 // // Giddyup!
6356 // case 42924: break;
6357 // // Ram - Trot
6358 // case 42992: break;
6359 // // Ram - Canter
6360 // case 42993: break;
6361 // // Ram - Gallop
6362 // case 42994: break;
6363 // // Ram Level - Neutral
6364 // case 43310: break;
6365 // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
6366 // case 43884: break;
6367 // // Wretched!
6368 // case 43963: break;
6369 // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
6370 // case 44000: break;
6371 // // Energy Feedback
6372 // case 44328: break;
6373 // // Romantic Picnic
6374 // case 45102: break;
6375 // // Romantic Picnic
6376 // case 45123: break;
6377 // // Looking for Love
6378 // case 45124: break;
6379 // // Kite - Lightning Strike Kite Aura
6380 // case 45197: break;
6381 // // Rocket Chicken
6382 // case 45202: break;
6383 // // Copy Offhand Weapon
6384 // case 45205: break;
6385 // // Upper Deck - Kite - Lightning Periodic Aura
6386 // case 45207: break;
6387 // // Kite -Sky Lightning Strike Kite Aura
6388 // case 45251: break;
6389 // // Ribbon Pole Dancer Check Aura
6390 // case 45390: break;
6391 // // Holiday - Midsummer, Ribbon Pole Periodic Visual
6392 // case 45406: break;
6393 // // Parachute
6394 // case 45472: break;
6395 // // Alliance Flag, Extra Damage Debuff
6396 // case 45898: break;
6397 // // Horde Flag, Extra Damage Debuff
6398 // case 45899: break;
6399 // // Ahune - Summoning Rhyme Aura
6400 // case 45926: break;
6401 // // Ahune - Slippery Floor
6402 // case 45945: break;
6403 // // Ahune's Shield
6404 // case 45954: break;
6405 // // Nether Vapor Lightning
6406 // case 45960: break;
6407 // // Darkness
6408 // case 45996: break;
6409 // // Summon Blood Elves Periodic
6410 // case 46041: break;
6411 // // Transform Visual Missile Periodic
6412 // case 46205: break;
6413 // // Find Opening Beam End
6414 // case 46333: break;
6415 // // Ice Spear Control Aura
6416 // case 46371: break;
6417 // // Hailstone Chill
6418 // case 46458: break;
6419 // // Hailstone Chill, Internal
6420 // case 46465: break;
6421 // // Chill, Internal Shifter
6422 // case 46549: break;
6423 // // Summon Ice Spear Knockback Delayer
6424 // case 46878: break;
6425 // // Burninate Effect
6426 // case 47214: break;
6427 // // Fizzcrank Practice Parachute
6428 // case 47228: break;
6429 // // Send Mug Control Aura
6430 // case 47369: break;
6431 // // Direbrew's Disarm (precast)
6432 // case 47407: break;
6433 // // Mole Machine Port Schedule
6434 // case 47489: break;
6435 // case 47941: break; // Crystal Spike
6436 // case 48200: break; // Healer Aura
6437 // case 48630: break; // Summon Gauntlet Mobs Periodic
6438 // case 49313: break; // Proximity Mine Area Aura
6439 // // Mole Machine Portal Schedule
6440 // case 49466: break;
6441 // case 49555: break; // Corpse Explode
6442 // case 49592: break; // Temporal Rift
6443 // case 49957: break; // Cutting Laser
6444 // case 50085: break; // Slow Fall
6445 // // Listening to Music
6446 // case 50493: break;
6447 // // Love Rocket Barrage
6448 // case 50530: break;
6449 // Exist more after, need add later
6450 default:
6451 break;
6453 break;
6454 case SPELLFAMILY_MAGE:
6456 // Mirror Image
6457 // if (spell->Id == 55342)
6458 // return;
6459 break;
6461 case SPELLFAMILY_WARRIOR:
6463 // Armored to the Teeth
6464 if (spell->SpellIconID == 3516)
6466 // Increases your attack power by $s1 for every $s2 armor value you have.
6467 // Calculate AP bonus (from 1 efect of this spell)
6468 int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
6469 m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
6470 return;
6472 break;
6474 case SPELLFAMILY_DRUID:
6476 switch (spell->Id)
6478 // Frenzied Regeneration
6479 case 22842:
6481 // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
6482 // Should be manauser
6483 if (m_target->getPowerType()!=POWER_RAGE)
6484 return;
6485 uint32 rage = m_target->GetPower(POWER_RAGE);
6486 // Nothing todo
6487 if (rage == 0)
6488 return;
6489 int32 mod = (rage < 100) ? rage : 100;
6490 int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
6491 int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000;
6492 m_target->CastCustomSpell(m_target, 22845, &regen, 0, 0, true, 0, this);
6493 m_target->SetPower(POWER_RAGE, rage-mod);
6494 return;
6496 // Force of Nature
6497 case 33831:
6498 return;
6499 default:
6500 break;
6502 break;
6504 case SPELLFAMILY_ROGUE:
6506 // switch (spell->Id)
6507 // {
6508 // Master of Subtlety
6509 // case 31666: break;
6510 // Killing Spree
6511 // case 51690: break;
6512 // Overkill
6513 // case 58428: break;
6514 // default:
6515 // break;
6516 // }
6517 break;
6519 case SPELLFAMILY_HUNTER:
6521 // Explosive Shot
6522 if (spell->SpellFamilyFlags & 0x8000000000000000LL)
6524 if (!caster)
6525 return;
6526 // Skip 0 tick
6527 if (m_duration < m_modifier.periodictime)
6528 return;
6529 int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target);
6530 damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
6531 damage/=4;
6532 caster->CastCustomSpell(m_target, 56298, &damage, 0, 0, true, 0, this);
6533 return;
6535 switch (spell->Id)
6537 // Harpooner's Mark
6538 // case 40084:
6539 // return;
6540 // Feeding Frenzy Rank 1
6541 case 53511:
6542 if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
6543 m_target->CastSpell(m_target, 60096, true, 0, this);
6544 return;
6545 // Feeding Frenzy Rank 2
6546 case 53512:
6547 if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
6548 m_target->CastSpell(m_target, 60097, true, 0, this);
6549 return;
6550 default:
6551 break;
6553 break;
6555 case SPELLFAMILY_SHAMAN:
6557 // Astral Shift
6558 // if (spell->Id == 52179)
6559 // return;
6560 break;
6562 case SPELLFAMILY_DEATHKNIGHT:
6564 // Death and Decay
6565 // if (spell->SpellFamilyFlags & 0x0000000000000020LL)
6566 // return;
6567 // Raise Dead
6568 // if (spell->SpellFamilyFlags & 0x0000000000001000LL)
6569 // return;
6570 // Chains of Ice
6571 if (spell->SpellFamilyFlags & 0x0000400000000000LL)
6573 // Get 0 effect aura
6574 Aura *slow = m_target->GetAura(GetId(), 0);
6575 if (slow)
6577 slow->ApplyModifier(false, true);
6578 Modifier *mod = slow->GetModifier();
6579 mod->m_amount+= m_modifier.m_amount;
6580 if (mod->m_amount > 0) mod->m_amount = 0;
6581 slow->ApplyModifier(true, true);
6583 return;
6585 // Summon Gargoyle
6586 // if (spell->SpellFamilyFlags & 0x0000008000000000LL)
6587 // return;
6588 // Death Rune Mastery
6589 // if (spell->SpellFamilyFlags & 0x0000000000004000LL)
6590 // return;
6591 // Bladed Armor
6592 if (spell->SpellIconID == 2653)
6594 // Increases your attack power by $s1 for every $s2 armor value you have.
6595 // Calculate AP bonus (from 1 efect of this spell)
6596 int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
6597 m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
6598 return;
6600 // Reaping
6601 // if (spell->SpellIconID == 22)
6602 // return;
6603 // Blood of the North
6604 // if (spell->SpellIconID == 30412)
6605 // return;
6606 break;
6608 default:
6609 break;
6613 void Aura::HandlePreventFleeing(bool apply, bool Real)
6615 if(!Real)
6616 return;
6618 Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
6619 if( !fearAuras.empty() )
6621 if (apply)
6622 m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
6623 else
6624 m_target->SetFeared(true);
6628 void Aura::HandleManaShield(bool apply, bool Real)
6630 if(!Real)
6631 return;
6633 // prevent double apply bonuses
6634 if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
6636 if(Unit* caster = GetCaster())
6638 float DoneActualBenefit = 0.0f;
6639 switch(m_spellProto->SpellFamilyName)
6641 case SPELLFAMILY_MAGE:
6642 if(m_spellProto->SpellFamilyFlags & 0x8000)
6644 // Mana Shield
6645 // +50% from +spd bonus
6646 DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
6647 break;
6649 break;
6650 default:
6651 break;
6654 DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
6656 m_modifier.m_amount += (int32)DoneActualBenefit;
6661 void Aura::HandleArenaPreparation(bool apply, bool Real)
6663 if(!Real)
6664 return;
6666 if(apply)
6667 m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6668 else
6669 m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
6672 void Aura::HandleAuraControlVehicle(bool apply, bool Real)
6674 if(!Real)
6675 return;
6677 if(m_target->GetTypeId() != TYPEID_PLAYER)
6678 return;
6680 if(Pet *pet = m_target->GetPet())
6681 pet->Remove(PET_SAVE_AS_CURRENT);
6683 WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
6684 ((Player*)m_target)->GetSession()->SendPacket(&data);
6687 void Aura::HandleAuraConvertRune(bool apply, bool Real)
6689 if(!Real)
6690 return;
6692 if(m_target->GetTypeId() != TYPEID_PLAYER)
6693 return;
6695 Player *plr = (Player*)m_target;
6697 if(plr->getClass() != CLASS_DEATH_KNIGHT)
6698 return;
6700 // how to determine what rune need to be converted?
6701 for(uint32 i = 0; i < MAX_RUNES; ++i)
6703 if(apply)
6705 if(!plr->GetRuneCooldown(i))
6707 plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]);
6708 break;
6711 else
6713 if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex])
6715 plr->ConvertRune(i, plr->GetBaseRune(i));
6716 break;