server/src/game/SpellAuras.cpp
VladimirMangos 2b10d8fd71 [7364] Really implenent server-side anti-cheating cooldown check for spells with SPELL_ATTR_DISABLED_WHILE_ACTIVE.
Move apply cooldown for like spells to aura apply (GO registering for owner in GO summon spell case)
Store "infinity" cooldown for like spells, ignore it at save and reapply it at aura loading.

Note: one problem still exist for like spells: at loading/far teleport spell icon lost diabled state at client.
      Need sedn some unknown data in SendInitialPacketsBeforeAddToMap or SendInitialPacketsAfterAddToMap for restore it state.
2009-03-01 10:21:47 +03:00

6699 lines
262 KiB
C++

/*
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "UpdateMask.h"
#include "World.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Player.h"
#include "Unit.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "DynamicObject.h"
#include "Group.h"
#include "UpdateData.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Policies/SingletonImp.h"
#include "Totem.h"
#include "Creature.h"
#include "Formulas.h"
#include "BattleGround.h"
#include "CreatureAI.h"
#include "Util.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#define NULL_AURA_SLOT 0xFF
pAuraHandler AuraHandler[TOTAL_AURAS]=
{
&Aura::HandleNULL, // 0 SPELL_AURA_NONE
&Aura::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT
&Aura::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS
&Aura::HandlePeriodicDamage, // 3 SPELL_AURA_PERIODIC_DAMAGE
&Aura::HandleAuraDummy, // 4 SPELL_AURA_DUMMY
&Aura::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE
&Aura::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM
&Aura::HandleModFear, // 7 SPELL_AURA_MOD_FEAR
&Aura::HandlePeriodicHeal, // 8 SPELL_AURA_PERIODIC_HEAL
&Aura::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED
&Aura::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT
&Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT
&Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN
&Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE
&Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage
&Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH
&Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT
&Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY
&Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION
&Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH
&Aura::HandleAuraModTotalManaPercentRegen, // 21 SPELL_AURA_OBS_MOD_MANA
&Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE
&Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL
&Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE
&Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY
&Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT
&Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE
&Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult
&Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT
&Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL
&Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED
&Aura::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED
&Aura::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED
&Aura::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH
&Aura::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY
&Aura::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT
&Aura::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY
&Aura::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY
&Aura::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY
&Aura::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY
&Aura::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY
&Aura::HandleAuraProcTriggerSpell, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell
&Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor
&Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES
&Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES
&Aura::HandleUnused, // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a)
&Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT
&Aura::HandleNULL, // 48 SPELL_AURA_48 spell Napalm (area damage spell with additional delayed damage effect)
&Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT
&Aura::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_BONUS
&Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT
&Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT
&Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH
&Aura::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE
&Aura::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE
&Aura::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM
&Aura::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE
&Aura::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED
&Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
&Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
&Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
&Aura::HandleUnused, // 63 unused (3.0.8a) old SPELL_AURA_PERIODIC_MANA_FUNNEL
&Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH
&Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
&Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
&Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM
&Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED
&Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
&Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect
&Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
&Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
&Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL
&Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult
&Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE
&Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT
&Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY
&Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED
&Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
&Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT
&Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT
&Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING
&Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE
&Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN
&Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN
&Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM
&Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT
&Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
&Aura::HandleUnused, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE
&Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
&Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING
&Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE
&Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll
&Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST
&Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget
&Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist
&Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT
&Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER
&Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now, but still have spells including GM-spell
&Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT
&Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
&Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT
&Aura::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK
&Aura::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL
&Aura::HandleAuraHover, //106 SPELL_AURA_HOVER
&Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER
&Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER
&Aura::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER
&Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT
&Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER chance redirect attack to caster
&Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
&Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
&Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
&Aura::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim
&Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
&Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
&Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus
&Aura::HandleUnused, //119 unused (3.0.8a) old SPELL_AURA_SHARE_PET_TRACKING
&Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
&Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
&Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
&Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE
&Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER
&Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
&Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
&Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
&Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET
&Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS
&Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
&Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
&Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT
&Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
&Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
&Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE
&Aura::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus
&Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
&Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE
&Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
&Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
&Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
&Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
&Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
&Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
&Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
&Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
&Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
&Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
&Aura::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
&Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
&Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
&Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
&Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
&Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL
&Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
&Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
&Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
&Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
&Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
&Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
&Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
&Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA
&Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE
&Aura::HandleUnused, //164 unused (3.0.8a), only one test spell
&Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
&Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
&Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
&Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
&Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
&Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE different spells that ignore transformation effects
&Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
&Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
&Aura::HandleUnused, //173 unused (3.0.8a) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
&Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus
&Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
&Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
&Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM
&Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
&Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
&Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
&Aura::HandleUnused, //181 unused (3.0.8a) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
&Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
&Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746
&Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult
&Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
&Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
&Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING
&Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
&Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
&Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
&Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
&Aura::HandleNULL, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL
&Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL implement in Unit::CalculateSpellDamage
&Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
&Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
&Aura::HandleUnused, //198 unused (3.0.8a) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
&Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
&Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP
&Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
&Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
&Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
&Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
&Aura::HandleNULL, //205 vulnerable to school dmg?
&Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED
&Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
&Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive)
&Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS
&Aura::HandleNULL, //210 Commentator's Command
&Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
&Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
&Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
&Aura::HandleNULL, //214 Tamed Pet Passive
&Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
&Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
&Aura::HandleUnused, //217 unused (3.0.8a)
&Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
&Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
&Aura::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT
&Aura::HandleNULL, //221 ignored
&Aura::HandleUnused, //222 unused (3.0.8a) only for spell 44586 that not used in real spell cast
&Aura::HandleNULL, //223 Cold Stare
&Aura::HandleUnused, //224 unused (3.0.8a)
&Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING
&Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY
&Aura::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE
&Aura::HandleNoImmediateEffect, //228 stealth detection
&Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
&Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
&Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
&Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
&Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
&Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
&Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
&Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE
&Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus
&Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
&Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
&Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE
&Aura::HandleForceMoveForward, //241 Forces the player to move forward
&Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING
&Aura::HandleNULL, //243 faction reaction override spells
&Aura::HandleComprehendLanguage, //244 Comprehend language
&Aura::HandleNULL, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS
&Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL
&Aura::HandleNULL, //247 target to become a clone of the caster
&Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
&Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
&Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE
&Aura::HandleNULL, //252 haste all?
&Aura::HandleNULL, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE
&Aura::HandleNULL, //254 SPELL_AURA_MOD_DISARM_SHIELD disarm Shield
&Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus
&Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
&Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
&Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
&Aura::HandleNULL, //259 corrupt healing over time spell
&Aura::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code
&Aura::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect
&Aura::HandleNULL, //262
&Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
&Aura::HandleUnused, //264 unused (3.0.8a)
&Aura::HandleUnused, //265 unused (3.0.8a)
&Aura::HandleUnused, //266 unused (3.0.8a)
&Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect
&Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
&Aura::HandleNULL, //269 ignore DR effects?
&Aura::HandleNULL, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST
&Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
&Aura::HandleNULL, //272 reduce spell cast time?
&Aura::HandleNULL, //273
&Aura::HandleNULL, //274 proc free shot?
&Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
&Aura::HandleNULL, //276 mod damage % mechanic?
&Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Use SpellClassMask for spell select
&Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
&Aura::HandleNULL, //279 visual effects? 58836 and 57507
&Aura::HandleNULL, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
&Aura::HandleNULL, //281 SPELL_AURA_MOD_HONOR_GAIN
&Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
&Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
&Aura::HandleUnused, //284 not used by any spells (3.08a)
&Aura::HandleUnused, //285 not used by any spells (3.08a)
&Aura::HandleUnused, //286 not used by any spells (3.08a)
&Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult
&Aura::HandleUnused, //288 not used by any spells (3.09) except 1 test spell.
};
static AuraType const frozenAuraTypes[] = { SPELL_AURA_MOD_ROOT, SPELL_AURA_MOD_STUN, SPELL_AURA_NONE };
Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
m_spellmod(NULL), m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target),
m_timeCla(1000), m_periodicTimer(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
m_effIndex(eff), m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),
m_positive(false), m_permanent(false), m_isPeriodic(false), m_isAreaAura(false), m_isPersistent(false),
m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
{
assert(target);
assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
m_spellProto = spellproto;
m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff];
m_isPassive = IsPassiveSpell(GetId());
m_positive = IsPositiveEffect(GetId(), m_effIndex);
m_applyTime = time(NULL);
int32 damage;
if(!caster)
{
m_caster_guid = target->GetGUID();
damage = m_currentBasePoints+1; // stored value-1
m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target);
}
else
{
m_caster_guid = caster->GetGUID();
damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target);
m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target);
if (!damage && castItem && castItem->GetItemSuffixFactor())
{
ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
if(item_rand_suffix)
{
for (int k=0; k<3; k++)
{
SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
if(pEnchant)
{
for (int t=0; t<3; t++)
if(pEnchant->spellid[t] == m_spellProto->Id)
{
damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 );
break;
}
}
if(damage)
break;
}
}
}
}
if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0)
m_permanent = true;
Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
if(!m_permanent && modOwner)
{
modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration);
// Get zero duration aura after - need set m_maxduration > 0 for apply/remove aura work
if (m_maxduration<=0)
m_maxduration = 1;
}
m_duration = m_maxduration;
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);
m_effIndex = eff;
SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
// Apply periodic time mod
if(modOwner && m_modifier.periodictime)
modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_modifier.periodictime);
// Start periodic on next tick or at aura apply
if (!(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY))
m_periodicTimer += m_modifier.periodictime;
m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
m_procCharges = m_spellProto->procCharges;
if(modOwner)
modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() &&
m_spellProto->Stances &&
!(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) &&
!(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT));
}
Aura::~Aura()
{
}
AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
{
m_isAreaAura = true;
// caster==NULL in constructor args if target==caster in fact
Unit* caster_ptr = caster ? caster : target;
m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex]));
if(Player* modOwner = caster_ptr->GetSpellModOwner())
modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius);
switch(spellproto->Effect[eff])
{
case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
m_areaAuraType = AREA_AURA_PARTY;
if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
m_modifier.m_auraname = SPELL_AURA_NONE;
break;
case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
m_areaAuraType = AREA_AURA_RAID;
if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
m_modifier.m_auraname = SPELL_AURA_NONE;
break;
case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
m_areaAuraType = AREA_AURA_FRIEND;
break;
case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
m_areaAuraType = AREA_AURA_ENEMY;
if(target == caster_ptr)
m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self
break;
case SPELL_EFFECT_APPLY_AREA_AURA_PET:
m_areaAuraType = AREA_AURA_PET;
break;
case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
m_areaAuraType = AREA_AURA_OWNER;
if(target == caster_ptr)
m_modifier.m_auraname = SPELL_AURA_NONE;
break;
default:
sLog.outError("Wrong spell effect in AreaAura constructor");
ASSERT(false);
break;
}
}
AreaAura::~AreaAura()
{
}
PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
{
m_isPersistent = true;
}
PersistentAreaAura::~PersistentAreaAura()
{
}
SingleEnemyTargetAura::SingleEnemyTargetAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
{
if (caster)
m_casters_target_guid = caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)caster)->GetSelection() : caster->GetUInt64Value(UNIT_FIELD_TARGET);
else
m_casters_target_guid = 0;
}
SingleEnemyTargetAura::~SingleEnemyTargetAura()
{
}
Unit* SingleEnemyTargetAura::GetTriggerTarget() const
{
return ObjectAccessor::GetUnit(*m_target, m_casters_target_guid);
}
Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem)
{
if (IsAreaAuraEffect(spellproto->Effect[eff]))
return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem);
uint32 triggeredSpellId = spellproto->EffectTriggerSpell[eff];
if(SpellEntry const* triggeredSpellInfo = sSpellStore.LookupEntry(triggeredSpellId))
for (int i = 0; i < 3; ++i)
if (triggeredSpellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_ENEMY)
return new SingleEnemyTargetAura(spellproto, eff, currentBasePoints, target, caster, castItem);
return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem);
}
Unit* Aura::GetCaster() const
{
if(m_caster_guid==m_target->GetGUID())
return m_target;
//return ObjectAccessor::GetUnit(*m_target,m_caster_guid);
//must return caster even if it's in another grid/map
Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL);
return unit && unit->IsInWorld() ? unit : NULL;
}
void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
{
m_modifier.m_auraname = t;
m_modifier.m_amount = a;
m_modifier.m_miscvalue = miscValue;
m_modifier.periodictime = pt;
}
void Aura::Update(uint32 diff)
{
if (m_duration > 0)
{
m_duration -= diff;
if (m_duration < 0)
m_duration = 0;
m_timeCla -= diff;
// GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras
// all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0
if(GetEffIndex()==0 && m_timeCla <= 0)
{
if(Unit* caster = GetCaster())
{
Powers powertype = Powers(m_spellProto->powerType);
int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel();
m_timeCla = 1*IN_MILISECONDS;
if (manaPerSecond)
{
if(powertype==POWER_HEALTH)
caster->ModifyHealth(-manaPerSecond);
else
caster->ModifyPower(powertype,-manaPerSecond);
}
}
}
}
// Channeled aura required check distance from caster
if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID())
{
Unit* caster = GetCaster();
if(!caster)
{
m_target->RemoveAura(GetId(),GetEffIndex());
return;
}
// Get spell range
float radius;
SpellModOp mod;
if (m_spellProto->EffectRadiusIndex[GetEffIndex()])
{
radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()]));
mod = SPELLMOD_RADIUS;
}
else
{
radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
mod = SPELLMOD_RANGE;
}
if(Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetId(), mod, radius,NULL);
if(!caster->IsWithinDistInMap(m_target,radius))
{
m_target->RemoveAura(GetId(),GetEffIndex());
return;
}
}
if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
{
m_periodicTimer -= diff;
if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
{
// update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
m_periodicTimer += m_modifier.periodictime;
PeriodicTick();
}
}
}
void AreaAura::Update(uint32 diff)
{
// update for the caster of the aura
if(m_caster_guid == m_target->GetGUID())
{
Unit* caster = m_target;
if( !caster->hasUnitState(UNIT_STAT_ISOLATED) )
{
Unit* owner = caster->GetCharmerOrOwner();
if (!owner)
owner = caster;
std::list<Unit *> targets;
switch(m_areaAuraType)
{
case AREA_AURA_PARTY:
{
Group *pGroup = NULL;
if (owner->GetTypeId() == TYPEID_PLAYER)
pGroup = ((Player*)owner)->GetGroup();
if( pGroup)
{
uint8 subgroup = ((Player*)owner)->GetSubGroup();
for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* Target = itr->getSource();
if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target))
{
if(caster->IsWithinDistInMap(Target, m_radius))
targets.push_back(Target);
Pet *pet = Target->GetPet();
if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
targets.push_back(pet);
}
}
}
else
{
// add owner
if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
targets.push_back(owner);
// add caster's pet
Unit* pet = caster->GetPet();
if( pet && caster->IsWithinDistInMap(pet, m_radius))
targets.push_back(pet);
}
break;
}
case AREA_AURA_RAID:
{
Group *pGroup = NULL;
if (owner->GetTypeId() == TYPEID_PLAYER)
pGroup = ((Player*)owner)->GetGroup();
if( pGroup)
{
uint8 subgroup = ((Player*)owner)->GetSubGroup();
for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* Target = itr->getSource();
if(Target && Target->isAlive() && caster->IsFriendlyTo(Target))
{
if(caster->IsWithinDistInMap(Target, m_radius))
targets.push_back(Target);
Pet *pet = Target->GetPet();
if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
targets.push_back(pet);
}
}
}
else
{
// add owner
if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
targets.push_back(owner);
// add caster's pet
Unit* pet = caster->GetPet();
if( pet && caster->IsWithinDistInMap(pet, m_radius))
targets.push_back(pet);
}
break;
}
case AREA_AURA_FRIEND:
{
CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius);
MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(caster,targets, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
break;
}
case AREA_AURA_ENEMY:
{
CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(caster, targets, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
break;
}
case AREA_AURA_OWNER:
case AREA_AURA_PET:
{
if(owner != caster)
targets.push_back(owner);
break;
}
}
for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
{
if((*tIter)->HasAura(GetId(), m_effIndex))
continue;
if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
{
int32 actualBasePoints = m_currentBasePoints;
// recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
if(actualSpellInfo != GetSpellProto())
actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL);
aur->SetAuraDuration(GetAuraDuration());
(*tIter)->AddAura(aur);
}
}
}
Aura::Update(diff);
}
else // aura at non-caster
{
Unit * tmp_target = m_target;
Unit* caster = GetCaster();
uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
// WARNING: the aura may get deleted during the update
// DO NOT access its members after update!
Aura::Update(diff);
// remove aura if out-of-range from caster (after teleport for example)
// or caster is isolated or caster no longer has the aura
// or caster is (no longer) friendly
bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
!caster->IsWithinDistInMap(tmp_target, m_radius) ||
!caster->HasAura(tmp_spellId, tmp_effIndex) ||
caster->IsFriendlyTo(tmp_target) != needFriendly
)
{
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
{
// not check group if target == owner or target == pet
if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
{
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
Group *pGroup = check ? check->GetGroup() : NULL;
if( pGroup )
{
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
}
else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
{
// not check group if target == owner or target == pet
if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
{
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
Group *pGroup = check ? check->GetGroup() : NULL;
if( pGroup )
{
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
if(!checkTarget)
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
else
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
}
else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
{
if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
}
}
}
void PersistentAreaAura::Update(uint32 diff)
{
bool remove = false;
// remove the aura if its caster or the dynamic object causing it was removed
// or if the target moves too far from the dynamic object
Unit *caster = GetCaster();
if (caster)
{
DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
if (dynObj)
{
if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius()))
remove = true;
}
else
remove = true;
}
else
remove = true;
Unit *tmp_target = m_target;
uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
// WARNING: the aura may get deleted during the update
// DO NOT access its members after update!
Aura::Update(diff);
if(remove)
tmp_target->RemoveAura(tmp_id, tmp_index);
}
void Aura::ApplyModifier(bool apply, bool Real)
{
AuraType aura = m_modifier.m_auraname;
m_in_use = true;
if(aura<TOTAL_AURAS)
(*this.*AuraHandler [aura])(apply,Real);
m_in_use = false;
}
void Aura::_AddAura()
{
if (!GetId())
return;
if(!m_target)
return;
// Second aura if some spell
bool secondaura = false;
// Try find slot for aura
uint8 slot = NULL_AURA_SLOT;
// Lookup for some spell auras (and get slot from it)
for(uint8 i = 0; i < m_effIndex; i++)
{
Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
{
// allow use single slot only by auras from same caster
if(itr->second->GetCasterGUID()==GetCasterGUID())
{
slot = itr->second->GetAuraSlot();
secondaura = true;
break;
}
}
if (secondaura)
break;
}
// Lookup free slot
if (!secondaura && m_target->GetVisibleAurasCount() < MAX_AURAS)
{
Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras();
for(uint8 i = 0; i < MAX_AURAS; ++i)
{
Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i);
if(itr == visibleAuras->end())
{
slot = i;
// update for out of range group members (on 1 slot use)
m_target->UpdateAuraForGroup(slot);
break;
}
}
}
Unit* caster = GetCaster();
// set infinity cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if (m_spellProto->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
{
Item* castItem = m_castItemGuid ? ((Player*)caster)->GetItemByGuid(m_castItemGuid) : NULL;
((Player*)caster)->AddSpellAndCategoryCooldowns(m_spellProto,castItem ? castItem->GetEntry() : 0, NULL,true);
}
}
// passive auras (except totem auras) do not get placed in the slots
// area auras with SPELL_AURA_NONE are not shown on target
if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
(m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
{
SetAuraSlot( slot );
if(slot < MAX_AURAS) // slot found send data to client
{
SetAura(false);
SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE));
SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
SendAuraUpdate(false);
}
//*****************************************************
// Update target aura state flag (at 1 aura apply)
// TODO: Make it easer
//*****************************************************
if (!secondaura)
{
// Sitdown on apply aura req seated
if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState())
m_target->SetStandState(UNIT_STAND_STATE_SIT);
// register aura diminishing on apply
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),true);
// Update Seals information
if (IsSealSpell(m_spellProto))
m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
// Conflagrate aura state on Immolate
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags & 4)
m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
// Faerie Fire (druid versions)
if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true);
// Victorious
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true);
// Swiftmend state on Regrowth & Rejuvenation
if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 )
m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
// Deadly poison aura state
if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000)
m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true);
// Enrage aura state
if(m_spellProto->Dispel == DISPEL_ENRAGE)
m_target->ModifyAuraState(AURA_STATE_ENRAGE, true);
}
}
}
void Aura::_RemoveAura()
{
// Remove all triggered by aura spells vs unlimited duration
// except same aura replace case
if(m_removeMode!=AURA_REMOVE_BY_STACK)
CleanupTriggeredSpells();
Unit* caster = GetCaster();
if(caster && IsPersistent())
{
DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
if (dynObj)
dynObj->RemoveAffected(m_target);
}
//passive auras do not get put in slots
// Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
//if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
// return;
uint8 slot = GetAuraSlot();
if(slot >= MAX_AURAS) // slot not set
return;
if(m_target->GetVisibleAura(slot) == 0)
return;
bool lastaura = true;
// find other aura in same slot (current already removed from list)
for(uint8 i = 0; i < 3; i++)
{
Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
{
if(itr->second->GetAuraSlot()==slot)
{
lastaura = false;
break;
}
}
if(!lastaura)
break;
}
// only remove icon when the last aura of the spell is removed (current aura already removed from list)
if (lastaura)
{
// unregister aura diminishing (and store last time)
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),false);
SetAura(true);
SetAuraFlags(AFLAG_NONE);
SetAuraLevel(0);
SendAuraUpdate(true);
// update for out of range group members
m_target->UpdateAuraForGroup(slot);
//*****************************************************
// Update target aura state flag (at last aura remove)
//*****************************************************
// Enrage aura state
if(m_spellProto->Dispel == DISPEL_ENRAGE)
m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
uint32 removeState = 0;
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_PALADIN:
if (IsSealSpell(m_spellProto))
removeState = AURA_STATE_JUDGEMENT; // Update Seals information
break;
case SPELLFAMILY_WARLOCK:
if(m_spellProto->SpellFamilyFlags & 4)
removeState = AURA_STATE_IMMOLATE; // Conflagrate aura state
break;
case SPELLFAMILY_DRUID:
if(m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
else if(m_spellProto->SpellFamilyFlags & 0x50)
removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
break;
case SPELLFAMILY_WARRIOR:
if(m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
break;
case SPELLFAMILY_ROGUE:
if(m_spellProto->SpellFamilyFlags & 0x10000)
removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
break;
case SPELLFAMILY_HUNTER:
if(m_spellProto->SpellFamilyFlags & 0x1000000000000000LL)
removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
}
// Remove state (but need check other auras for it)
if (removeState)
{
bool found = false;
Unit::AuraMap& Auras = m_target->GetAuras();
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags )
{
found = true;
break;
}
}
// this has been last aura
if(!found)
m_target->ModifyAuraState(AuraState(removeState), false);
}
// reset cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
((Player*)caster)->SendCooldownEvent(GetSpellProto());
}
}
}
void Aura::SendAuraUpdate(bool remove)
{
WorldPacket data(SMSG_AURA_UPDATE);
data.append(m_target->GetPackGUID());
data << uint8(GetAuraSlot());
data << uint32(remove ? 0 : GetId());
if(remove)
{
m_target->SendMessageToSet(&data, true);
return;
}
uint8 auraFlags = GetAuraFlags();
data << uint8(auraFlags);
data << uint8(GetAuraLevel());
data << uint8(m_procCharges ? m_procCharges : m_stackAmount);
if(!(auraFlags & AFLAG_NOT_CASTER))
{
data << uint8(0); // pguid
}
if(auraFlags & AFLAG_DURATION)
{
data << uint32(GetAuraMaxDuration());
data << uint32(GetAuraDuration());
}
m_target->SendMessageToSet(&data, true);
}
void Aura::SetStackAmount(uint8 stackAmount)
{
if (stackAmount != m_stackAmount)
{
Unit *target = GetTarget();
Unit *caster = GetCaster();
if (!target || !caster)
return;
m_stackAmount = stackAmount;
int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target);
// Reapply if amount change
if (amount!=m_modifier.m_amount)
{
ApplyModifier(false, true);
m_modifier.m_amount = amount;
ApplyModifier(true, true);
}
}
RefreshAura();
}
bool Aura::modStackAmount(int32 num)
{
// Can`t mod
if (!m_spellProto->StackAmount)
return true;
// Modify stack but limit it
int32 stackAmount = m_stackAmount + num;
if (stackAmount > m_spellProto->StackAmount)
stackAmount = m_spellProto->StackAmount;
else if (stackAmount <=0) // Last aura from stack removed
{
m_stackAmount = 0;
return true; // need remove aura
}
// Update stack amount
SetStackAmount(stackAmount);
return false;
}
void Aura::RefreshAura()
{
m_duration = m_maxduration;
SendAuraUpdate(false);
}
bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
{
// Check family name
if (spell->SpellFamilyName != m_spellProto->SpellFamilyName)
return false;
// Check EffectClassMask
uint32 const *ptr = getAuraSpellClassMask();
if (((uint64*)ptr)[0] & spell->SpellFamilyFlags)
return true;
if (ptr[2] & spell->SpellFamilyFlags2)
return true;
return false;
}
/*********************************************************/
/*** BASIC AURA FUNCTION ***/
/*********************************************************/
void Aura::HandleAddModifier(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
return;
if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
return;
if (apply)
{
// Add custom charges for some mod aura
switch (m_spellProto->Id)
{
case 17941: // Shadow Trance
case 22008: // Netherwind Focus
case 31834: // Light's Grace
case 34754: // Clearcasting
case 34936: // Backlash
case 48108: // Hot Streak
case 54741: // Firestarter
case 57761: // Fireball!
SetAuraCharges(1);
break;
}
SpellModifier *mod = new SpellModifier;
mod->op = SpellModOp(m_modifier.m_miscvalue);
mod->value = m_modifier.m_amount;
mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
mod->spellId = GetId();
uint32 const *ptr;
SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
if (spellAffect)
ptr = &spellAffect->SpellClassMask[0];
else
{
switch (m_effIndex)
{
case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break;
case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break;
case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break;
default:
return;
}
}
mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
mod->mask2= (uint64)ptr[2];
mod->charges = m_procCharges;
m_spellmod = mod;
}
uint64 spellFamilyMask = m_spellmod->mask;
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
// reapply some passive spells after add/remove related spellmods
if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
{
m_target->RemoveAurasDueToSpell(45471);
if(apply)
m_target->CastSpell(m_target,45471,true);
}
}
void Aura::HandleAddTargetTrigger(bool apply, bool Real)
{
// Use SpellModifier structure for check
// used only fields:
// spellId, mask, mask2
if (apply)
{
SpellModifier *mod = new SpellModifier;
mod->spellId = GetId();
uint32 const *ptr;
SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
if (spellAffect)
ptr = &spellAffect->SpellClassMask[0];
else
{
switch (m_effIndex)
{
case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break;
case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break;
case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break;
default:
return;
}
}
mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
mod->mask2= (uint64)ptr[2];
m_spellmod = mod;
}
else
{
delete m_spellmod;
m_spellmod = NULL;
}
}
void Aura::TriggerSpell()
{
Unit* caster = GetCaster();
Unit* target = GetTriggerTarget();
if(!caster || !target)
return;
// generic casting code with custom spells and target/caster customs
uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
SpellEntry const *auraSpellInfo = GetSpellProto();
uint32 auraId = auraSpellInfo->Id;
// specific code for cases with no trigger spell provided in field
if (triggeredSpellInfo == NULL)
{
switch(auraSpellInfo->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
switch(auraId)
{
// Firestone Passive (1-5 ranks)
case 758:
case 17945:
case 17947:
case 17949:
case 27252:
{
if (caster->GetTypeId()!=TYPEID_PLAYER)
return;
Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
if (!item)
return;
uint32 enchant_id = 0;
switch (GetId())
{
case 758: enchant_id = 1803; break; // Rank 1
case 17945: enchant_id = 1823; break; // Rank 2
case 17947: enchant_id = 1824; break; // Rank 3
case 17949: enchant_id = 1825; break; // Rank 4
case 27252: enchant_id = 2645; break; // Rank 5
default:
return;
}
// remove old enchanting before applying new
((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
// add new enchanting
((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
return;
}
// // Periodic Mana Burn
// case 812: break;
// // Polymorphic Ray
// case 6965: break;
// // Fire Nova (1-7 ranks)
// case 8350:
// case 8508:
// case 8509:
// case 11312:
// case 11313:
// case 25540:
// case 25544:
// break;
// Thaumaturgy Channel
case 9712: trigger_spell_id = 21029; break;
// // Egan's Blaster
// case 17368: break;
// // Haunted
// case 18347: break;
// // Ranshalla Waiting
// case 18953: break;
// // Inferno
// case 19695: break;
// // Frostwolf Muzzle DND
// case 21794: break;
// // Alterac Ram Collar DND
// case 21866: break;
// // Celebras Waiting
// case 21916: break;
// Brood Affliction: Bronze
case 23170:
{
m_target->CastSpell(m_target, 23171, true, 0, this);
return;
}
// // Mark of Frost
// case 23184: break;
// Restoration
case 23493:
{
int32 heal = caster->GetMaxHealth() / 10;
caster->ModifyHealth( heal );
caster->SendHealSpellLog(caster, 23493, heal);
int32 mana = caster->GetMaxPower(POWER_MANA);
if (mana)
{
mana /= 10;
caster->ModifyPower( POWER_MANA, mana );
caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
}
break;
}
// // Stoneclaw Totem Passive TEST
// case 23792: break;
// // Axe Flurry
// case 24018: break;
// // Mark of Arlokk
// case 24210: break;
// // Restoration
// case 24379: break;
// // Happy Pet
// case 24716: break;
// // Dream Fog
// case 24780: break;
// // Cannon Prep
// case 24832: break;
// // Shadow Bolt Whirl
// case 24834: break;
// // Stink Trap
// case 24918: break;
// // Mark of Nature
// case 25041: break;
// // Agro Drones
// case 25152: break;
// // Consume
// case 25371: break;
// // Pain Spike
// case 25572: break;
// // Rotate 360
// case 26009: break;
// // Rotate -360
// case 26136: break;
// // Consume
// case 26196: break;
// // Berserk
// case 26615: break;
// // Defile
// case 27177: break;
// // Teleport: IF/UC
// case 27601: break;
// // Five Fat Finger Exploding Heart Technique
// case 27673: break;
// // Nitrous Boost
// case 27746: break;
// // Steam Tank Passive
// case 27747: break;
// // Frost Blast
// case 27808: break;
// // Detonate Mana
// case 27819: break;
// // Controller Timer
// case 28095: break;
// // Stalagg Chain
// case 28096: break;
// // Stalagg Tesla Passive
// case 28097: break;
// // Feugen Tesla Passive
// case 28109: break;
// // Feugen Chain
// case 28111: break;
// // Mark of Didier
// case 28114: break;
// // Communique Timer, camp
// case 28346: break;
// // Icebolt
// case 28522: break;
// // Silithyst
// case 29519: break;
// // Inoculate Nestlewood Owlkin
case 29528: trigger_spell_id = 28713; break;
// // Overload
// case 29768: break;
// // Return Fire
// case 29788: break;
// // Return Fire
// case 29793: break;
// // Return Fire
// case 29794: break;
// // Guardian of Icecrown Passive
// case 29897: break;
// Feed Captured Animal
case 29917: trigger_spell_id = 29916; break;
// // Flame Wreath
// case 29946: break;
// // Flame Wreath
// case 29947: break;
// // Mind Exhaustion Passive
// case 30025: break;
// // Nether Beam - Serenity
// case 30401: break;
// Extract Gas
case 30427:
{
// move loot to player inventory and despawn target
if(caster->GetTypeId() ==TYPEID_PLAYER &&
target->GetTypeId() == TYPEID_UNIT &&
((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
{
Player* player = (Player*)caster;
Creature* creature = (Creature*)target;
// missing lootid has been reported on startup - just return
if (!creature->GetCreatureInfo()->SkinLootId)
return;
player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId,LootTemplates_Skinning,true);
creature->setDeathState(JUST_DIED);
creature->RemoveCorpse();
creature->SetHealth(0); // just for nice GM-mode view
}
return;
break;
}
// Quake
case 30576: trigger_spell_id = 30571; break;
// // Burning Maul
// case 30598: break;
// // Regeneration
// case 30799:
// case 30800:
// case 30801:
// break;
// // Despawn Self - Smoke cloud
// case 31269: break;
// // Time Rift Periodic
// case 31320: break;
// // Corrupt Medivh
// case 31326: break;
// Doom
case 31347:
{
m_target->CastSpell(m_target,31350,true);
m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
return;
}
// Spellcloth
case 31373:
{
// Summon Elemental after create item
caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
return;
}
// // Bloodmyst Tesla
// case 31611: break;
// // Doomfire
// case 31944: break;
// // Teleport Test
// case 32236: break;
// // Earthquake
// case 32686: break;
// // Possess
// case 33401: break;
// // Draw Shadows
// case 33563: break;
// // Murmur's Touch
// case 33711: break;
// Flame Quills
case 34229:
{
// cast 24 spells 34269-34289, 34314-34316
for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
caster->CastSpell(m_target,spell_id,true);
for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
caster->CastSpell(m_target,spell_id,true);
return;
}
// // Gravity Lapse
// case 34480: break;
// // Tornado
// case 34683: break;
// // Frostbite Rotate
// case 34748: break;
// // Arcane Flurry
// case 34821: break;
// // Interrupt Shutdown
// case 35016: break;
// // Interrupt Shutdown
// case 35176: break;
// // Inferno
// case 35268: break;
// // Salaadin's Tesla
// case 35515: break;
// // Ethereal Channel (Red)
// case 35518: break;
// // Nether Vapor
// case 35879: break;
// // Dark Portal Storm
// case 36018: break;
// // Burning Maul
// case 36056: break;
// // Living Grove Defender Lifespan
// case 36061: break;
// // Professor Dabiri Talks
// case 36064: break;
// // Kael Gaining Power
// case 36091: break;
// // They Must Burn Bomb Aura
// case 36344: break;
// // They Must Burn Bomb Aura (self)
// case 36350: break;
// // Stolen Ravenous Ravager Egg
// case 36401: break;
// // Activated Cannon
// case 36410: break;
// // Stolen Ravenous Ravager Egg
// case 36418: break;
// // Enchanted Weapons
// case 36510: break;
// // Cursed Scarab Periodic
// case 36556: break;
// // Cursed Scarab Despawn Periodic
// case 36561: break;
// // Vision Guide
// case 36573: break;
// // Cannon Charging (platform)
// case 36785: break;
// // Cannon Charging (self)
// case 36860: break;
// Remote Toy
case 37027: trigger_spell_id = 37029; break;
// // Mark of Death
// case 37125: break;
// // Arcane Flurry
// case 37268: break;
// // Spout
// case 37429: break;
// // Spout
// case 37430: break;
// // Karazhan - Chess NPC AI, Snapshot timer
// case 37440: break;
// // Karazhan - Chess NPC AI, action timer
// case 37504: break;
// // Karazhan - Chess: Is Square OCCUPIED aura (DND)
// case 39400: break;
// // Banish
// case 37546: break;
// // Shriveling Gaze
// case 37589: break;
// // Fake Aggro Radius (2 yd)
// case 37815: break;
// // Corrupt Medivh
// case 37853: break;
// Eye of Grillok
case 38495:
{
m_target->CastSpell(m_target, 38530, true);
return;
}
// Absorb Eye of Grillok (Zezzak's Shard)
case 38554:
{
if(m_target->GetTypeId() != TYPEID_UNIT)
return;
caster->CastSpell(caster, 38495, true);
Creature* creatureTarget = (Creature*)m_target;
creatureTarget->setDeathState(JUST_DIED);
creatureTarget->RemoveCorpse();
creatureTarget->SetHealth(0); // just for nice GM-mode view
return;
}
// // Magic Sucker Device timer
// case 38672: break;
// // Tomb Guarding Charging
// case 38751: break;
// // Murmur's Touch
// case 38794: break;
// // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item)
// case 39105: break;
// // Drain World Tree Visual
// case 39140: break;
// // Quest - Dustin's Undead Dragon Visual aura
// case 39259: break;
// // Hellfire - The Exorcism, Jules releases darkness, aura
// case 39306: break;
// // Inferno
// case 39346: break;
// // Enchanted Weapons
// case 39489: break;
// // Shadow Bolt Whirl
// case 39630: break;
// // Shadow Bolt Whirl
// case 39634: break;
// // Shadow Inferno
// case 39645: break;
// Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
case 39857: trigger_spell_id = 39856; break;
// // Soulgrinder Ritual Visual (Smashed)
// case 39974: break;
// // Simon Game Pre-game timer
// case 40041: break;
// // Knockdown Fel Cannon: The Aggro Check Aura
// case 40113: break;
// // Spirit Lance
// case 40157: break;
// // Demon Transform 2
// case 40398: break;
// // Demon Transform 1
// case 40511: break;
// // Ancient Flames
// case 40657: break;
// // Ethereal Ring Cannon: Cannon Aura
// case 40734: break;
// // Cage Trap
// case 40760: break;
// // Random Periodic
// case 40867: break;
// // Prismatic Shield
// case 40879: break;
// // Aura of Desire
// case 41350: break;
// // Dementia
// case 41404: break;
// // Chaos Form
// case 41629: break;
// // Alert Drums
// case 42177: break;
// // Spout
// case 42581: break;
// // Spout
// case 42582: break;
// // Return to the Spirit Realm
// case 44035: break;
// // Curse of Boundless Agony
// case 45050: break;
// // Earthquake
// case 46240: break;
// Personalized Weather
case 46736: trigger_spell_id = 46737; break;
// // Stay Submerged
// case 46981: break;
// // Dragonblight Ram
// case 47015: break;
// // Party G.R.E.N.A.D.E.
// case 51510: break;
default:
break;
}
break;
}
case SPELLFAMILY_MAGE:
{
switch(auraId)
{
// Invisibility
case 66:
// Here need periodic triger reducing threat spell (or do it manually)
return;
default:
break;
}
break;
}
// case SPELLFAMILY_WARRIOR:
// {
// switch(auraId)
// {
// // Wild Magic
// case 23410: break;
// // Corrupted Totems
// case 23425: break;
// default:
// break;
// }
// break;
// }
// case SPELLFAMILY_PRIEST:
// {
// switch(auraId)
// {
// // Blue Beam
// case 32930: break;
// // Fury of the Dreghood Elders
// case 35460: break;
// default:
// break;
// }
// break;
// }
case SPELLFAMILY_DRUID:
{
switch(auraId)
{
// Cat Form
// trigger_spell_id not set and unknown effect triggered in this case, ignoring for while
case 768:
return;
// Frenzied Regeneration
case 22842:
case 22895:
case 22896:
case 26999:
{
int32 LifePerRage = GetModifier()->m_amount;
int32 lRage = m_target->GetPower(POWER_RAGE);
if(lRage > 100) // rage stored as rage*10
lRage = 100;
m_target->ModifyPower(POWER_RAGE, -lRage);
int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10);
m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this);
return;
}
default:
break;
}
break;
}
// case SPELLFAMILY_HUNTER:
// {
// switch(auraId)
// {
// //Frost Trap Aura
// case 13810:
// return;
// //Rizzle's Frost Trap
// case 39900:
// return;
// // Tame spells
// case 19597: // Tame Ice Claw Bear
// case 19676: // Tame Snow Leopard
// case 19677: // Tame Large Crag Boar
// case 19678: // Tame Adult Plainstrider
// case 19679: // Tame Prairie Stalker
// case 19680: // Tame Swoop
// case 19681: // Tame Dire Mottled Boar
// case 19682: // Tame Surf Crawler
// case 19683: // Tame Armored Scorpid
// case 19684: // Tame Webwood Lurker
// case 19685: // Tame Nightsaber Stalker
// case 19686: // Tame Strigid Screecher
// case 30100: // Tame Crazed Dragonhawk
// case 30103: // Tame Elder Springpaw
// case 30104: // Tame Mistbat
// case 30647: // Tame Barbed Crawler
// case 30648: // Tame Greater Timberstrider
// case 30652: // Tame Nightstalker
// return;
// default:
// break;
// }
// break;
// }
case SPELLFAMILY_SHAMAN:
{
switch(auraId)
{
// Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
case 28820:
{
// Need remove self if Lightning Shield not active
Unit::AuraMap const& auras = target->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
{
SpellEntry const* spell = itr->second->GetSpellProto();
if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
spell->SpellFamilyFlags & 0x0000000000000400L)
return;
}
target->RemoveAurasDueToSpell(28820);
return;
}
// Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
case 38443:
{
bool all = true;
for(int i = 0; i < MAX_TOTEM; ++i)
{
if(!caster->m_TotemSlot[i])
{
all = false;
break;
}
}
if(all)
caster->CastSpell(caster,38437,true);
else
caster->RemoveAurasDueToSpell(38437);
return;
}
default:
break;
}
break;
}
default:
break;
}
// Reget trigger spell proto
triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
if(triggeredSpellInfo == NULL)
{
sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
return;
}
}
else
{
// Spell exist but require custom code
switch(auraId)
{
// Curse of Idiocy
case 1010:
{
// TODO: spell casted by result in correct way mostly
// BUT:
// 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell
// but must show affect apply like item casting
// 2) maybe aura must be replace by new with accumulative stat mods instead stacking
// prevent cast by triggered auras
if(m_caster_guid == m_target->GetGUID())
return;
// stop triggering after each affected stats lost > 90
int32 intelectLoss = 0;
int32 spiritLoss = 0;
Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT);
for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
{
if ((*i)->GetId() == 1010)
{
switch((*i)->GetModifier()->m_miscvalue)
{
case STAT_INTELLECT: intelectLoss += (*i)->GetModifier()->m_amount; break;
case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
default: break;
}
}
}
if(intelectLoss <= -90 && spiritLoss <= -90)
return;
caster = target;
break;
}
// Mana Tide
case 16191:
{
caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this);
return;
}
}
}
// All ok cast by default case
caster->CastSpell(target, triggeredSpellInfo, true, 0, this);
}
void Aura::TriggerSpellWithValue()
{
Unit* caster = GetCaster();
Unit* target = GetTriggerTarget();
if(!caster || !target)
return;
// generic casting code with custom spells and target/caster customs
uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
int32 basepoints0 = this->GetModifier()->m_amount;
caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, 0, 0, true, 0, this);
}
/*********************************************************/
/*** AURA EFFECTS ***/
/*********************************************************/
void Aura::HandleAuraDummy(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
Unit* caster = GetCaster();
// AT APPLY
if(apply)
{
switch(GetId())
{
case 1515: // Tame beast
// FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
if( caster && m_target->CanHaveThreatList())
m_target->AddThreat(caster, 10.0f);
return;
case 13139: // net-o-matic
// root to self part of (root_target->charge->root_self sequence
if(caster)
caster->CastSpell(caster,13138,true,NULL,this);
return;
case 39850: // Rocket Blast
if(roll_chance_i(20)) // backfire stun
m_target->CastSpell(m_target, 51581, true, NULL, this);
return;
case 43873: // Headless Horseman Laugh
if(caster->GetTypeId() == TYPEID_PLAYER)
((Player*)caster)->PlaySound(11965, false);
return;
case 46354: // Blood Elf Illusion
if(caster)
{
switch(caster->getGender())
{
case GENDER_FEMALE:
caster->CastSpell(m_target,46356,true,NULL,this);
break;
case GENDER_MALE:
caster->CastSpell(m_target,46355,true,NULL,this);
break;
default:
break;
}
}
return;
case 46699: // Requires No Ammo
if(m_target->GetTypeId()==TYPEID_PLAYER)
((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
return;
}
// Earth Shield
if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
{
// prevent double apply bonuses
if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
return;
}
// some auras applied at aura apply
if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER)
{
SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId());
if(saBounds.first != saBounds.second)
{
uint32 zone = m_target->GetZoneId();
uint32 area = m_target->GetAreaId();
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if(itr->second->autocast && itr->second->IsFitToRequirements((Player*)m_target,zone,area))
if( !m_target->HasAura(itr->second->spellId,0) )
m_target->CastSpell(m_target,itr->second->spellId,true);
}
}
}
// AT REMOVE
else
{
if( m_target->GetTypeId() == TYPEID_PLAYER &&
( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
{
// spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
((Player*)m_target)->SetFarSightGUID(0);
WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
((Player*)m_target)->GetSession()->SendPacket(&data);
return;
}
if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive())
{
uint32 finalSpelId = 0;
switch(GetId())
{
case 19548: finalSpelId = 19597; break;
case 19674: finalSpelId = 19677; break;
case 19687: finalSpelId = 19676; break;
case 19688: finalSpelId = 19678; break;
case 19689: finalSpelId = 19679; break;
case 19692: finalSpelId = 19680; break;
case 19693: finalSpelId = 19684; break;
case 19694: finalSpelId = 19681; break;
case 19696: finalSpelId = 19682; break;
case 19697: finalSpelId = 19683; break;
case 19699: finalSpelId = 19685; break;
case 19700: finalSpelId = 19686; break;
case 30646: finalSpelId = 30647; break;
case 30653: finalSpelId = 30648; break;
case 30654: finalSpelId = 30652; break;
case 30099: finalSpelId = 30100; break;
case 30102: finalSpelId = 30103; break;
case 30105: finalSpelId = 30104; break;
}
if(finalSpelId)
caster->CastSpell(m_target,finalSpelId,true,NULL,this);
return;
}
switch(GetId())
{
case 2584: // Waiting to Resurrect
{
// Waiting to resurrect spell cancel, we must remove player from resurrect queue
if(m_target->GetTypeId() == TYPEID_PLAYER)
if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
return;
}
case 45934: // Dark Fiend
{
// Kill target if dispelled
if (m_removeMode==AURA_REMOVE_BY_DISPEL)
m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
return;
}
case 46308: // Burning Winds
{
// casted only at creatures at spawn
m_target->CastSpell(m_target,47287,true,NULL,this);
return;
}
}
if (caster && m_removeMode == AURA_REMOVE_BY_DEATH)
{
// Stop caster Arcane Missle chanelling on death
if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE &&
m_spellProto->SpellFamilyFlags&0x0000000000000800LL)
{
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
return;
}
// Stop caster Penance chanelling on death
if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST &&
m_spellProto->SpellFamilyFlags2 & 0x00000080)
{
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
return;
}
}
// some auras remove at aura remove
if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER)
{
SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId());
if(saBounds.first != saBounds.second)
{
uint32 zone = m_target->GetZoneId();
uint32 area = m_target->GetAreaId();
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area))
m_target->RemoveAurasDueToSpell(itr->second->spellId);
}
}
}
// AT APPLY & REMOVE
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
// Unstable Power
if( GetId()==24658 )
{
uint32 spellId = 24659;
if (apply)
{
const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
if (!spell)
return;
for (int i=0; i < spell->StackAmount; ++i)
caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
return;
}
m_target->RemoveAurasDueToSpell(spellId);
return;
}
// Restless Strength
if( GetId()==24661 )
{
uint32 spellId = 24662;
if (apply)
{
const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
if (!spell)
return;
for (int i=0; i < spell->StackAmount; ++i)
caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
return;
}
m_target->RemoveAurasDueToSpell(spellId);
return;
}
//Summon Fire Elemental
if (GetId() == 40133 && caster)
{
Unit *owner = caster->GetOwner();
if (owner && owner->GetTypeId() == TYPEID_PLAYER)
{
if(apply)
owner->CastSpell(owner,8985,true);
else
((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
}
return;
}
//Summon Earth Elemental
if (GetId() == 40132 && caster)
{
Unit *owner = caster->GetOwner();
if (owner && owner->GetTypeId() == TYPEID_PLAYER)
{
if(apply)
owner->CastSpell(owner,19704,true);
else
((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
}
return;
}
break;
}
case SPELLFAMILY_MAGE:
{
break;
}
case SPELLFAMILY_PRIEST:
{
// Pain and Suffering
if( m_spellProto->SpellIconID == 2874 && m_target->GetTypeId()==TYPEID_PLAYER )
{
if(apply)
{
// Reduce backfire damage (dot damage) from Shadow Word: Death
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_DOT;
mod->value = m_modifier.m_amount;
mod->type = SPELLMOD_PCT;
mod->spellId = GetId();
mod->mask = 0x0000000200000000LL;
mod->mask2= 0LL;
m_spellmod = mod;
}
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
break;
}
case SPELLFAMILY_DRUID:
{
// Lifebloom
if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
{
if ( apply )
{
if ( caster )
// prevent double apply bonuses
if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
}
else
{
// Final heal only on dispelled or duration end
if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
return;
// have a look if there is still some other Lifebloom dummy aura
Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); ++itr)
if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
(*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
return;
// final heal
if(m_target->IsInWorld() && m_stackAmount > 0)
{
int32 amount = m_modifier.m_amount / m_stackAmount;
m_target->CastCustomSpell(m_target,33778,&amount,NULL,NULL,true,NULL,this,GetCasterGUID());
}
}
return;
}
// Predatory Strikes
if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
{
((Player*)m_target)->UpdateAttackPowerAndDamage();
return;
}
// Idol of the Emerald Queen
if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
{
if(apply)
{
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_DOT;
mod->value = m_modifier.m_amount/7;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
mod->mask = 0x001000000000LL;
mod->mask2= 0LL;
m_spellmod = mod;
}
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
break;
}
case SPELLFAMILY_HUNTER:
{
// Improved Aspect of the Viper
if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
{
if(apply)
{
// + effect value for Aspect of the Viper
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_EFFECT1;
mod->value = m_modifier.m_amount;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
mod->mask = 0x4000000000000LL;
mod->mask2= 0LL;
m_spellmod = mod;
}
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
break;
}
case SPELLFAMILY_SHAMAN:
{
// Improved Weapon Totems
if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
{
if(apply)
{
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_EFFECT1;
mod->value = m_modifier.m_amount;
mod->type = SPELLMOD_PCT;
mod->spellId = GetId();
switch (m_effIndex)
{
case 0:
mod->mask = 0x00200000000LL; // Windfury Totem
mod->mask2= 0LL;
break;
case 1:
mod->mask = 0x00400000000LL; // Flametongue Totem
mod->mask2= 0LL;
break;
}
m_spellmod = mod;
}
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
break;
}
}
// pet auras
if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
{
if(apply)
m_target->AddPetAura(petSpell);
else
m_target->RemovePetAura(petSpell);
return;
}
}
void Aura::HandleAuraMounted(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
if(apply)
{
CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
if(!ci)
{
sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
return;
}
uint32 team = 0;
if (m_target->GetTypeId()==TYPEID_PLAYER)
team = ((Player*)m_target)->GetTeam();
uint32 display_id = objmgr.ChooseDisplayId(team,ci);
CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
if (minfo)
display_id = minfo->modelid;
m_target->Mount(display_id);
}
else
{
m_target->Unmount();
}
}
void Aura::HandleAuraWaterWalk(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
WorldPacket data;
if(apply)
data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
else
data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
data.append(m_target->GetPackGUID());
data << uint32(0);
m_target->SendMessageToSet(&data,true);
}
void Aura::HandleAuraFeatherFall(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
WorldPacket data;
if(apply)
data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
else
data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
data.append(m_target->GetPackGUID());
data << (uint32)0;
m_target->SendMessageToSet(&data,true);
}
void Aura::HandleAuraHover(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
WorldPacket data;
if(apply)
data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
else
data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
data.append(m_target->GetPackGUID());
data << uint32(0);
m_target->SendMessageToSet(&data,true);
}
void Aura::HandleWaterBreathing(bool apply, bool Real)
{
if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING))
{
// update for enable timer in case not moving target
if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
{
((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
((Player*)m_target)->HandleDrowning();
}
}
}
void Aura::HandleAuraModShapeshift(bool apply, bool Real)
{
if(!Real)
return;
uint32 modelid = 0;
Powers PowerType = POWER_MANA;
ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
switch(form)
{
case FORM_CAT:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 892;
else
modelid = 8571;
PowerType = POWER_ENERGY;
break;
case FORM_TRAVEL:
modelid = 632;
break;
case FORM_AQUA:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 2428;
else
modelid = 2428;
break;
case FORM_BEAR:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 2281;
else
modelid = 2289;
PowerType = POWER_RAGE;
break;
case FORM_GHOUL:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 10045;
break;
case FORM_DIREBEAR:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 2281;
else
modelid = 2289;
PowerType = POWER_RAGE;
break;
case FORM_CREATUREBEAR:
modelid = 902;
break;
case FORM_GHOSTWOLF:
modelid = 4613;
break;
case FORM_FLIGHT:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 20857;
else
modelid = 20872;
break;
case FORM_MOONKIN:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 15374;
else
modelid = 15375;
break;
case FORM_FLIGHT_EPIC:
if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
modelid = 21243;
else
modelid = 21244;
break;
case FORM_METAMORPHOSIS:
modelid = 25277;
break;
case FORM_AMBIENT:
case FORM_SHADOW:
case FORM_STEALTH:
break;
case FORM_TREE:
modelid = 864;
break;
case FORM_BATTLESTANCE:
case FORM_BERSERKERSTANCE:
case FORM_DEFENSIVESTANCE:
PowerType = POWER_RAGE;
break;
case FORM_SPIRITOFREDEMPTION:
modelid = 16031;
break;
default:
sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
}
// remove polymorph before changing display id to keep new display id
switch ( form )
{
case FORM_CAT:
case FORM_TREE:
case FORM_TRAVEL:
case FORM_AQUA:
case FORM_BEAR:
case FORM_DIREBEAR:
case FORM_FLIGHT_EPIC:
case FORM_FLIGHT:
case FORM_MOONKIN:
// remove movement affects
m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
// and polymorphic affects
if(m_target->IsPolymorphed())
m_target->RemoveAurasDueToSpell(m_target->getTransForm());
break;
default:
break;
}
if(apply)
{
// remove other shapeshift before applying a new one
if(m_target->m_ShapeShiftFormSpellId)
m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
if(modelid > 0)
m_target->SetDisplayId(modelid);
if(PowerType != POWER_MANA)
{
// reset power to default values only at power change
if(m_target->getPowerType()!=PowerType)
m_target->setPowerType(PowerType);
switch(form)
{
case FORM_CAT:
case FORM_BEAR:
case FORM_DIREBEAR:
{
// get furor proc chance
uint32 FurorChance = 0;
Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
{
if ((*i)->GetSpellProto()->SpellIconID == 238)
{
FurorChance = (*i)->GetModifier()->m_amount;
break;
}
}
if (m_modifier.m_miscvalue == FORM_CAT)
{
m_target->SetPower(POWER_ENERGY,0);
if(urand(1,100) <= FurorChance)
m_target->CastSpell(m_target,17099,true,NULL,this);
}
else
{
m_target->SetPower(POWER_RAGE,0);
if(urand(1,100) <= FurorChance)
m_target->CastSpell(m_target,17057,true,NULL,this);
}
break;
}
case FORM_BATTLESTANCE:
case FORM_DEFENSIVESTANCE:
case FORM_BERSERKERSTANCE:
{
uint32 Rage_val = 0;
// Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if(itr->second->state == PLAYERSPELL_REMOVED) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
}
}
if (m_target->GetPower(POWER_RAGE) > Rage_val)
m_target->SetPower(POWER_RAGE,Rage_val);
break;
}
default:
break;
}
}
m_target->m_ShapeShiftFormSpellId = GetId();
m_target->m_form = form;
}
else
{
if(modelid > 0)
m_target->SetDisplayId(m_target->GetNativeDisplayId());
m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
if(m_target->getClass() == CLASS_DRUID)
m_target->setPowerType(POWER_MANA);
m_target->m_ShapeShiftFormSpellId = 0;
m_target->m_form = FORM_NONE;
switch(form)
{
// Nordrassil Harness - bonus
case FORM_BEAR:
case FORM_DIREBEAR:
case FORM_CAT:
{
if(Aura* dummy = m_target->GetDummyAura(37315) )
m_target->CastSpell(m_target,37316,true,NULL,dummy);
break;
}
// Nordrassil Regalia - bonus
case FORM_MOONKIN:
{
if(Aura* dummy = m_target->GetDummyAura(37324) )
m_target->CastSpell(m_target,37325,true,NULL,dummy);
break;
}
}
}
// adding/removing linked auras
// add/remove the shapeshift aura's boosts
HandleShapeshiftBoosts(apply);
if(m_target->GetTypeId()==TYPEID_PLAYER)
((Player*)m_target)->InitDataForForm();
}
void Aura::HandleAuraTransform(bool apply, bool Real)
{
if (apply)
{
// special case (spell specific functionality)
if(m_modifier.m_miscvalue==0)
{
// player applied only
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
switch(GetId())
{
// Orb of Deception
case 16739:
{
uint32 orb_model = m_target->GetNativeDisplayId();
switch(orb_model)
{
// Troll Female
case 1479: m_target->SetDisplayId(10134); break;
// Troll Male
case 1478: m_target->SetDisplayId(10135); break;
// Tauren Male
case 59: m_target->SetDisplayId(10136); break;
// Human Male
case 49: m_target->SetDisplayId(10137); break;
// Human Female
case 50: m_target->SetDisplayId(10138); break;
// Orc Male
case 51: m_target->SetDisplayId(10139); break;
// Orc Female
case 52: m_target->SetDisplayId(10140); break;
// Dwarf Male
case 53: m_target->SetDisplayId(10141); break;
// Dwarf Female
case 54: m_target->SetDisplayId(10142); break;
// NightElf Male
case 55: m_target->SetDisplayId(10143); break;
// NightElf Female
case 56: m_target->SetDisplayId(10144); break;
// Undead Female
case 58: m_target->SetDisplayId(10145); break;
// Undead Male
case 57: m_target->SetDisplayId(10146); break;
// Tauren Female
case 60: m_target->SetDisplayId(10147); break;
// Gnome Male
case 1563: m_target->SetDisplayId(10148); break;
// Gnome Female
case 1564: m_target->SetDisplayId(10149); break;
// BloodElf Female
case 15475: m_target->SetDisplayId(17830); break;
// BloodElf Male
case 15476: m_target->SetDisplayId(17829); break;
// Dranei Female
case 16126: m_target->SetDisplayId(17828); break;
// Dranei Male
case 16125: m_target->SetDisplayId(17827); break;
default: break;
}
break;
}
// Murloc costume
case 42365: m_target->SetDisplayId(21723); break;
default: break;
}
}
else
{
CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
if(!ci)
{
//pig pink ^_^
m_target->SetDisplayId(16358);
sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
}
else
{
// Will use the default model here
m_target->SetDisplayId(ci->DisplayID_A);
// Dragonmaw Illusion (set mount model also)
if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
}
m_target->setTransForm(GetId());
}
// polymorph case
if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
{
// for players, start regeneration after 1s (in polymorph fast regeneration case)
// only if caster is Player (after patch 2.4.2)
if(IS_PLAYER_GUID(GetCasterGUID()) )
((Player*)m_target)->setRegenTimer(1*IN_MILISECONDS);
//dismount polymorphed target (after patch 2.4.2)
if (m_target->IsMounted())
m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
}
}
else
{
Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
if(otherTransforms.empty())
{
m_target->SetDisplayId(m_target->GetNativeDisplayId());
m_target->setTransForm(0);
}
else
{
// look for other transform auras
Aura* handledAura = *otherTransforms.begin();
for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
{
// negative auras are preferred
if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
{
handledAura = *i;
break;
}
}
handledAura->ApplyModifier(true);
}
// Dragonmaw Illusion (restore mount model)
if(GetId()==42016 && m_target->GetMountID()==16314)
{
if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
{
uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
{
uint32 team = 0;
if (m_target->GetTypeId()==TYPEID_PLAYER)
team = ((Player*)m_target)->GetTeam();
uint32 display_id = objmgr.ChooseDisplayId(team,ci);
CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
if (minfo)
display_id = minfo->modelid;
m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
}
}
}
}
}
void Aura::HandleForceReaction(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
if(!Real)
return;
Player* player = (Player*)m_target;
uint32 faction_id = m_modifier.m_miscvalue;
uint32 faction_rank = m_modifier.m_amount;
if(apply)
player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
else
player->m_forcedReactions.erase(faction_id);
WorldPacket data;
data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
data << uint32(player->m_forcedReactions.size());
for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
{
data << uint32(itr->first); // faction_id (Faction.dbc)
data << uint32(itr->second); // reputation rank
}
player->SendDirectMessage(&data);
}
void Aura::HandleAuraModSkill(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
int32 points = GetModifier()->m_amount;
((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
if(prot == SKILL_DEFENSE)
((Player*)m_target)->UpdateDefenseBonusesMod();
}
void Aura::HandleChannelDeathItem(bool apply, bool Real)
{
if(Real && !apply)
{
Unit* caster = GetCaster();
Unit* victim = GetTarget();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
return;
// Item amount
if (m_modifier.m_amount <= 0)
return;
SpellEntry const *spellInfo = GetSpellProto();
if(spellInfo->EffectItemType[m_effIndex] == 0)
return;
// Soul Shard only from non-grey units
if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
(victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
return;
//Adding items
uint32 noSpaceForCount = 0;
uint32 count = m_modifier.m_amount;
ItemPosCountVec dest;
uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], count, &noSpaceForCount);
if( msg != EQUIP_ERR_OK )
{
count-=noSpaceForCount;
((Player*)caster)->SendEquipError( msg, NULL, NULL );
if (count==0)
return;
}
Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
((Player*)caster)->SendNewItem(newitem, count, true, false);
}
}
void Aura::HandleBindSight(bool apply, bool Real)
{
Unit* caster = GetCaster();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
}
void Aura::HandleFarSight(bool apply, bool Real)
{
Unit* caster = GetCaster();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
}
void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
{
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
if(apply)
m_target->RemoveNoStackAurasDueToAura(this);
m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
}
void Aura::HandleAuraTrackResources(bool apply, bool Real)
{
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
if(apply)
m_target->RemoveNoStackAurasDueToAura(this);
m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
}
void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
{
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
if(apply)
m_target->RemoveNoStackAurasDueToAura(this);
m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
}
void Aura::HandleAuraModScale(bool apply, bool Real)
{
m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
}
void Aura::HandleModPossess(bool apply, bool Real)
{
if(!Real)
return;
if(m_target->getLevel() > m_modifier.m_amount)
return;
// not possess yourself
if(GetCasterGUID() == m_target->GetGUID())
return;
Unit* caster = GetCaster();
if(!caster)
return;
if( apply )
{
m_target->SetCharmerGUID(GetCasterGUID());
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
caster->SetCharm(m_target);
m_target->CombatStop();
m_target->DeleteThreatList();
if(m_target->GetTypeId() == TYPEID_UNIT)
{
m_target->StopMoving();
m_target->GetMotionMaster()->Clear();
m_target->GetMotionMaster()->MoveIdle();
CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
charmInfo->InitPossessCreateSpells();
}
if(caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)caster)->PossessSpellInitialize();
}
}
else
{
m_target->SetCharmerGUID(0);
if(m_target->GetTypeId() == TYPEID_PLAYER)
((Player*)m_target)->setFactionForRace(m_target->getRace());
else if(m_target->GetTypeId() == TYPEID_UNIT)
{
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
}
caster->SetCharm(0);
if(caster->GetTypeId() == TYPEID_PLAYER)
{
WorldPacket data(SMSG_PET_SPELLS, 8);
data << uint64(0);
data << uint32(0);
((Player*)caster)->GetSession()->SendPacket(&data);
}
if(m_target->GetTypeId() == TYPEID_UNIT)
{
((Creature*)m_target)->AIM_Initialize();
if (((Creature*)m_target)->AI())
((Creature*)m_target)->AI()->AttackStart(caster);
}
}
if(caster->GetTypeId() == TYPEID_PLAYER)
((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
}
void Aura::HandleModPossessPet(bool apply, bool Real)
{
if(!Real)
return;
Unit* caster = GetCaster();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
Pet *pet = caster->GetPet();
if(!pet || pet != m_target)
return;
if(apply)
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
else
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : NULL);
((Player*)caster)->SetCharm(apply ? pet : NULL);
((Player*)caster)->SetClientControl(pet, apply ? 1 : 0);
if(apply)
{
pet->StopMoving();
pet->GetMotionMaster()->Clear();
pet->GetMotionMaster()->MoveIdle();
}
else
{
pet->AttackStop();
pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
}
}
void Aura::HandleAuraModPetTalentsPoints(bool Apply, bool Real)
{
if(!Real)
return;
// Recalculate pet tlaent points
if (Pet *pet=m_target->GetPet())
pet->InitTalentForLevel();
}
void Aura::HandleModCharm(bool apply, bool Real)
{
if(!Real)
return;
// not charm yourself
if(GetCasterGUID() == m_target->GetGUID())
return;
Unit* caster = GetCaster();
if(!caster)
return;
if(int32(m_target->getLevel()) <= m_modifier.m_amount)
{
if( apply )
{
m_target->SetCharmerGUID(GetCasterGUID());
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
m_target->CastStop(m_target==caster ? GetId() : 0);
caster->SetCharm(m_target);
m_target->CombatStop();
m_target->DeleteThreatList();
if(m_target->GetTypeId() == TYPEID_UNIT)
{
((Creature*)m_target)->AIM_Initialize();
CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
charmInfo->InitCharmCreateSpells();
charmInfo->SetReactState( REACT_DEFENSIVE );
if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
{
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
{
//to prevent client crash
m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
//just to enable stat window
charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
//if charmed two demons the same session, the 2nd gets the 1st one's name
m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
}
}
}
if(caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)caster)->CharmSpellInitialize();
}
}
else
{
m_target->SetCharmerGUID(0);
if(m_target->GetTypeId() == TYPEID_PLAYER)
((Player*)m_target)->setFactionForRace(m_target->getRace());
else
{
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
// restore faction
if(((Creature*)m_target)->isPet())
{
if(Unit* owner = m_target->GetOwner())
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
else if(cinfo)
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
}
else if(cinfo) // normal creature
m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
// restore UNIT_FIELD_BYTES_0
if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
{
CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
if(cainfo && cainfo->bytes0 != 0)
m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
else
m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
if(m_target->GetCharmInfo())
m_target->GetCharmInfo()->SetPetNumber(0, true);
else
sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
}
}
caster->SetCharm(0);
if(caster->GetTypeId() == TYPEID_PLAYER)
{
WorldPacket data(SMSG_PET_SPELLS, 8);
data << uint64(0);
data << uint32(0);
((Player*)caster)->GetSession()->SendPacket(&data);
}
if(m_target->GetTypeId() == TYPEID_UNIT)
{
((Creature*)m_target)->AIM_Initialize();
if (((Creature*)m_target)->AI())
((Creature*)m_target)->AI()->AttackStart(caster);
}
}
}
}
void Aura::HandleModConfuse(bool apply, bool Real)
{
if(!Real)
return;
m_target->SetConfused(apply, GetCasterGUID(), GetId());
}
void Aura::HandleModFear(bool apply, bool Real)
{
if (!Real)
return;
m_target->SetFeared(apply, GetCasterGUID(), GetId());
}
void Aura::HandleFeignDeath(bool apply, bool Real)
{
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
if( apply )
{
/*
WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
data<<m_target->GetGUID();
data<<uint8(0);
m_target->SendMessageToSet(&data,true);
*/
// blizz like 2.0.x
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
// blizz like 2.0.x
m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x
m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
m_target->addUnitState(UNIT_STAT_DIED);
m_target->CombatStop();
// prevent interrupt message
if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
m_target->InterruptNonMeleeSpells(true);
m_target->getHostilRefManager().deleteReferences();
}
else
{
/*
WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
data<<m_target->GetGUID();
data<<uint8(1);
m_target->SendMessageToSet(&data,true);
*/
// blizz like 2.0.x
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
// blizz like 2.0.x
m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x
m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
m_target->clearUnitState(UNIT_STAT_DIED);
}
}
void Aura::HandleAuraModDisarm(bool apply, bool Real)
{
if(!Real)
return;
if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
return;
// not sure for it's correctness
if(apply)
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
else
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
// only at real add/remove aura
if (m_target->GetTypeId() != TYPEID_PLAYER)
return;
// main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
if (((Player *)m_target)->IsInFeralForm())
return;
if (apply)
m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
else
((Player *)m_target)->SetRegularAttackTime();
m_target->UpdateDamagePhysical(BASE_ATTACK);
}
void Aura::HandleAuraModStun(bool apply, bool Real)
{
if(!Real)
return;
if (apply)
{
// Frost stun aura -> freeze/unfreeze target
if (GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST)
m_target->ModifyAuraState(AURA_STATE_FROZEN, apply);
m_target->addUnitState(UNIT_STAT_STUNNED);
m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
// Creature specific
if(m_target->GetTypeId() != TYPEID_PLAYER)
((Creature*)m_target)->StopMoving();
else
m_target->SetUnitMovementFlags(0); //Clear movement flags
WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
data.append(m_target->GetPackGUID());
data << uint32(0);
m_target->SendMessageToSet(&data,true);
}
else
{
// Frost stun aura -> freeze/unfreeze target
if (GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST)
{
bool found_another = false;
for(AuraType const* itr = &frozenAuraTypes[0]; *itr != SPELL_AURA_NONE; ++itr)
{
Unit::AuraList const& auras = m_target->GetAurasByType(*itr);
for(Unit::AuraList::const_iterator i = auras.begin(); i != auras.end(); ++i)
{
if( GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST)
{
found_another = true;
break;
}
}
if(found_another)
break;
}
if(!found_another)
m_target->ModifyAuraState(AURA_STATE_FROZEN, apply);
}
// Real remove called after current aura remove from lists, check if other similar auras active
if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
return;
m_target->clearUnitState(UNIT_STAT_STUNNED);
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
{
if(m_target->getVictim() && m_target->isAlive())
m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
data.append(m_target->GetPackGUID());
data << uint32(0);
m_target->SendMessageToSet(&data,true);
}
// Wyvern Sting
if (m_spellProto->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellProto->SpellFamilyFlags & 0x0000100000000000LL)
{
Unit* caster = GetCaster();
if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
return;
uint32 spell_id = 0;
switch(GetId())
{
case 19386: spell_id = 24131; break;
case 24132: spell_id = 24134; break;
case 24133: spell_id = 24135; break;
case 27068: spell_id = 27069; break;
case 49011: spell_id = 49009; break;
case 49012: spell_id = 49010; break;
default:
sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
return;
}
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
if(!spellInfo)
return;
caster->CastSpell(m_target,spellInfo,true,NULL,this);
return;
}
}
}
void Aura::HandleModStealth(bool apply, bool Real)
{
if(apply)
{
// drop flag at stealth in bg
if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround())
if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
bg->EventPlayerDroppedFlag((Player*)m_target);
// only at real aura add
if(Real)
{
m_target->SetStandFlags(UNIT_STAND_FLAGS_CREEP);
if(m_target->GetTypeId()==TYPEID_PLAYER)
m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
// apply only if not in GM invisibility (and overwrite invisibility state)
if(m_target->GetVisibility()!=VISIBILITY_OFF)
{
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
}
}
}
else
{
// only at real aura remove
if(Real)
{
// if last SPELL_AURA_MOD_STEALTH and no GM invisibility
if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
{
m_target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP);
if(m_target->GetTypeId()==TYPEID_PLAYER)
m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
// restore invisibility if any
if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
{
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
}
else
m_target->SetVisibility(VISIBILITY_ON);
}
}
}
// Master of Subtlety
Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
{
if ((*i)->GetSpellProto()->SpellIconID == 2114)
{
if (apply)
{
int32 bp = (*i)->GetModifier()->m_amount;
m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
}
else
m_target->CastSpell(m_target,31666,true);
break;
}
}
}
void Aura::HandleInvisibility(bool apply, bool Real)
{
if(apply)
{
m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
{
// apply glow vision
m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
// drop flag at invisible in bg
if(((Player*)m_target)->InBattleGround())
if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
bg->EventPlayerDroppedFlag((Player*)m_target);
}
// apply only if not in GM invisibility and not stealth
if(m_target->GetVisibility()==VISIBILITY_ON)
{
// Aura not added yet but visibility code expect temporary add aura
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
}
}
else
{
// recalculate value at modifier remove (current aura already removed)
m_target->m_invisibilityMask = 0;
Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
// only at real aura remove and if not have different invisibility auras.
if(Real && m_target->m_invisibilityMask==0)
{
// remove glow vision
if(m_target->GetTypeId() == TYPEID_PLAYER)
m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
// apply only if not in GM invisibility & not stealthed while invisible
if(m_target->GetVisibility()!=VISIBILITY_OFF)
{
// if have stealth aura then already have stealth visibility
if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
m_target->SetVisibility(VISIBILITY_ON);
}
}
}
}
void Aura::HandleInvisibilityDetect(bool apply, bool Real)
{
if(apply)
{
m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
}
else
{
// recalculate value at modifier remove (current aura already removed)
m_target->m_detectInvisibilityMask = 0;
Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
}
if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
}
void Aura::HandleAuraModRoot(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
uint32 apply_stat = UNIT_STAT_ROOT;
if (apply)
{
// Frost root aura -> freeze/unfreeze target
if (GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST)
m_target->ModifyAuraState(AURA_STATE_FROZEN, apply);
m_target->addUnitState(UNIT_STAT_ROOT);
m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
// probably wrong (this add skinable flag)
// TODO: find correct flag
// m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
//Save last orientation
if( m_target->getVictim() )
m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
data.append(m_target->GetPackGUID());
data << (uint32)2;
m_target->SendMessageToSet(&data,true);
//Clear unit movement flags
m_target->SetUnitMovementFlags(0);
}
else
((Creature *)m_target)->StopMoving();
}
else
{
// Frost root aura -> freeze/unfreeze target
if (GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST)
{
bool found_another = false;
for(AuraType const* itr = &frozenAuraTypes[0]; *itr != SPELL_AURA_NONE; ++itr)
{
Unit::AuraList const& auras = m_target->GetAurasByType(*itr);
for(Unit::AuraList::const_iterator i = auras.begin(); i != auras.end(); ++i)
{
if( GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST)
{
found_another = true;
break;
}
}
if(found_another)
break;
}
if(!found_another)
m_target->ModifyAuraState(AURA_STATE_FROZEN, apply);
}
// Real remove called after current aura remove from lists, check if other similar auras active
if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
return;
m_target->clearUnitState(UNIT_STAT_ROOT);
// probably wrong (this add skinable flag)
// TODO: find correct flag
// m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
{
if(m_target->getVictim() && m_target->isAlive())
m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
data.append(m_target->GetPackGUID());
data << (uint32)2;
m_target->SendMessageToSet(&data,true);
}
}
}
}
void Aura::HandleAuraModSilence(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
if(apply)
{
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
// Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
{
Spell* currentSpell = m_target->m_currentSpells[i];
if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
{
uint32 state = currentSpell->getState();
// Stop spells on prepare or casting state
if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
{
currentSpell->cancel();
currentSpell->SetReferencedFromCurrent(false);
m_target->m_currentSpells[i] = NULL;
}
}
}
switch (GetId())
{
// Arcane Torrent (Energy)
case 25046:
{
Unit * caster = GetCaster();
if (!caster)
return;
// Search Mana Tap auras on caster
Aura * dummy = caster->GetDummyAura(28734);
if (dummy)
{
int32 bp = dummy->GetStackAmount() * 10;
caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true);
caster->RemoveAurasDueToSpell(28734);
}
}
}
}
else
{
// Real remove called after current aura remove from lists, check if other similar auras active
if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
return;
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
}
}
void Aura::HandleModThreat(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
if(!m_target->isAlive())
return;
Unit* caster = GetCaster();
if(!caster || !caster->isAlive())
return;
int level_diff = 0;
int multiplier = 0;
switch (GetId())
{
// Arcane Shroud
case 26400:
level_diff = m_target->getLevel() - 60;
multiplier = 2;
break;
// The Eye of Diminution
case 28862:
level_diff = m_target->getLevel() - 60;
multiplier = 1;
break;
}
if (level_diff > 0)
m_modifier.m_amount += multiplier * level_diff;
for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
{
if(m_modifier.m_miscvalue & int32(1<<x))
{
if(m_target->GetTypeId() == TYPEID_PLAYER)
ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
}
}
}
void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
return;
Unit* caster = GetCaster();
if(!caster || !caster->isAlive())
return;
float threatMod = 0.0f;
if(apply)
threatMod = float(m_modifier.m_amount);
else
threatMod = float(-m_modifier.m_amount);
m_target->getHostilRefManager().threatAssist(caster, threatMod);
}
void Aura::HandleModTaunt(bool apply, bool Real)
{
// only at real add/remove aura
if(!Real)
return;
if(!m_target->isAlive() || !m_target->CanHaveThreatList())
return;
Unit* caster = GetCaster();
if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
return;
if(apply)
m_target->TauntApply(caster);
else
{
// When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
m_target->TauntFadeOut(caster);
}
}
/*********************************************************/
/*** MODIFY SPEED ***/
/*********************************************************/
void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
m_target->UpdateSpeed(MOVE_RUN, true);
}
void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
m_target->UpdateSpeed(MOVE_RUN, true);
}
void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
// Enable Fly mode for flying mounts
if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
{
WorldPacket data;
if(apply)
data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
else
data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
data.append(m_target->GetPackGUID());
data << uint32(0); // unknown
m_target->SendMessageToSet(&data, true);
//Players on flying mounts must be immune to polymorph
if (m_target->GetTypeId()==TYPEID_PLAYER)
m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
// Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
}
m_target->UpdateSpeed(MOVE_FLIGHT, true);
}
void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
m_target->UpdateSpeed(MOVE_SWIM, true);
}
void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
m_target->UpdateSpeed(MOVE_RUN, true);
m_target->UpdateSpeed(MOVE_SWIM, true);
m_target->UpdateSpeed(MOVE_FLIGHT, true);
}
void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
m_target->UpdateSpeed(MOVE_RUN, true);
m_target->UpdateSpeed(MOVE_SWIM, true);
m_target->UpdateSpeed(MOVE_FLIGHT, true);
}
/*********************************************************/
/*** IMMUNITY ***/
/*********************************************************/
void Aura::HandleModMechanicImmunity(bool apply, bool Real)
{
uint32 mechanic = 1 << m_modifier.m_miscvalue;
//immune movement impairment and loss of control
if(GetId()==42292 || GetId()==59752)
mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
{
Unit::AuraMap& Auras = m_target->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
{
next = iter;
++next;
SpellEntry const *spell = iter->second->GetSpellProto();
if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) && // spells unaffected by invulnerability
spell->Id != GetId())
{
//check for mechanic mask
if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
{
m_target->RemoveAurasDueToSpell(spell->Id);
if(Auras.empty())
break;
else
next = Auras.begin();
}
}
}
}
m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
// Bestial Wrath
if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680)
{
// The Beast Within cast on owner if talent present
if ( Unit* owner = m_target->GetOwner() )
{
// Search talent
Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
{
if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
{
if (apply)
owner->CastSpell(owner, 34471, true, 0, this);
else
owner->RemoveAurasDueToSpell(34471);
break;
}
}
}
}
// The Beast Within and Bestial Wrath - immunity
if(GetId() == 19574 || GetId() == 34471)
{
if(apply)
{
m_target->CastSpell(m_target,24395,true);
m_target->CastSpell(m_target,24396,true);
m_target->CastSpell(m_target,24397,true);
m_target->CastSpell(m_target,26592,true);
}
else
{
m_target->RemoveAurasDueToSpell(24395);
m_target->RemoveAurasDueToSpell(24396);
m_target->RemoveAurasDueToSpell(24397);
m_target->RemoveAurasDueToSpell(26592);
}
}
}
void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
{
if(!apply)
{
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
if(((Player*)m_target)->InBattleGround())
{
BattleGround *bg = ((Player*)m_target)->GetBattleGround();
if(bg)
{
switch(bg->GetTypeID())
{
case BATTLEGROUND_AV:
{
break;
}
case BATTLEGROUND_WS:
{
// Warsong Flag, horde // Silverwing Flag, alliance
if(GetId() == 23333 || GetId() == 23335)
bg->EventPlayerDroppedFlag(((Player*)m_target));
break;
}
case BATTLEGROUND_AB:
{
break;
}
case BATTLEGROUND_EY:
{
if(GetId() == 34976)
bg->EventPlayerDroppedFlag(((Player*)m_target));
break;
}
}
}
}
}
}
m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
}
void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
{
if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
{
Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
{
if (auraList.front() != this) // skip itself aura (it already added)
{
m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
itr = auraList.begin();
}
else
++itr;
}
}
m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
}
void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
{
m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
{
if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
{
uint32 school_mask = m_modifier.m_miscvalue;
Unit::AuraMap& Auras = m_target->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
{
next = iter;
++next;
SpellEntry const *spell = iter->second->GetSpellProto();
if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
&& !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
&& !iter->second->IsPositive() //Don't remove positive spells
&& spell->Id != GetId() ) //Don't remove self
{
m_target->RemoveAurasDueToSpell(spell->Id);
if(Auras.empty())
break;
else
next = Auras.begin();
}
}
}
}
if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
{
if( apply )
m_target->addUnitState(UNIT_STAT_ISOLATED);
else
m_target->clearUnitState(UNIT_STAT_ISOLATED);
}
}
void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
{
m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
}
void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
}
void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
{
if(!Real)
return;
if(apply)
{
// some spell have charges by functionality not have its in spell data
switch (GetId())
{
case 28200: // Ascendance (Talisman of Ascendance trinket)
SetAuraCharges(6);
break;
default: break;
}
}
}
void Aura::HandleAuraModStalked(bool apply, bool Real)
{
// used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
if(apply)
m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
else
m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
}
/*********************************************************/
/*** PERIODIC ***/
/*********************************************************/
void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
{
m_isPeriodic = apply;
if (m_spellProto->Id == 66 && !apply)
{
if (m_removeMode == AURA_REMOVE_BY_DEFAULT && m_duration<=0)
m_target->CastSpell(m_target, 32612, true, NULL, this);
}
}
void Aura::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandlePeriodicEnergize(bool apply, bool Real)
{
if (!Real)
return;
m_isPeriodic = apply;
// Replenishment (0.25% from max)
// Infinite Replenishment
if (GetId() == 57669 ||
GetId() == 61782)
m_modifier.m_amount = m_target->GetMaxPower(POWER_MANA) * 25 / 10000;
}
void Aura::HandleAuraPowerBurn(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
// For prevent double apply bonuses
bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
Unit* caster = GetCaster();
SpellEntry const*spell = GetSpellProto();
switch( spell->SpellFamilyName)
{
case SPELLFAMILY_ROGUE:
{
// Master of Subtlety
if (spell->Id==31666 && !apply)
{
m_target->RemoveAurasDueToSpell(31665);
break;
}
break;
}
case SPELLFAMILY_HUNTER:
{
// Explosive Shot
if (apply && !loading && caster)
m_modifier.m_amount +=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
break;
}
}
m_isPeriodic = apply;
}
void Aura::HandlePeriodicHeal(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandlePeriodicDamage(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
m_isPeriodic = apply;
// For prevent double apply bonuses
bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
// Custom damage calculation after
if (!apply || loading)
return;
Unit *caster = GetCaster();
if (!caster)
return;
switch (m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
// Pounce Bleed
if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 )
{
// $AP*0.18/6 bonus per tick
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
return;
}
break;
}
case SPELLFAMILY_WARRIOR:
{
// Rend
if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
{
// $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 mws = caster->GetAttackTime(BASE_ATTACK);
float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f);
return;
}
break;
}
case SPELLFAMILY_DRUID:
{
// Rake
if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
{
// $AP*0.06 bonus per tick
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100);
return;
}
// Lacerate
if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
{
// $AP*0.05/5 bonus per tick
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
return;
}
// Rip
if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
{
// 0.01*$AP*cp
if (caster->GetTypeId() != TYPEID_PLAYER)
return;
uint8 cp = ((Player*)caster)->GetComboPoints();
// Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
{
if((*itr)->GetId()==34241)
{
m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
break;
}
}
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
return;
}
// Lock Jaw
if (m_spellProto->SpellFamilyFlags & 0x1000000000000000LL)
{
// 0.15*$AP
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 15 / 100);
return;
}
break;
}
case SPELLFAMILY_ROGUE:
{
// Rupture
if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
{
if (caster->GetTypeId() != TYPEID_PLAYER)
return;
//1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs
//2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs
//3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs
//4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs
//5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs
float AP_per_combo[] = {0, 0.015f, 0.024, 0.03, 0.03428571, 0.0375};
uint8 cp = ((Player*)caster)->GetComboPoints();
if (cp > 5) cp = 5;
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]);
return;
}
// Garrote
if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
{
// $AP*0.07 bonus per tick
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 7 / 100);
return;
}
// Deadly Poison
if (m_spellProto->SpellFamilyFlags & 0x0000000000010000)
{
// 0.08*$AP / 4 * amount of stack
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 * GetStackAmount() / 100);
return;
}
break;
}
case SPELLFAMILY_HUNTER:
{
// Serpent Sting
if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
{
// $RAP*0.1/5 bonus per tick
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
return;
}
// Immolation Trap
if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
{
// $RAP*0.1/5 bonus per tick
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
return;
}
break;
}
default:
break;
}
}
void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandlePeriodicLeech(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandlePeriodicHealthFunnel(bool apply, bool Real)
{
m_isPeriodic = apply;
}
/*********************************************************/
/*** MODIFY STATS ***/
/*********************************************************/
/********************************/
/*** RESISTANCE ***/
/********************************/
void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
{
for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
{
if(m_modifier.m_miscvalue & int32(1<<x))
{
m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER)
m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
}
}
}
void Aura::HandleAuraModResistance(bool apply, bool Real)
{
for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
{
if(m_modifier.m_miscvalue & int32(1<<x))
{
m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
}
}
}
void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
{
// only players have base stats
if(m_target->GetTypeId() != TYPEID_PLAYER)
{
//pets only have base armor
if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
}
else
{
for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
{
if(m_modifier.m_miscvalue & int32(1<<x))
m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
}
}
}
void Aura::HandleModResistancePercent(bool apply, bool Real)
{
for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
{
if(m_modifier.m_miscvalue & int32(1<<i))
{
m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
{
m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
}
}
}
}
void Aura::HandleModBaseResistance(bool apply, bool Real)
{
// only players have base stats
if(m_target->GetTypeId() != TYPEID_PLAYER)
{
//only pets have base stats
if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
else
{
for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
if(m_modifier.m_miscvalue & (1<<i))
m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
}
/********************************/
/*** STAT ***/
/********************************/
void Aura::HandleAuraModStat(bool apply, bool Real)
{
if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
{
sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
return;
}
for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
// -1 or -2 is all stats ( misc < -2 checked in function beginning )
if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
{
//m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
}
}
}
void Aura::HandleModPercentStat(bool apply, bool Real)
{
if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
{
sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
return;
}
// only players have base stats
if (m_target->GetTypeId() != TYPEID_PLAYER)
return;
for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
}
}
void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Magic damage modifiers implemented in Unit::SpellDamageBonus
// This information for client side use only
// Recalculate bonus
((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
}
void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Recalculate bonus
((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
}
void Aura::HandleAuraModDispelResist(bool apply, bool Real)
{
if(!Real || !apply)
return;
if(GetId()==33206)
m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
}
void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Magic damage modifiers implemented in Unit::SpellDamageBonus
// This information for client side use only
// Recalculate bonus
((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
}
void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Recalculate bonus
((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
}
void Aura::HandleModHealingDone(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
// implemented in Unit::SpellHealingBonus
// this information is for client side only
((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
}
void Aura::HandleModTotalPercentStat(bool apply, bool Real)
{
if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
{
sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
return;
}
//save current and max HP before applying aura
uint32 curHPValue = m_target->GetHealth();
uint32 maxHPValue = m_target->GetMaxHealth();
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
{
m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
}
}
//recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
{
// newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
m_target->SetHealth(newHPValue);
}
}
void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
{
// support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
// and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
return;
}
// Recalculate Armor
m_target->UpdateArmor();
}
/********************************/
/*** HEAL & ENERGIZE ***/
/********************************/
void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
{
if(m_modifier.periodictime == 0)
m_modifier.periodictime = 1000;
m_periodicTimer = m_modifier.periodictime;
m_isPeriodic = apply;
}
void Aura::HandleModRegen(bool apply, bool Real) // eating
{
if(m_modifier.periodictime == 0)
m_modifier.periodictime = 5000;
m_periodicTimer = 5000;
m_isPeriodic = apply;
}
void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
{
if (!Real)
return;
Powers pt = m_target->getPowerType();
if(m_modifier.periodictime == 0)
{
// Anger Management (only spell use this aura for rage)
if (pt == POWER_RAGE)
m_modifier.periodictime = 3000;
else
m_modifier.periodictime = 2000;
}
m_periodicTimer = 5000;
if (m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
((Player*)m_target)->UpdateManaRegen();
m_isPeriodic = apply;
}
void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if (m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Update manaregen value
if (m_modifier.m_miscvalue == POWER_MANA)
((Player*)m_target)->UpdateManaRegen();
}
void Aura::HandleModManaRegen(bool /*apply*/, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if (m_target->GetTypeId() != TYPEID_PLAYER)
return;
//Note: an increase in regen does NOT cause threat.
((Player*)m_target)->UpdateManaRegen();
}
void Aura::HandleComprehendLanguage(bool apply, bool Real)
{
if(apply)
m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
else
m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
}
void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
{
// Special case with temporary increase max/current health
switch(GetId())
{
case 12976: // Warrior Last Stand triggered spell
case 28726: // Nightmare Seed ( Nightmare Seed )
case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
{
if(Real)
{
if(apply)
{
m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
m_target->ModifyHealth(m_modifier.m_amount);
}
else
{
if (int32(m_target->GetHealth()) > m_modifier.m_amount)
m_target->ModifyHealth(-m_modifier.m_amount);
else
m_target->SetHealth(1);
m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
}
return;
}
}
// generic case
m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
{
uint32 oldhealth = m_target->GetHealth();
double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
// refresh percentage
if(oldhealth > 0)
{
uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
if(newhealth==0)
newhealth = 1;
m_target->SetHealth(newhealth);
}
}
void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
{
Powers powerType = m_target->getPowerType();
if(int32(powerType) != m_modifier.m_miscvalue)
return;
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/)
{
Powers powerType = m_target->getPowerType();
if(int32(powerType) != m_modifier.m_miscvalue)
return;
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/)
{
m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/)
{
m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_modifier.m_amount), apply);
}
/********************************/
/*** FIGHT ***/
/********************************/
void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
((Player*)m_target)->UpdateParryPercentage();
}
void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
((Player*)m_target)->UpdateDodgePercentage();
//sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
}
void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
((Player*)m_target)->UpdateBlockPercentage();
//sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
}
void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
((Player*)m_target)->UpdateManaRegen();
}
void Aura::HandleAuraModCritPercent(bool apply, bool Real)
{
if(m_target->GetTypeId()!=TYPEID_PLAYER)
return;
// apply item specific bonuses for already equipped weapon
if(Real)
{
for(int i = 0; i < MAX_ATTACK; ++i)
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
}
// mods must be applied base at equipped weapon class and subclass comparison
// with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
// m_modifier.m_miscvalue comparison with item generated damage types
if (GetSpellProto()->EquippedItemClass == -1)
{
((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
}
else
{
// done in Player::_ApplyWeaponDependentAuraMods
}
}
void Aura::HandleModHitChance(bool apply, bool Real)
{
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
((Player*)m_target)->UpdateMeleeHitChances();
((Player*)m_target)->UpdateRangedHitChances();
}
else
{
m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
}
}
void Aura::HandleModSpellHitChance(bool apply, bool Real)
{
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
((Player*)m_target)->UpdateSpellHitChances();
}
else
{
m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
}
}
void Aura::HandleModSpellCritChance(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
((Player*)m_target)->UpdateAllSpellCritChances();
}
else
{
m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
}
}
void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
if (m_modifier.m_miscvalue & (1<<school))
((Player*)m_target)->UpdateSpellCritChance(school);
}
/********************************/
/*** ATTACK SPEED ***/
/********************************/
void Aura::HandleModCastingSpeed(bool apply, bool Real)
{
m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
}
void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
{
m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
}
void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
{
m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
}
void Aura::HandleModAttackSpeed(bool apply, bool Real)
{
if(!m_target->isAlive() )
return;
m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
}
void Aura::HandleHaste(bool apply, bool Real)
{
m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
}
void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
{
m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
}
void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
}
/********************************/
/*** ATTACK POWER ***/
/********************************/
void Aura::HandleAuraModAttackPower(bool apply, bool Real)
{
m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
{
if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
return;
m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
{
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
{
if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
return;
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
// Recalculate bonus
if(m_target->GetTypeId() == TYPEID_PLAYER && !(m_target->getClassMask() & CLASSMASK_WAND_USERS))
((Player*)m_target)->UpdateAttackPowerAndDamage(true);
}
void Aura::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
// Recalculate bonus
if(m_target->GetTypeId() == TYPEID_PLAYER)
((Player*)m_target)->UpdateAttackPowerAndDamage(false);
}
/********************************/
/*** DAMAGE BONUS ***/
/********************************/
void Aura::HandleModDamageDone(bool apply, bool Real)
{
// apply item specific bonuses for already equipped weapon
if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
{
for(int i = 0; i < MAX_ATTACK; ++i)
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
}
// m_modifier.m_miscvalue is bitmask of spell schools
// 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
// 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
// 127 - full bitmask any damages
//
// mods must be applied base at equipped weapon class and subclass comparison
// with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
// m_modifier.m_miscvalue comparison with item generated damage types
if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
{
// apply generic physical damage bonuses including wand case
if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
{
m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}
else
{
// done in Player::_ApplyWeaponDependentAuraMods
}
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
if(m_positive)
m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
else
m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
}
}
// Skip non magic case for speedup
if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
return;
if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
{
// wand magic case (skip generic to all item spell bonuses)
// done in Player::_ApplyWeaponDependentAuraMods
// Skip item specific requirements for not wand magic damage
return;
}
// Magic damage modifiers implemented in Unit::SpellDamageBonus
// This information for client side use only
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
if(m_positive)
{
for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
{
if((m_modifier.m_miscvalue & (1<<i)) != 0)
m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
}
}
else
{
for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
{
if((m_modifier.m_miscvalue & (1<<i)) != 0)
m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
}
}
Pet* pet = m_target->GetPet();
if(pet)
pet->UpdateAttackPowerAndDamage();
}
}
void Aura::HandleModDamagePercentDone(bool apply, bool Real)
{
sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
// apply item specific bonuses for already equipped weapon
if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
{
for(int i = 0; i < MAX_ATTACK; ++i)
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
}
// m_modifier.m_miscvalue is bitmask of spell schools
// 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
// 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
// 127 - full bitmask any damages
//
// mods must be applied base at equipped weapon class and subclass comparison
// with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
// m_modifier.m_miscvalue comparison with item generated damage types
if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
{
// apply generic physical damage bonuses including wand case
if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
{
m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
else
{
// done in Player::_ApplyWeaponDependentAuraMods
}
// For show in client
if(m_target->GetTypeId() == TYPEID_PLAYER)
m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
}
// Skip non magic case for speedup
if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
return;
if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
{
// wand magic case (skip generic to all item spell bonuses)
// done in Player::_ApplyWeaponDependentAuraMods
// Skip item specific requirements for not wand magic damage
return;
}
// Magic damage percent modifiers implemented in Unit::SpellDamageBonus
// Send info to client
if(m_target->GetTypeId() == TYPEID_PLAYER)
for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
}
void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
sLog.outDebug("AURA MOD OFFHAND DAMAGE");
m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
}
/********************************/
/*** POWER COST ***/
/********************************/
void Aura::HandleModPowerCostPCT(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
float amount = m_modifier.m_amount/100.0f;
for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
if(m_modifier.m_miscvalue & (1<<i))
m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
}
void Aura::HandleModPowerCost(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
if(m_modifier.m_miscvalue & (1<<i))
m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
}
void Aura::HandleNoReagentUseAura(bool Apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
uint32 mask[3] = {0, 0, 0};
Unit::AuraList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE);
for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
{
uint32 const *ptr = (*i)->getAuraSpellClassMask();
mask[0]|=ptr[0];
mask[1]|=ptr[1];
mask[2]|=ptr[2];
}
m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]);
m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]);
m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]);
}
/*********************************************************/
/*** OTHERS ***/
/*********************************************************/
void Aura::HandleShapeshiftBoosts(bool apply)
{
uint32 spellId = 0;
uint32 spellId2 = 0;
uint32 HotWSpellId = 0;
switch(GetModifier()->m_miscvalue)
{
case FORM_CAT:
spellId = 3025;
HotWSpellId = 24900;
break;
case FORM_TREE:
spellId = 5420;
spellId2 = 34123;
break;
case FORM_TRAVEL:
spellId = 5419;
break;
case FORM_AQUA:
spellId = 5421;
break;
case FORM_BEAR:
spellId = 1178;
spellId2 = 21178;
HotWSpellId = 24899;
break;
case FORM_DIREBEAR:
spellId = 9635;
spellId2 = 21178;
HotWSpellId = 24899;
break;
case FORM_BATTLESTANCE:
spellId = 21156;
break;
case FORM_DEFENSIVESTANCE:
spellId = 7376;
break;
case FORM_BERSERKERSTANCE:
spellId = 7381;
break;
case FORM_MOONKIN:
spellId = 24905;
// aura from effect trigger spell
spellId2 = 24907;
break;
case FORM_FLIGHT:
spellId = 33948;
spellId2 = 34764;
break;
case FORM_FLIGHT_EPIC:
spellId = 40122;
spellId2 = 40121;
break;
case FORM_METAMORPHOSIS:
spellId = 54817;
spellId2 = 54879;
break;
case FORM_SPIRITOFREDEMPTION:
spellId = 27792;
spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
break;
case FORM_GHOSTWOLF:
case FORM_AMBIENT:
case FORM_GHOUL:
case FORM_SHADOW:
case FORM_STEALTH:
case FORM_CREATURECAT:
case FORM_CREATUREBEAR:
spellId = 0;
break;
}
uint32 form = GetModifier()->m_miscvalue-1;
if(apply)
{
if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if(itr->second->state == PLAYERSPELL_REMOVED) continue;
if(itr->first==spellId || itr->first==spellId2) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue;
if (spellInfo->Stances & (1<<form))
m_target->CastSpell(m_target, itr->first, true, NULL, this);
}
//LotP
if (((Player*)m_target)->HasSpell(17007))
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
if (spellInfo && spellInfo->Stances & (1<<form))
m_target->CastSpell(m_target, 24932, true, NULL, this);
}
// HotW
if (HotWSpellId)
{
Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
{
if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
{
int32 HotWMod = (*i)->GetModifier()->m_amount;
if(GetModifier()->m_miscvalue == FORM_CAT)
HotWMod /= 2;
m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
break;
}
}
}
}
}
else
{
m_target->RemoveAurasDueToSpell(spellId);
m_target->RemoveAurasDueToSpell(spellId2);
Unit::AuraMap& tAuras = m_target->GetAuras();
for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
if (itr->second->IsRemovedOnShapeLost())
{
m_target->RemoveAurasDueToSpell(itr->second->GetId());
itr = tAuras.begin();
}
else
{
++itr;
}
}
}
/*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
}
void Aura::HandleAuraEmpathy(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_UNIT)
return;
CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
if(ci && ci->type == CREATURE_TYPE_BEAST)
m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
}
void Aura::HandleAuraUntrackable(bool apply, bool Real)
{
if(apply)
m_target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
else
m_target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
}
void Aura::HandleAuraModPacify(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
if(apply)
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
else
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
}
void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
{
HandleAuraModPacify(apply,Real);
HandleAuraModSilence(apply,Real);
}
void Aura::HandleAuraGhost(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
if(apply)
{
m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
}
else
{
m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
}
}
void Aura::HandleAuraAllowFlight(bool apply, bool Real)
{
// all applied/removed only at real aura add/remove
if(!Real)
return;
// allow fly
WorldPacket data;
if(apply)
data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
else
data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
data.append(m_target->GetPackGUID());
data << uint32(0); // unk
m_target->SendMessageToSet(&data, true);
}
void Aura::HandleModRating(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (m_modifier.m_miscvalue & (1 << rating))
((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
}
void Aura::HandleModRatingFromStat(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Just recalculate ratings
for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (m_modifier.m_miscvalue & (1 << rating))
((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply);
}
void Aura::HandleForceMoveForward(bool apply, bool Real)
{
if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
return;
if(apply)
m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
else
m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
}
void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
}
void Aura::HandleModTargetResistance(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
// applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
// show armor penetration
if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
// show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
}
void Aura::HandleShieldBlockValue(bool apply, bool Real)
{
BaseModType modType = FLAT_MOD;
if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
modType = PCT_MOD;
if(m_target->GetTypeId() == TYPEID_PLAYER)
((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
}
void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
Player *target = (Player*)m_target;
// combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
// remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
if( !apply && m_duration==0 && target->GetComboTarget())
if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
target->AddComboPoints(unit, -m_modifier.m_amount);
}
void Aura::HandleModUnattackable( bool Apply, bool Real )
{
if(Real && Apply)
m_target->CombatStop();
m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
}
void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
{
// spells required only Real aura add/remove
if(!Real)
return;
// prepare spirit state
if(apply)
{
if(m_target->GetTypeId()==TYPEID_PLAYER)
{
// disable breath/etc timers
((Player*)m_target)->StopMirrorTimers();
// set stand state (expected in this form)
if(!m_target->IsStandState())
m_target->SetStandState(UNIT_STAND_STATE_STAND);
}
m_target->SetHealth(1);
}
// die at aura end
else
m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
}
void Aura::CleanupTriggeredSpells()
{
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0000001000000020LL)
{
// Blood Frenzy remove
m_target->RemoveAurasDueToSpell(30069);
m_target->RemoveAurasDueToSpell(30070);
return;
}
uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
if(!tSpellId)
return;
SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
if(!tProto)
return;
if(GetSpellDuration(tProto) != -1)
return;
// needed for spell 43680, maybe others
// TODO: is there a spell flag, which can solve this in a more sophisticated way?
if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
return;
m_target->RemoveAurasDueToSpell(tSpellId);
}
void Aura::HandleSchoolAbsorb(bool apply, bool Real)
{
if(!Real)
return;
// prevent double apply bonuses
if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
{
if(Unit* caster = GetCaster())
{
float DoneActualBenefit = 0.0f;
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_PRIEST:
if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
{
//+30% from +healing bonus
DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
break;
}
break;
case SPELLFAMILY_MAGE:
if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
{
//frost ward, fire ward, ice barrier
//+10% from +spd bonus
DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
break;
}
break;
case SPELLFAMILY_WARLOCK:
if(m_spellProto->SpellFamilyFlags == 0x00)
{
//shadow ward
//+10% from +spd bonus
DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
break;
}
break;
default:
break;
}
DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
m_modifier.m_amount += (int32)DoneActualBenefit;
}
}
}
void Aura::PeriodicTick()
{
if(!m_target->isAlive())
return;
switch(m_modifier.m_auraname)
{
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
{
Unit *pCaster = GetCaster();
if(!pCaster)
return;
if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
return;
// Check for immune (not use charges)
if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
return;
// some auras remove at specific health level or more
if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
{
switch(GetId())
{
case 43093: case 31956: case 38801:
case 35321: case 38363: case 39215:
if(m_target->GetHealth() == m_target->GetMaxHealth() )
{
m_target->RemoveAurasDueToSpell(GetId());
return;
}
break;
case 38772:
{
uint32 percent =
GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
100;
if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
{
m_target->RemoveAurasDueToSpell(GetId());
return;
}
break;
}
default:
break;
}
}
uint32 absorb=0;
uint32 resist=0;
CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
// ignore non positive values (can be result apply spellmods to aura damage
uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
uint32 pdamage;
if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
{
pdamage = amount;
// Calculate armor mitigation if it is a physical spell
// But not for bleed mechanic spells
if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
{
uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
cleanDamage.damage += pdamage - pdamageReductedArmor;
pdamage = pdamageReductedArmor;
}
pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
// Curse of Agony damage-per-tick calculation
if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
{
// 1..4 ticks, 1/2 from normal tick damage
if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
pdamage = pdamage/2;
// 9..12 ticks, 3/2 from normal tick damage
else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
// 5..8 ticks have normal tick damage
}
}
else
pdamage = uint32(m_target->GetMaxHealth()*amount/100);
//As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
// Reduce dot damage from resilience for players
if (m_target->GetTypeId()==TYPEID_PLAYER)
pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
data.append(m_target->GetPackGUID());
data.appendPackGUID(GetCasterGUID());
data << uint32(GetId());
data << uint32(1);
data << uint32(m_modifier.m_auraname);
data << (uint32)pdamage;
data << uint32(0); // overkill
data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
data << (uint32)absorb;
data << (uint32)resist;
m_target->SendMessageToSet(&data,true);
Unit* target = m_target; // aura can be deleted in DealDamage
SpellEntry const* spellProto = GetSpellProto();
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
if (pdamage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true);
break;
}
case SPELL_AURA_PERIODIC_LEECH:
case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
{
Unit *pCaster = GetCaster();
if(!pCaster)
return;
if(!pCaster->isAlive())
return;
if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
return;
// Check for immune
if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
return;
uint32 absorb=0;
uint32 resist=0;
CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
//Calculate armor mitigation if it is a physical spell
if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
{
uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
cleanDamage.damage += pdamage - pdamageReductedArmor;
pdamage = pdamageReductedArmor;
}
pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
//As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
// Reduce dot damage from resilience for players
if (m_target->GetTypeId()==TYPEID_PLAYER)
pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
if(m_target->GetHealth() < pdamage)
pdamage = uint32(m_target->GetHealth());
sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
Unit* target = m_target; // aura can be deleted in DealDamage
SpellEntry const* spellProto = GetSpellProto();
float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
int32 stackAmount = GetStackAmount();
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist);
if (pdamage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false);
if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
{
for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
{
if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
pCaster->m_currentSpells[i]->cancel();
}
}
if(Player *modOwner = pCaster->GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
uint32 heal = pCaster->SpellHealingBonus(pCaster, spellProto, uint32(new_damage * multiplier), DOT, stackAmount);
int32 gain = pCaster->ModifyHealth(heal);
pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
break;
}
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_OBS_MOD_HEALTH:
{
Unit *pCaster = GetCaster();
if(!pCaster)
return;
// heal for caster damage (must be alive)
if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive())
return;
// ignore non positive values (can be result apply spellmods to aura damage
uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
uint32 pdamage;
if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
pdamage = uint32(m_target->GetMaxHealth() * amount/100);
else
pdamage = amount;
pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
data.append(m_target->GetPackGUID());
data.appendPackGUID(GetCasterGUID());
data << uint32(GetId());
data << uint32(1);
data << uint32(m_modifier.m_auraname);
data << (uint32)pdamage;
data << uint32(0); // wotlk
m_target->SendMessageToSet(&data,true);
int32 gain = m_target->ModifyHealth(pdamage);
// add HoTs to amount healed in bgs
if( pCaster->GetTypeId() == TYPEID_PLAYER )
if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
//Do check before because m_modifier.auraName can be invalidate by DealDamage.
bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
Unit* target = m_target; // aura can be deleted in DealDamage
SpellEntry const* spellProto = GetSpellProto();
bool haveCastItem = GetCastItemGUID()!=0;
// heal for caster damage
if(m_target!=pCaster && spellProto->SpellVisual[0]==163)
{
uint32 dmg = spellProto->manaPerSecond;
if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
{
pCaster->RemoveAurasDueToSpell(GetId());
// finish current generic/channeling spells, don't affect autorepeat
if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
{
pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
}
if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
{
pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
}
}
else
{
pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
}
}
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HEAL;
uint32 procVictim = 0;//ROC_FLAG_ON_TAKE_PERIODIC | PROC_FLAG_TAKEN_HEAL;
// ignore item heals
// if(procSpell && !haveCastItem)
// pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
break;
}
case SPELL_AURA_PERIODIC_MANA_LEECH:
{
Unit *pCaster = GetCaster();
if(!pCaster)
return;
if(!pCaster->isAlive())
return;
if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
return;
// Check for immune (not use charges)
if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
return;
// ignore non positive values (can be result apply spellmods to aura damage
uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
break;
Powers power = Powers(m_modifier.m_miscvalue);
// power type might have changed between aura applying and tick (druid's shapeshift)
if(m_target->getPowerType() != power)
break;
int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
m_target->ModifyPower(power, -drain_amount);
float gain_multiplier = 0;
if(pCaster->GetMaxPower(power) > 0)
{
gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
if(Player *modOwner = pCaster->GetSpellModOwner())
modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
}
WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
data.append(m_target->GetPackGUID());
data.appendPackGUID(GetCasterGUID());
data << uint32(GetId());
data << uint32(1);
data << uint32(m_modifier.m_auraname);
data << (uint32)power; // power type
data << (uint32)drain_amount;
data << (float)gain_multiplier;
m_target->SendMessageToSet(&data,true);
int32 gain_amount = int32(drain_amount*gain_multiplier);
if(gain_amount)
{
int32 gain = pCaster->ModifyPower(power,gain_amount);
m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
}
break;
}
case SPELL_AURA_PERIODIC_ENERGIZE:
{
// ignore non positive values (can be result apply spellmods to aura damage
uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
break;
Powers power = Powers(m_modifier.m_miscvalue);
if(m_target->GetMaxPower(power) == 0)
break;
WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
data.append(m_target->GetPackGUID());
data.appendPackGUID(GetCasterGUID());
data << uint32(GetId());
data << uint32(1);
data << uint32(m_modifier.m_auraname);
data << (uint32)power; // power type
data << (uint32)pdamage;
m_target->SendMessageToSet(&data,true);
int32 gain = m_target->ModifyPower(power,pdamage);
if(Unit* pCaster = GetCaster())
m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_OBS_MOD_MANA:
{
// ignore non positive values (can be result apply spellmods to aura damage
uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
if(m_target->GetMaxPower(POWER_MANA) == 0)
break;
WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
data.append(m_target->GetPackGUID());
data.appendPackGUID(GetCasterGUID());
data << uint32(GetId());
data << uint32(1);
data << uint32(m_modifier.m_auraname);
data << (uint32)0; // ?
data << (uint32)pdamage;
m_target->SendMessageToSet(&data,true);
int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
if(Unit* pCaster = GetCaster())
m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_POWER_BURN_MANA:
{
Unit *pCaster = GetCaster();
if(!pCaster)
return;
// Check for immune (not use charges)
if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
return;
int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
Powers powerType = Powers(m_modifier.m_miscvalue);
if(!m_target->isAlive() || m_target->getPowerType() != powerType)
return;
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
SpellEntry const* spellProto = GetSpellProto();
//maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask);
pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto);
pCaster->SendSpellNonMeleeDamageLog(&damageInfo);
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE);
if (damageInfo.damage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
pCaster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);
pCaster->DealSpellDamage(&damageInfo, true);
break;
}
case SPELL_AURA_MOD_REGEN:
{
int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
if (Unit *caster = GetCaster())
m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_MOD_POWER_REGEN:
{
Powers pt = m_target->getPowerType();
if(int32(pt) != m_modifier.m_miscvalue)
return;
if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
{
// eating anim
m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
}
else if( GetId() == 20577 )
{
// cannibalize anim
m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE);
}
// Anger Management
// amount = 1+ 16 = 17 = 3,4*5 = 10,2*5/3
// so 17 is rounded amount for 5 sec tick grow ~ 1 range grow in 3 sec
if(pt == POWER_RAGE)
m_target->ModifyPower(pt, m_modifier.m_amount*3/5);
break;
}
// Here tick dummy auras
case SPELL_AURA_PERIODIC_DUMMY:
{
PeriodicDummyTick();
break;
}
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
{
TriggerSpell();
break;
}
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
{
TriggerSpellWithValue();
break;
}
default:
break;
}
}
void Aura::PeriodicDummyTick()
{
Unit *caster = GetCaster();
SpellEntry const* spell = GetSpellProto();
switch (spell->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
switch (spell->Id)
{
// Drink
case 430:
case 431:
case 432:
case 1133:
case 1135:
case 1137:
case 10250:
case 22734:
case 27089:
case 34291:
case 43706:
case 46755:
case 49472: // Drink Coffee
case 61830:
{
if (m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
{
if ((*i)->GetId() == GetId())
{
(*i)->GetModifier()->m_amount = m_modifier.m_amount;
((Player*)m_target)->UpdateManaRegen();
// Disable continue
m_isPeriodic = false;
return;
}
}
return;
}
// Forsaken Skills
case 7054:
{
// Possibly need cast one of them (but
// 7038 Forsaken Skill: Swords
// 7039 Forsaken Skill: Axes
// 7040 Forsaken Skill: Daggers
// 7041 Forsaken Skill: Maces
// 7042 Forsaken Skill: Staves
// 7043 Forsaken Skill: Bows
// 7044 Forsaken Skill: Guns
// 7045 Forsaken Skill: 2H Axes
// 7046 Forsaken Skill: 2H Maces
// 7047 Forsaken Skill: 2H Swords
// 7048 Forsaken Skill: Defense
// 7049 Forsaken Skill: Fire
// 7050 Forsaken Skill: Frost
// 7051 Forsaken Skill: Holy
// 7053 Forsaken Skill: Shadow
return;
}
// // Panda
// case 19230: break;
// // Gossip NPC Periodic - Talk
// case 33208: break;
// // Gossip NPC Periodic - Despawn
// case 33209: break;
// // Steal Weapon
// case 36207: break;
// // Simon Game START timer, (DND)
// case 39993: break;
// // Knockdown Fel Cannon: break; The Aggro Burst
// case 40119: break;
// // Old Mount Spell
// case 40154: break;
// // Magnetic Pull
// case 40581: break;
// // Ethereal Ring: break; The Bolt Burst
// case 40801: break;
// // Crystal Prison
// case 40846: break;
// // Copy Weapon
// case 41054: break;
// // Dementia
// case 41404: break;
// // Ethereal Ring Visual, Lightning Aura
// case 41477: break;
// // Ethereal Ring Visual, Lightning Aura (Fork)
// case 41525: break;
// // Ethereal Ring Visual, Lightning Jumper Aura
// case 41567: break;
// // No Man's Land
// case 41955: break;
// // Headless Horseman - Fire
// case 42074: break;
// // Headless Horseman - Visual - Large Fire
// case 42075: break;
// // Headless Horseman - Start Fire, Periodic Aura
// case 42140: break;
// // Ram Speed Boost
// case 42152: break;
// // Headless Horseman - Fires Out Victory Aura
// case 42235: break;
// // Pumpkin Life Cycle
// case 42280: break;
// // Brewfest Request Chick Chuck Mug Aura
// case 42537: break;
// // Squashling
// case 42596: break;
// // Headless Horseman Climax, Head: Periodic
// case 42603: break;
// // Fire Bomb
// case 42621: break;
// // Headless Horseman - Conflagrate, Periodic Aura
// case 42637: break;
// // Headless Horseman - Create Pumpkin Treats Aura
// case 42774: break;
// // Headless Horseman Climax - Summoning Rhyme Aura
// case 42879: break;
// // Tricky Treat
// case 42919: break;
// // Giddyup!
// case 42924: break;
// // Ram - Trot
// case 42992: break;
// // Ram - Canter
// case 42993: break;
// // Ram - Gallop
// case 42994: break;
// // Ram Level - Neutral
// case 43310: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
// case 43884: break;
// // Wretched!
// case 43963: break;
// // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
// case 44000: break;
// // Energy Feedback
// case 44328: break;
// // Romantic Picnic
// case 45102: break;
// // Romantic Picnic
// case 45123: break;
// // Looking for Love
// case 45124: break;
// // Kite - Lightning Strike Kite Aura
// case 45197: break;
// // Rocket Chicken
// case 45202: break;
// // Copy Offhand Weapon
// case 45205: break;
// // Upper Deck - Kite - Lightning Periodic Aura
// case 45207: break;
// // Kite -Sky Lightning Strike Kite Aura
// case 45251: break;
// // Ribbon Pole Dancer Check Aura
// case 45390: break;
// // Holiday - Midsummer, Ribbon Pole Periodic Visual
// case 45406: break;
// // Parachute
// case 45472: break;
// // Alliance Flag, Extra Damage Debuff
// case 45898: break;
// // Horde Flag, Extra Damage Debuff
// case 45899: break;
// // Ahune - Summoning Rhyme Aura
// case 45926: break;
// // Ahune - Slippery Floor
// case 45945: break;
// // Ahune's Shield
// case 45954: break;
// // Nether Vapor Lightning
// case 45960: break;
// // Darkness
// case 45996: break;
// // Summon Blood Elves Periodic
// case 46041: break;
// // Transform Visual Missile Periodic
// case 46205: break;
// // Find Opening Beam End
// case 46333: break;
// // Ice Spear Control Aura
// case 46371: break;
// // Hailstone Chill
// case 46458: break;
// // Hailstone Chill, Internal
// case 46465: break;
// // Chill, Internal Shifter
// case 46549: break;
// // Summon Ice Spear Knockback Delayer
// case 46878: break;
// // Burninate Effect
// case 47214: break;
// // Fizzcrank Practice Parachute
// case 47228: break;
// // Send Mug Control Aura
// case 47369: break;
// // Direbrew's Disarm (precast)
// case 47407: break;
// // Mole Machine Port Schedule
// case 47489: break;
// case 47941: break; // Crystal Spike
// case 48200: break; // Healer Aura
// case 48630: break; // Summon Gauntlet Mobs Periodic
// case 49313: break; // Proximity Mine Area Aura
// // Mole Machine Portal Schedule
// case 49466: break;
// case 49555: break; // Corpse Explode
// case 49592: break; // Temporal Rift
// case 49957: break; // Cutting Laser
// case 50085: break; // Slow Fall
// // Listening to Music
// case 50493: break;
// // Love Rocket Barrage
// case 50530: break;
// Exist more after, need add later
default:
break;
}
break;
case SPELLFAMILY_MAGE:
{
// Mirror Image
// if (spell->Id == 55342)
// return;
break;
}
case SPELLFAMILY_WARRIOR:
{
// Armored to the Teeth
if (spell->SpellIconID == 3516)
{
// Increases your attack power by $s1 for every $s2 armor value you have.
// Calculate AP bonus (from 1 efect of this spell)
int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
return;
}
break;
}
case SPELLFAMILY_DRUID:
{
switch (spell->Id)
{
// Frenzied Regeneration
case 22842:
{
// Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
// Should be manauser
if (m_target->getPowerType()!=POWER_RAGE)
return;
uint32 rage = m_target->GetPower(POWER_RAGE);
// Nothing todo
if (rage == 0)
return;
int32 mod = (rage < 100) ? rage : 100;
int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000;
m_target->CastCustomSpell(m_target, 22845, &regen, 0, 0, true, 0, this);
m_target->SetPower(POWER_RAGE, rage-mod);
return;
}
// Force of Nature
case 33831:
return;
default:
break;
}
break;
}
case SPELLFAMILY_ROGUE:
{
// switch (spell->Id)
// {
// Master of Subtlety
// case 31666: break;
// Killing Spree
// case 51690: break;
// Overkill
// case 58428: break;
// default:
// break;
// }
break;
}
case SPELLFAMILY_HUNTER:
{
// Explosive Shot
if (spell->SpellFamilyFlags & 0x8000000000000000LL)
{
if (!caster)
return;
int32 damage = m_modifier.m_amount;
// Full damage to target at 0 tick
if (m_duration > m_modifier.periodictime)
{
caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this);
return;
}
damage/=4;
caster->CastCustomSpell(m_target, 56298, &damage, 0, 0, true, 0, this);
return;
}
switch (spell->Id)
{
// Harpooner's Mark
// case 40084:
// return;
// Feeding Frenzy Rank 1
case 53511:
if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
m_target->CastSpell(m_target, 60096, true, 0, this);
return;
// Feeding Frenzy Rank 2
case 53512:
if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 )
m_target->CastSpell(m_target, 60097, true, 0, this);
return;
default:
break;
}
break;
}
case SPELLFAMILY_SHAMAN:
{
// Astral Shift
if (spell->Id == 52179)
{
// Periodic need for remove visual on stun/fear/silence lost
if (!(m_target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)))
m_target->RemoveAurasDueToSpell(52179);
return;
}
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
// Death and Decay
if (spell->SpellFamilyFlags & 0x0000000000000020LL)
{
if (caster)
caster->CastCustomSpell(m_target, 52212, &m_modifier.m_amount, NULL, NULL, true, 0, this);
return;
}
// Raise Dead
// if (spell->SpellFamilyFlags & 0x0000000000001000LL)
// return;
// Chains of Ice
if (spell->SpellFamilyFlags & 0x0000400000000000LL)
{
// Get 0 effect aura
Aura *slow = m_target->GetAura(GetId(), 0);
if (slow)
{
slow->ApplyModifier(false, true);
Modifier *mod = slow->GetModifier();
mod->m_amount+= m_modifier.m_amount;
if (mod->m_amount > 0) mod->m_amount = 0;
slow->ApplyModifier(true, true);
}
return;
}
// Summon Gargoyle
// if (spell->SpellFamilyFlags & 0x0000008000000000LL)
// return;
// Death Rune Mastery
// if (spell->SpellFamilyFlags & 0x0000000000004000LL)
// return;
// Bladed Armor
if (spell->SpellIconID == 2653)
{
// Increases your attack power by $s1 for every $s2 armor value you have.
// Calculate AP bonus (from 1 efect of this spell)
int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target);
m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this);
return;
}
// Reaping
// if (spell->SpellIconID == 22)
// return;
// Blood of the North
// if (spell->SpellIconID == 30412)
// return;
break;
}
default:
break;
}
}
void Aura::HandlePreventFleeing(bool apply, bool Real)
{
if(!Real)
return;
Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
if( !fearAuras.empty() )
{
if (apply)
m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
else
m_target->SetFeared(true);
}
}
void Aura::HandleManaShield(bool apply, bool Real)
{
if(!Real)
return;
// prevent double apply bonuses
if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
{
if(Unit* caster = GetCaster())
{
float DoneActualBenefit = 0.0f;
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_MAGE:
if(m_spellProto->SpellFamilyFlags & 0x8000)
{
// Mana Shield
// +50% from +spd bonus
DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
break;
}
break;
default:
break;
}
DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
m_modifier.m_amount += (int32)DoneActualBenefit;
}
}
}
void Aura::HandleArenaPreparation(bool apply, bool Real)
{
if(!Real)
return;
if(apply)
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
else
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
}
void Aura::HandleAuraControlVehicle(bool apply, bool Real)
{
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
if(Pet *pet = m_target->GetPet())
pet->Remove(PET_SAVE_AS_CURRENT);
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
((Player*)m_target)->GetSession()->SendPacket(&data);
}
void Aura::HandleAuraConvertRune(bool apply, bool Real)
{
if(!Real)
return;
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
Player *plr = (Player*)m_target;
if(plr->getClass() != CLASS_DEATH_KNIGHT)
return;
// how to determine what rune need to be converted?
for(uint32 i = 0; i < MAX_RUNES; ++i)
{
if(apply)
{
if(!plr->GetRuneCooldown(i))
{
plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]);
break;
}
}
else
{
if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex])
{
plr->ConvertRune(i, plr->GetBaseRune(i));
break;
}
}
}
}
void Aura::HandlePhase(bool apply, bool Real)
{
if(!Real)
return;
// always non stackable
if(apply)
{
Unit::AuraList const& phases = m_target->GetAurasByType(SPELL_AURA_PHASE);
if(!phases.empty())
m_target->RemoveAurasDueToSpell(phases.front()->GetId(),this);
}
// no-phase is also phase state so same code for apply and remove
// phase auras normally not expected at BG but anyway better check
if(m_target->GetTypeId()==TYPEID_PLAYER)
{
// drop flag at invisible in bg
if(((Player*)m_target)->InBattleGround())
if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
bg->EventPlayerDroppedFlag((Player*)m_target);
// GM-mode have mask 0xFFFFFFFF
if(!((Player*)m_target)->isGameMaster())
m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false);
((Player*)m_target)->GetSession()->SendSetPhaseShift(apply ? GetMiscValue() : PHASEMASK_NORMAL);
}
else
m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false);
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
if(m_target->GetVisibility()!=VISIBILITY_OFF)
m_target->SetVisibility(m_target->GetVisibility());
}